From d6572e679fe320d10f31955e9ff3ecbcc5ee7da4 Mon Sep 17 00:00:00 2001 From: CN_SZTL Date: Tue, 2 Jul 2019 19:05:14 +0800 Subject: [PATCH] resolve package problems --- package/jsda/gargoyle-firewall-util/Makefile | 71 - .../files/gargoyle_additions.firewall | 2 - .../files/gargoyle_firewall.hotplug | 42 - .../files/gargoyle_firewall_util.sh | 585 -------- .../files/modemaccess.pppoe | 49 - .../files/set_kernel_timezone.init | 20 - .../jsda/gargoyle-firewall-util/src/Makefile | 19 - .../src/backup_quotas.c | 217 --- .../src/delete_chain_from_table.c | 76 - .../src/make_iptables_rules.c | 984 ------------- .../gargoyle-firewall-util/src/print_quotas.c | 410 ------ .../src/restore_quotas.c | 1071 -------------- package/jsda/libericstools/Makefile | 54 - package/jsda/libericstools/src/Makefile | 78 - package/jsda/libericstools/src/erics_tools.h | 276 ---- package/jsda/libericstools/src/file_util.c | 189 --- package/jsda/libericstools/src/list.c | 277 ---- .../jsda/libericstools/src/priority_queue.c | 350 ----- package/jsda/libericstools/src/safe_malloc.c | 80 -- package/jsda/libericstools/src/string_util.c | 669 --------- .../libericstools/src/test_list_and_queue.c | 85 -- package/jsda/libericstools/src/test_map.c | 322 ----- package/jsda/libericstools/src/test_string.c | 25 - package/jsda/libericstools/src/tree_map.c | 884 ------------ package/jsda/libiptbwctl/Makefile | 74 - package/jsda/libiptbwctl/src/Makefile | 60 - package/jsda/libiptbwctl/src/ipt_bwctl.c | 1279 ----------------- package/jsda/libiptbwctl/src/ipt_bwctl.h | 147 -- .../libiptbwctl/src/ipt_bwctl_safe_malloc.c | 23 - package/jsda/libiptbwctl/src/utils/Makefile | 12 - package/jsda/libiptbwctl/src/utils/bw_get.c | 175 --- .../src/utils/bw_print_history_file.c | 37 - package/jsda/libiptbwctl/src/utils/bw_set.c | 184 --- .../src/utils/set_kernel_timezone.c | 27 - package/jsda/luci-app-qos-gargoyle/LICENSE | 201 --- package/jsda/luci-app-qos-gargoyle/Makefile | 31 - package/jsda/luci-app-qos-gargoyle/README.md | 5 - .../luasrc/controller/qos_gargoyle.lua | 100 -- .../model/cbi/qos_gargoyle/download.lua | 166 --- .../model/cbi/qos_gargoyle/download_class.lua | 61 - .../model/cbi/qos_gargoyle/download_rule.lua | 87 -- .../luasrc/model/cbi/qos_gargoyle/global.lua | 123 -- .../luasrc/model/cbi/qos_gargoyle/upload.lua | 160 --- .../model/cbi/qos_gargoyle/upload_class.lua | 52 - .../model/cbi/qos_gargoyle/upload_rule.lua | 87 -- .../luasrc/model/qos_gargoyle.lua | 31 - .../luasrc/view/qos_gargoyle/list_view.htm | 97 -- .../view/qos_gargoyle/troubleshooting.htm | 52 - .../po/templates/qos-gargoyle.pot | 292 ---- .../po/zh-cn/qos-gargoyle.po | 334 ----- .../po/zh-cn/qos_gargoyle.po | 334 ----- .../etc/uci-defaults/40_luci-qos-gargoyle | 14 - package/jsda/openwrt-dnsforwarder/Makefile | 4 +- package/jsda/qos-gargoyle/Makefile | 66 - .../files/example-qos-config2.conf | 119 -- .../jsda/qos-gargoyle/files/qos_gargoyle.conf | 26 - .../qos-gargoyle/files/qos_gargoyle.hotplug | 20 - .../jsda/qos-gargoyle/files/qos_gargoyle.init | 771 ---------- .../qos-gargoyle/patches/001-musl-fixes.patch | 47 - package/jsda/qos-gargoyle/src/Makefile | 35 - package/jsda/qos-gargoyle/src/qosmon.c | 1246 ---------------- 61 files changed, 2 insertions(+), 13412 deletions(-) delete mode 100644 package/jsda/gargoyle-firewall-util/Makefile delete mode 100755 package/jsda/gargoyle-firewall-util/files/gargoyle_additions.firewall delete mode 100644 package/jsda/gargoyle-firewall-util/files/gargoyle_firewall.hotplug delete mode 100644 package/jsda/gargoyle-firewall-util/files/gargoyle_firewall_util.sh delete mode 100644 package/jsda/gargoyle-firewall-util/files/modemaccess.pppoe delete mode 100755 package/jsda/gargoyle-firewall-util/files/set_kernel_timezone.init delete mode 100644 package/jsda/gargoyle-firewall-util/src/Makefile delete mode 100644 package/jsda/gargoyle-firewall-util/src/backup_quotas.c delete mode 100644 package/jsda/gargoyle-firewall-util/src/delete_chain_from_table.c delete mode 100644 package/jsda/gargoyle-firewall-util/src/make_iptables_rules.c delete mode 100644 package/jsda/gargoyle-firewall-util/src/print_quotas.c delete mode 100644 package/jsda/gargoyle-firewall-util/src/restore_quotas.c delete mode 100644 package/jsda/libericstools/Makefile delete mode 100644 package/jsda/libericstools/src/Makefile delete mode 100644 package/jsda/libericstools/src/erics_tools.h delete mode 100644 package/jsda/libericstools/src/file_util.c delete mode 100644 package/jsda/libericstools/src/list.c delete mode 100644 package/jsda/libericstools/src/priority_queue.c delete mode 100644 package/jsda/libericstools/src/safe_malloc.c delete mode 100644 package/jsda/libericstools/src/string_util.c delete mode 100644 package/jsda/libericstools/src/test_list_and_queue.c delete mode 100644 package/jsda/libericstools/src/test_map.c delete mode 100644 package/jsda/libericstools/src/test_string.c delete mode 100644 package/jsda/libericstools/src/tree_map.c delete mode 100644 package/jsda/libiptbwctl/Makefile delete mode 100644 package/jsda/libiptbwctl/src/Makefile delete mode 100644 package/jsda/libiptbwctl/src/ipt_bwctl.c delete mode 100644 package/jsda/libiptbwctl/src/ipt_bwctl.h delete mode 100644 package/jsda/libiptbwctl/src/ipt_bwctl_safe_malloc.c delete mode 100644 package/jsda/libiptbwctl/src/utils/Makefile delete mode 100644 package/jsda/libiptbwctl/src/utils/bw_get.c delete mode 100644 package/jsda/libiptbwctl/src/utils/bw_print_history_file.c delete mode 100644 package/jsda/libiptbwctl/src/utils/bw_set.c delete mode 100644 package/jsda/libiptbwctl/src/utils/set_kernel_timezone.c delete mode 100755 package/jsda/luci-app-qos-gargoyle/LICENSE delete mode 100755 package/jsda/luci-app-qos-gargoyle/Makefile delete mode 100755 package/jsda/luci-app-qos-gargoyle/README.md delete mode 100755 package/jsda/luci-app-qos-gargoyle/luasrc/controller/qos_gargoyle.lua delete mode 100755 package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/download.lua delete mode 100755 package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/download_class.lua delete mode 100755 package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/download_rule.lua delete mode 100755 package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/global.lua delete mode 100755 package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/upload.lua delete mode 100755 package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/upload_class.lua delete mode 100755 package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/upload_rule.lua delete mode 100755 package/jsda/luci-app-qos-gargoyle/luasrc/model/qos_gargoyle.lua delete mode 100755 package/jsda/luci-app-qos-gargoyle/luasrc/view/qos_gargoyle/list_view.htm delete mode 100755 package/jsda/luci-app-qos-gargoyle/luasrc/view/qos_gargoyle/troubleshooting.htm delete mode 100755 package/jsda/luci-app-qos-gargoyle/po/templates/qos-gargoyle.pot delete mode 100755 package/jsda/luci-app-qos-gargoyle/po/zh-cn/qos-gargoyle.po delete mode 100755 package/jsda/luci-app-qos-gargoyle/po/zh-cn/qos_gargoyle.po delete mode 100755 package/jsda/luci-app-qos-gargoyle/root/etc/uci-defaults/40_luci-qos-gargoyle delete mode 100644 package/jsda/qos-gargoyle/Makefile delete mode 100644 package/jsda/qos-gargoyle/files/example-qos-config2.conf delete mode 100644 package/jsda/qos-gargoyle/files/qos_gargoyle.conf delete mode 100644 package/jsda/qos-gargoyle/files/qos_gargoyle.hotplug delete mode 100644 package/jsda/qos-gargoyle/files/qos_gargoyle.init delete mode 100644 package/jsda/qos-gargoyle/patches/001-musl-fixes.patch delete mode 100644 package/jsda/qos-gargoyle/src/Makefile delete mode 100644 package/jsda/qos-gargoyle/src/qosmon.c diff --git a/package/jsda/gargoyle-firewall-util/Makefile b/package/jsda/gargoyle-firewall-util/Makefile deleted file mode 100644 index 648a3f75b2..0000000000 --- a/package/jsda/gargoyle-firewall-util/Makefile +++ /dev/null @@ -1,71 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=gargoyle-firewall-util -PKG_VERSION:=1.0.0 -PKG_RELEASE:=1 - -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(INCLUDE_DIR)/package.mk - -define Package/gargoyle-firewall-util - SECTION:=net - CATEGORY:=Gargoyle - SUBMENU:=Network - TITLE:=A couple of shell script routines for firewall initialization - DEPENDS:=+ebtables +libericstools +uci +libiptbwctl +iptables-mod-filter \ - +iptables-mod-ipopt +iptables-mod-conntrack-extra +iptables-mod-nat-extra \ - +iptables-mod-extra +iptables-mod-iprange +iptables-mod-bandwidth \ - +iptables-mod-timerange +iptables-mod-weburl +kmod-gre +kmod-pptp \ - +kmod-tun +kmod-nf-nathelper +kmod-nf-nathelper-extra - MAINTAINER:=Eric Bishop -endef - -define Package/gargoyle-firewall-util/description - A couple of shell script routines for firewall initialization -endef - -define Build/Prepare - echo PACKAGE BUILD DIR = $(PACKAGE_BUILD_DIR) - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - -define Build/Configure -endef - -define Build/Compile - $(MAKE) -C $(PKG_BUILD_DIR) \ - $(TARGET_CONFIGURE_OPTS) \ - STAGING_DIR="$(STAGING_DIR)" \ - CFLAGS="$(TARGET_CFLAGS) -I $(STAGING_DIR)/usr/include" \ - LDFLAGS="$(TARGET_LDFLAGS) -L $(STAGING_DIR)/usr/lib" -endef - -define Package/gargoyle-firewall-util/postinst - #!/bin/sh - included=$$(cat $${IPKG_INSTROOT}/etc/config/firewall | grep 'gargoyle_additions.firewall' ) - if [ -z "$$included" ] ; then printf "config include\n\toption type script\n\toption path /usr/lib/gargoyle_firewall_util/gargoyle_additions.firewall\n\toption family IPv4\n\toption reload 1\n\n" >> $${IPKG_INSTROOT}/etc/config/firewall ; fi -endef - -define Package/gargoyle-firewall-util/install - $(INSTALL_DIR) $(1)/usr/lib/gargoyle_firewall_util/ - $(INSTALL_DIR) $(1)/etc/hotplug.d/iface/ - $(INSTALL_DIR) $(1)/usr/bin/ - $(INSTALL_DIR) $(1)/etc/init.d/ - $(INSTALL_DIR) $(1)/etc/ppp/ip-up.d/ - - $(INSTALL_BIN) $(PKG_BUILD_DIR)/make_iptables_rules $(1)/usr/bin/make_iptables_rules - $(INSTALL_BIN) $(PKG_BUILD_DIR)/delete_chain_from_table $(1)/usr/bin/delete_chain_from_table - $(INSTALL_BIN) $(PKG_BUILD_DIR)/backup_quotas $(1)/usr/bin/backup_quotas - $(INSTALL_BIN) $(PKG_BUILD_DIR)/restore_quotas $(1)/usr/bin/restore_quotas - $(INSTALL_BIN) $(PKG_BUILD_DIR)/print_quotas $(1)/usr/bin/print_quotas - - $(INSTALL_BIN) ./files/gargoyle_firewall_util.sh $(1)/usr/lib/gargoyle_firewall_util/gargoyle_firewall_util.sh - $(INSTALL_BIN) ./files/gargoyle_additions.firewall $(1)/usr/lib/gargoyle_firewall_util/gargoyle_additions.firewall - $(INSTALL_BIN) ./files/gargoyle_firewall.hotplug $(1)/etc/hotplug.d/iface/21-gargoyle_firewall - $(INSTALL_BIN) ./files/set_kernel_timezone.init $(1)/etc/init.d/set_kernel_timezone - $(INSTALL_BIN) ./files/modemaccess.pppoe $(1)/etc/ppp/ip-up.d/modemaccess.sh -endef - -$(eval $(call BuildPackage,gargoyle-firewall-util)) diff --git a/package/jsda/gargoyle-firewall-util/files/gargoyle_additions.firewall b/package/jsda/gargoyle-firewall-util/files/gargoyle_additions.firewall deleted file mode 100755 index 86df4d28cb..0000000000 --- a/package/jsda/gargoyle-firewall-util/files/gargoyle_additions.firewall +++ /dev/null @@ -1,2 +0,0 @@ -. /usr/lib/gargoyle_firewall_util/gargoyle_firewall_util.sh -initialize_firewall diff --git a/package/jsda/gargoyle-firewall-util/files/gargoyle_firewall.hotplug b/package/jsda/gargoyle-firewall-util/files/gargoyle_firewall.hotplug deleted file mode 100644 index 125d4b0c91..0000000000 --- a/package/jsda/gargoyle-firewall-util/files/gargoyle_firewall.hotplug +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/sh - -if [ "$INTERFACE" = "wan" ]; then - - . /usr/lib/gargoyle_firewall_util/gargoyle_firewall_util.sh - - if [ "$ACTION" = "ifup" ]; then - - # previously we waited until firewall was up here, testing firewall.core.loaded in /var/state - # unfortunately that was removed in barrier breaker, but new firewall (fw3) loads very FAST as it's a binary - # So... just wait 2 seconds - sleep 2 - - #Bring up the parts of the firewall that depend on device name and WAN IP address. - ifup_firewall - - #Start up the bandwidth monitor which depends on the device name - if [ -h /etc/rc.d/S55bwmon_gargoyle ]; then - /etc/init.d/bwmon_gargoyle restart - fi - fi - - if [ "$ACTION" = "ifdown" ]; then - quota_chains_exist=$(iptables -t mangle -L combined_quotas 2>/dev/null) - if [ -n "$quota_chains_exist" ]; then - backup_quotas - fi - fi - -fi - -if [ "$INTERFACE" = "lan" ]; then - wan_exists=$(uci -q get network.wan) - if [ -z "$wan_exists" ]; then - if [ "$ACTION" = "ifup" ]; then - /etc/init.d/bwmon_gargoyle restart - fi - if [ "$ACTION" = "ifdown" ]; then - /etc/init.d/bwmon_gargoyle stop - fi - fi -fi diff --git a/package/jsda/gargoyle-firewall-util/files/gargoyle_firewall_util.sh b/package/jsda/gargoyle-firewall-util/files/gargoyle_firewall_util.sh deleted file mode 100644 index 89a904954e..0000000000 --- a/package/jsda/gargoyle-firewall-util/files/gargoyle_firewall_util.sh +++ /dev/null @@ -1,585 +0,0 @@ -# Copyright Eric Bishop, 2008-2010 -# This is free software licensed under the terms of the GNU GPL v2.0 -# -. /lib/functions.sh -include /lib/network - -ra_mask="0x0080" -ra_mark="$ra_mask/$ra_mask" - -death_mask=0x8000 -death_mark="$death_mask" - -wan_if="" - -mask_to_cidr() -{ - mask="$1" - bits=0; - mask_parts=$(echo $mask | sed 's/\./ /g') - for p in $mask_parts ; do - case $p in - 255) - bits=$(($bits + 8)) ;; - 254) - bits=$(($bits + 7)) ;; - 252) - bits=$(($bits + 6)) ;; - 248) - bits=$(($bits + 5)) ;; - 240) - bits=$(($bits + 4)) ;; - 224) - bits=$(($bits + 3)) ;; - 192) - bits=$(($bits + 2)) ;; - 128) - bits=$(($bits + 1)) ;; - esac - done - echo $bits -} - -define_wan_if() -{ - if [ -z "$wan_if" ]; then - #Wait for up to 15 seconds for the wan interface to indicate it is up. - wait_sec=15 - while [ -z "$(uci -P /var/state get network.wan.up 2>/dev/null)" ] && [ "$wait_sec" -gt 0 ]; do - sleep 1 - wait_sec=$(($wait_sec - 1)) - done - - #The interface name will depend on if pppoe is used or not. If pppoe is used then - #the name we are looking for is in network.wan.ifname. If there is nothing there - #use the device named by network.wan.device - - wan_if=$(uci -P /var/state get network.wan.ifname 2>/dev/null) - if [ -z "$wan_if" ]; then - wan_if=$(uci -P /var/state get network.wan.device 2>/dev/null) - fi - fi -} - -# parse remote_accept sections in firewall config and add necessary rules -insert_remote_accept_rules() -{ - local config_name="firewall" - local section_type="remote_accept" - - ssh_max_attempts=$(uci -q get dropbear.@dropbear[0].max_remote_attempts) - ssh_port=$(uci -q get dropbear.@dropbear[0].Port) - if [ -z "$ssh_max_attempts" ] || [ "$ssh_max_attempts" = "unlimited" ]; then - ssh_max_attempts="" - else - ssh_max_attempts=$(( $ssh_max_attempts + 1 )) - fi - - #add rules for remote_accepts - parse_remote_accept_config() - { - vars="local_port remote_port start_port end_port proto zone" - proto="tcp udp" - zone="wan" - for var in $vars ; do - config_get $var $1 $var - done - if [ "$proto" = "tcpudp" ] || [ -z "$proto" ]; then - proto="tcp udp" - fi - - for prot in $proto ; do - if [ -n "$local_port" ]; then - - if [ -z "$remote_port" ]; then - remote_port="$local_port" - fi - - #Discourage brute force attacks on ssh from the WAN by limiting failed conneciton attempts. - #Each attempt gets a maximum of 10 password tries by dropbear. - if [ -n "$ssh_max_attempts" ] && [ "$local_port" = "$ssh_port" ] && [ "$prot" = "tcp" ]; then - iptables -t filter -A "input_${zone}_rule" -p "$prot" --dport $ssh_port -m recent --set --name SSH_CHECK - iptables -t filter -A "input_${zone}_rule" -m recent --update --seconds 300 --hitcount $ssh_max_attempts --name SSH_CHECK -j DROP - fi - - if [ "$remote_port" != "$local_port" ]; then - #since we're inserting with -I, insert redirect rule first which will then be hit second, after setting connmark - iptables -t nat -I "zone_"$zone"_prerouting" -p "$prot" --dport "$remote_port" -j REDIRECT --to-ports "$local_port" - iptables -t nat -I "zone_"$zone"_prerouting" -p "$prot" --dport "$remote_port" -j CONNMARK --set-mark "$ra_mark" - iptables -t filter -A "input_${zone}_rule" -p $prot --dport "$local_port" -m connmark --mark "$ra_mark" -j ACCEPT - else - iptables -t nat -I "zone_"$zone"_prerouting" -p "$prot" --dport "$remote_port" -j REDIRECT --to-ports "$local_port" - iptables -t filter -A "input_${zone}_rule" -p "$prot" --dport "$local_port" -j ACCEPT - fi - elif [ -n "$start_port" ] && [ -n "$end_port" ]; then - iptables -t nat -I "zone_"$zone"_prerouting" -p "$prot" --dport "$start_port:$end_port" -j REDIRECT - iptables -t filter -A "input_${zone}_rule" -p "$prot" --dport "$start_port:$end_port" -j ACCEPT - fi - done - } - config_load "$config_name" - config_foreach parse_remote_accept_config "$section_type" -} - -insert_pf_loopback_rules() -{ - config_name="firewall" - section_type="redirect" - - #Need to always delete the old chains first. - delete_chain_from_table "nat" "pf_loopback_A" - delete_chain_from_table "filter" "pf_loopback_B" - delete_chain_from_table "nat" "pf_loopback_C" - - define_wan_if - if [ -z "$wan_if" ] ; then return ; fi - wan_ip=$(uci -p /tmp/state get network.wan.ipaddr) - lan_mask=$(uci -p /tmp/state get network.lan.netmask) - - if [ -n "$wan_ip" ] && [ -n "$lan_mask" ]; then - - iptables -t nat -N "pf_loopback_A" - iptables -t filter -N "pf_loopback_B" - iptables -t nat -N "pf_loopback_C" - - iptables -t nat -I zone_lan_prerouting -d $wan_ip -j pf_loopback_A - iptables -t filter -I zone_lan_forward -j pf_loopback_B - iptables -t nat -I postrouting_rule -o br-lan -j pf_loopback_C - - add_pf_loopback() - { - local vars="src dest proto src_dport dest_ip dest_port" - local all_defined="1" - for var in $vars ; do - config_get $var $1 $var - loaded=$(eval echo "\$$var") - #echo $var = $loaded - if [ -z "$loaded" ] && [ ! "$var" = "$src_dport" ]; then - all_defined="0" - fi - done - - if [ -z "$src_dport" ]; then - src_dport=$dest_port - fi - - sdp_dash=$src_dport - sdp_colon=$(echo $sdp_dash | sed 's/\-/:/g') - dp_dash=$dest_port - dp_colon=$(echo $dp_dash | sed 's/\-/:/g') - - if [ "$all_defined" = "1" ] && [ "$src" = "wan" ] && [ "$dest" = "lan" ] ; then - iptables -t nat -A pf_loopback_A -p $proto --dport $sdp_colon -j DNAT --to-destination $dest_ip:$dp_dash - iptables -t filter -A pf_loopback_B -p $proto --dport $dp_colon -d $dest_ip -j ACCEPT - iptables -t nat -A pf_loopback_C -p $proto --dport $dp_colon -d $dest_ip -s $dest_ip/$lan_mask -j MASQUERADE - fi - } - - config_load "$config_name" - config_foreach add_pf_loopback "$section_type" - fi -} - -insert_dmz_rule() -{ - local config_name="firewall" - local section_type="dmz" - - #add rules for remote_accepts - parse_dmz_config() - { - vars="to_ip from" - for var in $vars ; do - config_get $var $1 $var - done - if [ -n "$from" ]; then - from_if=$(uci -q -p /tmp/state get network.$from.ifname) - fi - # echo "from_if = $from_if" - if [ -n "$to_ip" ] && [ -n "$from" ] && [ -n "$from_if" ]; then - iptables -t nat -A "zone_"$from"_prerouting" -i $from_if -j DNAT --to-destination $to_ip - # echo "iptables -t nat -A "prerouting_"$from -i $from_if -j DNAT --to-destination $to_ip" - iptables -t filter -I "zone_"$from"_forward" -d $to_ip -j ACCEPT - fi - } - config_load "$config_name" - config_foreach parse_dmz_config "$section_type" -} - -insert_restriction_rules() -{ - define_wan_if - if [ -z "$wan_if" ] ; then return ; fi - - if [ -e /tmp/restriction_init.lock ]; then return ; fi - touch /tmp/restriction_init.lock - - egress_exists=$(iptables -t filter -L egress_restrictions 2>/dev/null) - ingress_exists=$(iptables -t filter -L ingress_restrictions 2>/dev/null) - - if [ -n "$egress_exists" ]; then - delete_chain_from_table filter egress_whitelist - delete_chain_from_table filter egress_restrictions - fi - if [ -n "$ingress_exists" ]; then - delete_chain_from_table filter ingress_whitelist - delete_chain_from_table filter ingress_restrictions - fi - - iptables -t filter -N egress_restrictions - iptables -t filter -N ingress_restrictions - iptables -t filter -N egress_whitelist - iptables -t filter -N ingress_whitelist - - iptables -t filter -I FORWARD -o $wan_if -j egress_restrictions - iptables -t filter -I FORWARD -i $wan_if -j ingress_restrictions - - iptables -t filter -I egress_restrictions -j egress_whitelist - iptables -t filter -I ingress_restrictions -j ingress_whitelist - - package_name="firewall" - parse_rule_config() - { - section=$1 - section_type=$(uci get "$package_name"."$section") - - config_get "enabled" "$section" "enabled" - if [ -z "$enabled" ]; then enabled="1" ; fi - if [ "$enabled" = "1" ] && ( [ "$section_type" = "restriction_rule" ] || [ "$section_type" = "whitelist_rule" ] ) ; then - #convert app_proto && not_app_proto to connmark here - config_get "app_proto" "$section" "app_proto" - config_get "not_app_proto" "$section" "not_app_proto" - - if [ -n "$app_proto" ]; then - app_proto_connmark=$(cat /etc/l7marker.marks 2>/dev/null | grep $app_proto | awk '{ print $2 ; }' ) - app_proto_mask=$(cat /etc/l7marker.marks 2>/dev/null | grep $app_proto | awk '{ print $3 ; }' ) - uci set "$package_name"."$section".connmark="$app_proto_connmark/$app_proto_mask" - fi - if [ -n "$not_app_proto" ]; then - not_app_proto_connmark=$(cat /etc/l7marker.marks 2>/dev/null | grep "$not_app_proto" | awk '{ print $2 }') - not_app_proto_mask=$(cat /etc/l7marker.marks 2>/dev/null | grep "$not_app_proto" | awk '{ print $3 }') - uci set "$package_name"."$section".not_connmark="$not_app_proto_connmark/$not_app_proto_mask" - fi - - table="filter" - chain="egress_restrictions" - ingress="" - target="REJECT" - - config_get "is_ingress" "$section" "is_ingress" - if [ "$is_ingress" = "1" ]; then - ingress=" -i " - if [ "$section_type" = "restriction_rule" ]; then - chain="ingress_restrictions" - else - chain="ingress_whitelist" - fi - else - if [ "$section_type" = "restriction_rule" ]; then - chain="egress_restrictions" - else - chain="egress_whitelist" - fi - fi - - if [ "$section_type" = "whitelist_rule" ]; then - target="ACCEPT" - fi - - make_iptables_rules -p "$package_name" -s "$section" -t "$table" -c "$chain" -g "$target" $ingress - make_iptables_rules -p "$package_name" -s "$section" -t "$table" -c "$chain" -g "$target" $ingress -r - - uci del "$package_name"."$section".connmark 2>/dev/null - uci del "$package_name"."$section".not_connmark 2>/dev/null - fi - } - - config_load "$package_name" - config_foreach parse_rule_config "whitelist_rule" - config_foreach parse_rule_config "restriction_rule" - - rm -rf /tmp/restriction_init.lock -} - -initialize_quotas() -{ - define_wan_if - if [ -z "$wan_if" ] ; then return ; fi - - if [ -e /tmp/quota_init.lock ]; then return ; fi - touch /tmp/quota_init.lock - - lan_mask=$(uci -p /tmp/state get network.lan.netmask) - lan_ip=$(uci -p /tmp/state get network.lan.ipaddr) - full_qos_enabled=$(ls /etc/rc.d/*qos_gargoyle 2>/dev/null) - - if [ -n "$full_qos_enabled" ]; then - full_up=$(uci get qos_gargoyle.upload.total_bandwidth 2>/dev/null) - full_down=$(uci get qos_gargoyle.download.total_bandwidth 2>/dev/null) - if [ -z "$full_up" ] && [ -z "$full_down" ]; then - full_qos_enabled="" - fi - fi - - - # restore_quotas does the hard work of building quota chains & rebuilding crontab file to do backups - # - # this initializes qos functions ONLY if we have quotas that - # have up and down speeds defined for when quota is exceeded - # and full qos is not enabled - if [ -z "$full_qos_enabled" ]; then - restore_quotas -w $wan_if -d $death_mark -m $death_mask -s "$lan_ip/$lan_mask" -c "0 0,4,8,12,16,20 * * * /usr/bin/backup_quotas >/dev/null 2>&1" - initialize_quota_qos - else - restore_quotas -q -w $wan_if -d $death_mark -m $death_mask -s "$lan_ip/$lan_mask" -c "0 0,4,8,12,16,20 * * * /usr/bin/backup_quotas >/dev/null 2>&1" - cleanup_old_quota_qos - fi - - #enable cron, but only restart cron if it is currently running - #since we initialize this before cron, this will - #make sure we don't start cron twice at boot - /etc/init.d/cron enable - cron_active=$(ps | grep "crond" | grep -v "grep" ) - if [ -n "$cron_active" ]; then - /etc/init.d/cron restart - fi - - rm -rf /tmp/quota_init.lock -} - -load_all_config_sections() -{ - local config_name="$1" - local section_type="$2" - - all_config_sections="" - section_order="" - config_cb() - { - if [ -n "$2" ] || [ -n "$1" ]; then - if [ -n "$section_type" ]; then - if [ "$1" = "$section_type" ]; then - all_config_sections="$all_config_sections $2" - fi - else - all_config_sections="$all_config_sections $2" - fi - fi - } - - config_load "$config_name" - echo "$all_config_sections" -} - -cleanup_old_quota_qos() -{ - for iface in $(tc qdisc show | awk '{print $5}' | sort -u ); do - tc qdisc del dev "$iface" root >/dev/null 2>&1 - done -} - -initialize_quota_qos() -{ - cleanup_old_quota_qos - - #speeds should be in kbyte/sec, units should NOT be present in config file (unit processing should be done by front-end) - quota_sections=$(load_all_config_sections "firewall" "quota") - upload_speeds="" - download_speeds="" - config_load "firewall" - for q in $quota_sections ; do - config_get "exceeded_up_speed" $q "exceeded_up_speed" - config_get "exceeded_down_speed" $q "exceeded_down_speed" - if [ -n "$exceeded_up_speed" ] && [ -n "$exceeded_down_speed" ]; then - if [ $exceeded_up_speed -gt 0 ] && [ $exceeded_down_speed -gt 0 ]; then - upload_speeds="$exceeded_up_speed $upload_speeds" - download_speeds="$exceeded_down_speed $download_speeds" - fi - fi - done - - #echo "upload_speeds = $upload_speeds" - - unique_up=$( printf "%d\n" $upload_speeds 2>/dev/null | sort -u -n) - unique_down=$( printf "%d\n" $download_speeds 2>/dev/null | sort -u -n) - - #echo "unique_up = $unique_up" - - num_up_bands=1 - num_down_bands=1 - if [ -n "$upload_speeds" ]; then - num_up_bands=$((1 + $(printf "%d\n" $upload_speeds 2>/dev/null | sort -u -n | wc -l) )) - fi - if [ -n "$download_speeds" ]; then - num_down_bands=$((1 + $(printf "%d\n" $download_speeds 2>/dev/null | sort -u -n | wc -l) )) - fi - - #echo "num_up_bands=$num_up_bands" - #echo "num_down_bands=$num_down_bands" - - if [ -n "$wan_if" ] && [ $num_up_bands -gt 1 ] && [ $num_down_bands -gt 1 ]; then - insmod sch_prio >/dev/null 2>&1 - insmod sch_tbf >/dev/null 2>&1 - insmod cls_fw >/dev/null 2>&1 - - ifconfig imq0 down >/dev/null 2>&1 - ifconfig imq1 down >/dev/null 2>&1 - rmmod imq >/dev/null 2>&1 - insmod imq numdevs=1 hook_chains="INPUT,FORWARD" hook_tables="mangle,mangle" >/dev/null 2>&1 - ip link set imq0 up - - #egress/upload - tc qdisc del dev $wan_if root >/dev/null 2>&1 - tc qdisc add dev $wan_if handle 1:0 root prio bands $num_up_bands priomap 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - cur_band=2 - upload_shift=0 - for rate_kb in $unique_up ; do - kbit=$(echo $((rate_kb*8))kbit) - mark=$(($cur_band << $upload_shift)) - tc filter add dev $wan_if parent 1:0 prio $cur_band protocol ip handle $mark fw flowid 1:$cur_band - tc qdisc add dev $wan_if parent 1:$cur_band handle $cur_band: tbf rate $kbit burst $kbit limit $kbit - cur_band=$(($cur_band+1)) - done - - #ingress/download - tc qdisc del dev imq0 root >/dev/null 2>&1 - tc qdisc add dev imq0 handle 1:0 root prio bands $num_down_bands priomap 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - cur_band=2 - download_shift=8 - for rate_kb in $unique_down ; do - kbit=$(echo $((rate_kb*8))kbit) - mark=$(($cur_band << $download_shift)) - tc filter add dev imq0 parent 1:0 prio $cur_band protocol ip handle $mark fw flowid 1:$cur_band - tc qdisc add dev imq0 parent 1:$cur_band handle $cur_band: tbf rate $kbit burst $kbit limit $kbit - cur_band=$(($cur_band+1)) - done - - iptables -t mangle -I ingress_quotas -i $wan_if -j IMQ --todev 0 - - #tc -s qdisc show dev $wan_if - #tc -s qdisc show dev imq0 - fi -} - -enforce_dhcp_assignments() -{ - enforce_assignments=$(uci -q get firewall.@defaults[0].enforce_dhcp_assignments) - delete_chain_from_table "filter" "lease_mismatch_check" - - local pairs1 - local pairs2 - local pairs - pairs1="" - pairs2="" - if [ -e /tmp/dhcp.leases ]; then - pairs1=$(cat /tmp/dhcp.leases | sed '/^[ \t]*$/d' | awk ' { print $2"^"$3"\n" ; } ' ) - fi - if [ -e /etc/ethers ]; then - pairs2=$(cat /etc/ethers | sed '/^[ \t]*$/d' | awk ' { print $1"^"$2"\n" ; } ' ) - fi - pairs=$( printf "$pairs1\n$pairs2\n" | sort | uniq ) - - - if [ "$enforce_assignments" = "1" ] && [ -n "$pairs" ]; then - iptables -t filter -N lease_mismatch_check - local p - for p in $pairs ; do - local mac - local ip - mac=$(echo $p | sed 's/\^.*$//g') - ip=$(echo $p | sed 's/^.*\^//g') - if [ -n "$ip" ] && [ -n "$mac" ]; then - iptables -t filter -A lease_mismatch_check ! -s "$ip" -m mac --mac-source "$mac" -j REJECT - iptables -t filter -A lease_mismatch_check -s "$ip" -m mac ! --mac-source "$mac" -j REJECT - fi - done - iptables -t filter -I delegate_forward -j lease_mismatch_check - fi -} - -force_router_dns() -{ - force_router_dns=$(uci get firewall.@defaults[0].force_router_dns 2> /dev/null) - if [ "$force_router_dns" = "1" ]; then - iptables -t nat -I zone_lan_prerouting -p tcp --dport 53 -j REDIRECT - iptables -t nat -I zone_lan_prerouting -p udp --dport 53 -j REDIRECT - fi -} - -add_adsl_modem_routes() -{ - wan_proto=$(uci -q get network.wan.proto) - if [ "$wan_proto" = "pppoe" ]; then - wan_dev=$(uci -q get network.wan.ifname) #not really the interface, but the device - iptables -A postrouting_rule -t nat -o $wan_dev -j MASQUERADE - iptables -A forwarding_rule -o $wan_dev -j ACCEPT - /etc/ppp/ip-up.d/modemaccess.sh firewall $wan_dev - fi -} - -initialize_firewall() -{ - iptables -I zone_lan_forward -i br-lan -o br-lan -j ACCEPT - insert_remote_accept_rules - insert_dmz_rule - enforce_dhcp_assignments - force_router_dns - add_adsl_modem_routes - isolate_guest_networks -} - -guest_mac_from_uci() -{ - local is_guest_network - local macaddr - config_get is_guest_network "$1" is_guest_network - if [ "$is_guest_network" = "1" ]; then - config_get macaddr "$1" macaddr - echo "$macaddr" - fi -} - -get_guest_macs() -{ - config_load "wireless" - config_foreach guest_mac_from_uci "wifi-iface" -} - -isolate_guest_networks() -{ - ebtables -t filter -F FORWARD - ebtables -t filter -F INPUT - local guest_macs=$( get_guest_macs ) - if [ -n "$guest_macs" ]; then - local lanifs=`brctl show br-lan 2>/dev/null | awk ' $NF !~ /interfaces/ { print $NF } '` - local lif - - local lan_ip=$(uci -p /tmp/state get network.lan.ipaddr) - - for lif in $lanifs ; do - for gmac in $guest_macs ; do - local is_guest=$(ifconfig "$lif" 2>/dev/null | grep -i "$gmac") - if [ -n "$is_guest" ]; then - echo "$lif with mac $gmac is wireless guest" - - #Allow access to WAN but not other LAN hosts for anyone on guest network - ebtables -t filter -A FORWARD -i "$lif" --logical-out br-lan -j DROP - - #Only allow DHCP/DNS access to router for anyone on guest network - ebtables -t filter -A INPUT -i "$lif" -p ARP -j ACCEPT - ebtables -t filter -A INPUT -i "$lif" -p IPV4 --ip-protocol UDP --ip-destination-port 53 -j ACCEPT - ebtables -t filter -A INPUT -i "$lif" -p IPV4 --ip-protocol UDP --ip-destination-port 67 -j ACCEPT - ebtables -t filter -A INPUT -i "$lif" -p IPV4 --ip-destination $lan_ip -j DROP - - fi - done - done - fi -} - -ifup_firewall() -{ - insert_restriction_rules - initialize_quotas - insert_pf_loopback_rules -} diff --git a/package/jsda/gargoyle-firewall-util/files/modemaccess.pppoe b/package/jsda/gargoyle-firewall-util/files/modemaccess.pppoe deleted file mode 100644 index f28a9547c2..0000000000 --- a/package/jsda/gargoyle-firewall-util/files/modemaccess.pppoe +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh - -#This script allows access to the ADSL modem web interface when pppoe is used. -#For this to work configure your modem in bridge mode with DHCP enabled on the modem. -#This will cause the modem to dish an address to the router interface when requested below. -# -#Alternatively you can manually set the below variable ROUTER_IP with the IP address -#you want to use. Make sure the IP address is on the same network as the modem. -#ROUTER_IP=10.0.0.2 - -#Main case statement used only by udhcp which only calls with one of the -#following four key words in parameter 1. -case "$1" in - deconfig) - ifconfig "$interface" 0.0.0.0 - exit 0 - ;; - renew) - ifconfig $interface $ip netmask ${subnet:-255.255.255.0} broadcast ${broadcast:-+} - exit 0 - ;; - bound) - ifconfig $interface $ip netmask ${subnet:-255.255.255.0} broadcast ${broadcast:-+} - exit 0 - ;; - nak) - exit 0 - ;; - leasefail) - exit 0 - ;; -esac - -#if we get here then udhcp did not call us. Must be from pppd or /usr/lib/gargoyle_firewall_util - -#configure the ethernet interface. -if [ -n "$ROUTER_IP" ]; then - #In manual mode the user gave us an IP address for our interface - ifconfig $2 $ROUTER_IP netmask 255.255.255.0 -else - #In auto mode we first check if we have an ip address already. - ROUTER_IP=$(ifconfig $2 | grep "inet addr:") - if [ -z "$ROUTER_IP" ]; then - #Dont have one so try an get one. - udhcpc -f -i $2 -n -q -s /etc/ppp/ip-up.d/modemaccess.sh - fi -fi - -exit 0 diff --git a/package/jsda/gargoyle-firewall-util/files/set_kernel_timezone.init b/package/jsda/gargoyle-firewall-util/files/set_kernel_timezone.init deleted file mode 100755 index 05241ddd94..0000000000 --- a/package/jsda/gargoyle-firewall-util/files/set_kernel_timezone.init +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh /etc/rc.common -START=30 - -start() -{ - /usr/bin/set_kernel_timezone - - touch /etc/crontabs/root - if ! grep -q "set_kernel_timezone" /etc/crontabs/root; then - echo '0,1,11,21,31,41,51 * * * * /usr/bin/set_kernel_timezone >/dev/null 2>&1' >> /etc/crontabs/root - /etc/init.d/cron enable - #only restart cron if it is currently running - #since we initialize this before cron, this will - #make sure we don't start cron twice at boot - cron_active=$(ps | grep "crond" | grep -v "grep" ) - if [ -n "$cron_active" ]; then - /etc/init.d/cron restart - fi - fi -} diff --git a/package/jsda/gargoyle-firewall-util/src/Makefile b/package/jsda/gargoyle-firewall-util/src/Makefile deleted file mode 100644 index fac998e0f3..0000000000 --- a/package/jsda/gargoyle-firewall-util/src/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -all: make_iptables_rules delete_chain_from_table backup_quotas restore_quotas print_quotas - -print_quotas: print_quotas.c - $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ -lericstools -luci -liptbwctl - -restore_quotas: restore_quotas.c - $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ -lericstools -luci -liptbwctl - -backup_quotas: backup_quotas.c - $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ -lericstools -luci -liptbwctl - -delete_chain_from_table: delete_chain_from_table.c - $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ -lericstools - -make_iptables_rules: make_iptables_rules.c - $(CC) $(CFLAGS) $(LDFLAGS) make_iptables_rules.c -o make_iptables_rules -lericstools -luci -lm - -clean: - rm -rf make_iptables_rules delete_chain_from_table print_quotas backup_quotas restore_quotas *.o *~ .*sw* diff --git a/package/jsda/gargoyle-firewall-util/src/backup_quotas.c b/package/jsda/gargoyle-firewall-util/src/backup_quotas.c deleted file mode 100644 index ad27a36945..0000000000 --- a/package/jsda/gargoyle-firewall-util/src/backup_quotas.c +++ /dev/null @@ -1,217 +0,0 @@ -/* backup_quotas -- Used to backup quota data from iptables rules that use the "bandwidth" module - * Originally designed for use with Gargoyle router firmware (gargoyle-router.com) - * - * - * Copyright © 2009 by Eric Bishop - * - * This file is free software: you may copy, redistribute 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 file 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 -#define malloc safe_malloc -#define strdup safe_strdup - -list* get_all_sections_of_type(struct uci_context *ctx, char* package, char* section_type); -void backup_quota(char* quota_id, char* quota_backup_dir); -char* get_uci_option(struct uci_context* ctx,char* package_name, char* section_name, char* option_name); -char* get_option_value_string(struct uci_option* uopt); - -int main(void) -{ - struct uci_context *ctx = uci_alloc_context(); - list* quota_sections = get_all_sections_of_type(ctx, "firewall", "quota"); - system("mkdir -p /usr/data/quotas"); - unlock_bandwidth_semaphore_on_exit(); - while(quota_sections->length > 0) - { - char* next_quota = shift_list(quota_sections); - char* ignore_backup = get_uci_option(ctx, "firewall", next_quota, "ignore_backup_at_next_restore"); - int do_backup = 1; - if(ignore_backup != NULL) - { - if(strcmp(ignore_backup, "1") == 0) - { - do_backup = 0; - } - free(ignore_backup); - } - - if(do_backup) - { - //do backup - - /* base id for quota is the ip associated with it*/ - char* backup_id = get_uci_option(ctx, "firewall", next_quota, "id"); - char* ip = get_uci_option(ctx, "firewall", next_quota, "ip"); - if(ip == NULL) - { - ip = strdup("ALL"); - } - else if(strcmp(ip, "") == 0) - { - free(ip); - ip = strdup("ALL"); - } - if(backup_id == NULL) - { - backup_id = strdup(ip); - } - else if(strcmp(backup_id, "") == 0) - { - free(backup_id); - backup_id = strdup(ip); - } - - char* types[] = { "ingress_limit", "egress_limit", "combined_limit" }; - char* postfixes[] = { "_ingress", "_egress", "_combined" }; - int type_index; - for(type_index=0; type_index < 3; type_index++) - { - char* defined = get_uci_option(ctx, "firewall", next_quota, types[type_index]); - if(defined != NULL) - { - char* type_id = dynamic_strcat(2, backup_id, postfixes[type_index]); - - backup_quota(type_id, "/usr/data/quotas" ); - - free(type_id); - free(defined); - } - } - free(backup_id); - free(ip); - } - free(next_quota); - } - - unsigned long num; - destroy_list(quota_sections, DESTROY_MODE_FREE_VALUES, &num); - uci_free_context(ctx); - - return 0; -} - -list* get_all_sections_of_type(struct uci_context *ctx, char* package, char* section_type) -{ - struct uci_package *p = NULL; - struct uci_element *e = NULL; - - list* sections_of_type = initialize_list(); - if(uci_load(ctx, package, &p) == UCI_OK) - { - uci_foreach_element( &p->sections, e) - { - struct uci_section *section = uci_to_section(e); - if(safe_strcmp(section->type, section_type) == 0) - { - push_list(sections_of_type, strdup(section->e.name)); - } - } - } - return sections_of_type; -} - -void backup_quota(char* id, char* quota_backup_dir) -{ - /* if we ever bother to allow quotas to apply to subnets - * specified with '/', this may be necessary - */ - char* quota_file_name; - if(strstr(id, "/") != NULL) - { - char* quota_file_name = dynamic_replace(id, "/", "_"); - } - else - { - quota_file_name = strdup(id); - } - - char* quota_file_path = dynamic_strcat(3, quota_backup_dir, "/quota_", quota_file_name); - - unsigned long num_ips; - ip_bw *ip_buf = NULL; - int query_succeeded = get_all_bandwidth_usage_for_rule_id(id, &num_ips, &ip_buf, 5000); - if(query_succeeded) - { - save_usage_to_file(ip_buf, num_ips, quota_file_path); - free(ip_buf); - } - free(quota_file_path); - free(quota_file_name); -} - -char* get_uci_option(struct uci_context* ctx, char* package_name, char* section_name, char* option_name) -{ - char* option_value = NULL; - struct uci_ptr ptr; - char* lookup_str = dynamic_strcat(5, package_name, ".", section_name, ".", option_name); - int ret_value = uci_lookup_ptr(ctx, &ptr, lookup_str, 1); - if(ret_value == UCI_OK) - { - if( !(ptr.flags & UCI_LOOKUP_COMPLETE)) - { - ret_value = UCI_ERR_NOTFOUND; - } - else - { - struct uci_element *e = (struct uci_element*)ptr.o; - option_value = get_option_value_string(uci_to_option(e)); - } - } - free(lookup_str); - - return option_value; -} - -// this function dynamically allocates memory for -// the option string, but since this program exits -// almost immediately (after printing variable info) -// the massive memory leak we're opening up shouldn't -// cause any problems. This is your reminder/warning -// that this might be an issue if you use this code to -// do anything fancy. -char* get_option_value_string(struct uci_option* uopt) -{ - char* opt_str = NULL; - if(uopt->type == UCI_TYPE_STRING) - { - opt_str = strdup(uopt->v.string); - } - if(uopt->type == UCI_TYPE_LIST) - { - struct uci_element* e; - uci_foreach_element(&uopt->v.list, e) - { - if(opt_str == NULL) - { - opt_str = strdup(e->name); - } - else - { - char* tmp; - tmp = dynamic_strcat(3, opt_str, " ", e->name); - free(opt_str); - opt_str = tmp; - } - } - } - return opt_str; -} diff --git a/package/jsda/gargoyle-firewall-util/src/delete_chain_from_table.c b/package/jsda/gargoyle-firewall-util/src/delete_chain_from_table.c deleted file mode 100644 index 25ead9f4b2..0000000000 --- a/package/jsda/gargoyle-firewall-util/src/delete_chain_from_table.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#define malloc safe_malloc -#define strdup safe_strdup - -void free_split_pieces(char** split_pieces); - -int main(int argc, char **argv) -{ - char *table = argv[1]; - char *delete_chain = argv[2]; - if(argc != 3) - { - printf("USAGE: %s [TABLE] [CHAIN TO DELETE]\n\n", argv[0]); - return 0; - } - - char *command = dynamic_strcat(3, "iptables -t ", table, " -L -n --line-numbers 2>/dev/null"); - unsigned long num_lines = 0; - char** table_dump = get_shell_command_output_lines(command, &num_lines); - free(command); - - unsigned long line_index; - char* current_chain = NULL; - list* delete_commands = initialize_list(); - - for(line_index=0; line_index < num_lines; line_index++) - { - char* line = table_dump[line_index]; - unsigned long num_pieces = 0; - char whitespace[] = { '\t', ' ', '\r', '\n' }; - char** line_pieces = split_on_separators(line, whitespace, 4, -1, 0, &num_pieces); - if(strcmp(line_pieces[0], "Chain") == 0) - { - if(current_chain != NULL) { free(current_chain); } - current_chain = strdup(line_pieces[1]); - } - else - { - unsigned long line_num; - int read = sscanf(line_pieces[0], "%ld", &line_num); - - if(read > 0 && current_chain != NULL && num_pieces >1) - { - if(strcmp(line_pieces[1], delete_chain) == 0) - { - char* delete_command = dynamic_strcat(7, "iptables -t ", table, " -D ", current_chain, " ", line_pieces[0], " 2>/dev/null"); - push_list(delete_commands, delete_command); - } - } - } - - //free line_pieces - free_null_terminated_string_array(line_pieces); - } - free_null_terminated_string_array(table_dump); - - /* final two commands to flush chain being deleted and whack it */ - unshift_list(delete_commands, dynamic_strcat(5, "iptables -t ", table, " -F ", delete_chain, " 2>/dev/null")); - unshift_list(delete_commands, dynamic_strcat(5, "iptables -t ", table, " -X ", delete_chain, " 2>/dev/null")); - - /* run delete commands */ - while(delete_commands->length > 0) - { - char *next_command = (char*)pop_list(delete_commands); - char **out = get_shell_command_output_lines(next_command, &num_lines); - free_null_terminated_string_array(out); - } - - return 0; -} diff --git a/package/jsda/gargoyle-firewall-util/src/make_iptables_rules.c b/package/jsda/gargoyle-firewall-util/src/make_iptables_rules.c deleted file mode 100644 index 326ebafdb2..0000000000 --- a/package/jsda/gargoyle-firewall-util/src/make_iptables_rules.c +++ /dev/null @@ -1,984 +0,0 @@ -/* make_iptables_rules -- A tool to generate firewall rules from options in UCI config files - * Originally designed for use with Gargoyle router firmware (gargoyle-router.com) - * - * - * Copyright © 2009 by Eric Bishop - * - * This file is free software: you may copy, redistribute 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 file 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 -#define malloc safe_malloc -#define strdup safe_strdup - -/* these are indices don't change! */ -#define MATCH_IP_INDEX 0 -#define MATCH_IP_RANGE_INDEX 1 -#define MATCH_MAC_INDEX 2 - -string_map* get_rule_definition(char* config, char* section); -char* get_option_value_string(struct uci_option* uopt); -int parse_option(char* option_name, char* option_value, string_map* definition); - -char*** parse_ips_and_macs(char* addr_str); -char** parse_ports(char* port_str); -char** parse_marks(char* list_str, unsigned long max_mask); -list* parse_quoted_list(char* list_str, char quote_char, char escape_char, char add_remainder_if_uneven_quotes); - -int truncate_if_starts_with(char* test_str, char* prefix); - -char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingress, char* target, char* target_options); -int compute_multi_rules(char** def, list* multi_rules, char** single_check, int never_single, char* rule_prefix, char* test_prefix1, char* test_prefix2, int is_negation, int mask_byte_index, char* proto, int requires_proto, int quoted_args); - -int main(int argc, char **argv) -{ - int c; - char* package = NULL; - char* section = NULL; - char* table = NULL; - char* chain = NULL; - char* target = NULL; - char* target_options = NULL; - int is_ingress = 0; - int run_commands = 0; - int usage_printed = 0; - while((c = getopt(argc, argv, "P:p:S:s:T:t:C:c:G:g:O:o:IiRrUu")) != -1) //section, page, css includes, javascript includes, title, output interface variables - { - switch(c) - { - case 'P': - case 'p': - package = strdup(optarg); - break; - case 'S': - case 's': - section = strdup(optarg); - break; - case 'T': - case 't': - table = strdup(optarg); - break; - case 'C': - case 'c': - chain = strdup(optarg); - break; - case 'G': - case 'g': - target = strdup(optarg); - break; - case 'O': - case 'o': - target_options = strdup(optarg); - break; - case 'I': - case 'i': - is_ingress = 1; - break; - case 'R': - case 'r': - run_commands = 1; - break; - case 'U': - case 'u': - default: - fprintf(stderr, "USAGE: %s -p [PACKAGE] -s [SECTION] -t [TABLE] -c [CHAIN] -g [TARGET] [OPTIONS]\n -o [TARGET_OPTIONS]\n -i indicates that this rule applies to ingress packets\n -r implies computed commands should be executed instead of just printed\n -u print usage and exit\n\n", argv[0]); - usage_printed = 1; - break; - - } - } - if(package != NULL && section != NULL && table != NULL && chain != NULL && target != NULL) - { - string_map* def = get_rule_definition(package, section); - if(def != NULL) - { - char** rules = compute_rules(def, table, chain, 0, target, target_options); - - int rindex = 0; - for(rindex=0; rules[rindex] != NULL; rindex++) - { - if(run_commands == 0) - { - printf("%s\n", rules[rindex]); - } - else - { - system(rules[rindex]); - } - } - } - else - { - fprintf(stderr, "ERROR: Invalid package / section\n"); - - } - } - else if(!usage_printed) - { - fprintf(stderr, "USAGE: %s -p [PACKAGE] -s [SECTION] -t [TABLE] -c [CHAIN] -g [TARGET] [OPTIONS]\n -o [TARGET_OPTIONS]\n -i indicates that this rule applies to ingress packets\n -r implies computed commands should be executed instead of just printed\n -u print usage and exit\n\n", argv[0]); - - } - return 0; -} - -/* - * Note we've currently maxed out out one whole byte of address space - * in the connmark at this point. If we want to match in - * further dimensions, we will have to be greedy and take - * even more address space - */ -char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingress, char* target, char* target_options) -{ - list* multi_rules = initialize_list(); - char* single_check = strdup(""); - char* rule_prefix = dynamic_strcat(5, "iptables -t ", table, " -A ", chain, " "); - - target = strdup(target); - to_uppercase(target); - - /* get timerange vars first */ - char* active_hours = get_map_element(rule_def, "active_hours"); - char* active_weekdays = get_map_element(rule_def, "active_weekdays"); - char* active_weekly_ranges = get_map_element(rule_def, "active_weekly_ranges"); - if(active_weekly_ranges != NULL) - { - char* tmp = dynamic_strcat(3, " -m timerange --weekly_ranges \"", active_weekly_ranges, "\" " ); - dcat_and_free(&single_check, &tmp, 1, 1); - } - else if(active_hours != NULL && active_weekdays != NULL) - { - char* tmp = dynamic_strcat(5, " -m timerange --hours \"", active_hours, "\" --weekdays \"", active_weekdays, "\" " ); - dcat_and_free(&single_check, &tmp, 1, 1); - } - else if(active_hours != NULL) - { - char* tmp = dynamic_strcat(3, " -m timerange --hours \"", active_hours, "\" " ); - dcat_and_free(&single_check, &tmp, 1, 1); - } - else if(active_weekdays != NULL) - { - char* tmp = dynamic_strcat(3, " -m timerange --weekdays \"", active_weekdays, "\" " ); - dcat_and_free(&single_check, &tmp, 1, 1); - } - - /* - * layer7 && ipp2p can not be negated. To negate them - * set a mark/connmark and negate that - */ - char* layer7_def = get_map_element(rule_def, "layer7"); - if(layer7_def != NULL) - { - char* tmp = dynamic_strcat(2, " -m layer7 --l7proto ", layer7_def ); - dcat_and_free(&single_check, &tmp, 1, 1); - } - char* ipp2p_def = get_map_element(rule_def, "ipp2p"); - if(ipp2p_def != NULL) - { - char* tmp = dynamic_strcat(2, " -m ipp2p --", ipp2p_def ); - dcat_and_free(&single_check, &tmp, 1, 1); - } - char* min_def = get_map_element(rule_def, "min_pkt_size"); - char* max_def = get_map_element(rule_def, "max_pkt_size"); - if(min_def != NULL && max_def != NULL) - { - min_def = min_def == NULL ? "0" : min_def; - max_def = max_def == NULL ? "3000" : max_def; //typical max transmission size is 1500, let's make default max 2x that - char* tmp = dynamic_strcat(5, " -m length --length ", min_def, ":", max_def, " " ); - dcat_and_free(&single_check, &tmp, 1, 1); - } - - /* make sure proto is lower case */ - char* proto = get_map_element(rule_def, "proto"); - if(proto == NULL) - { - proto = strdup("both"); - set_map_element(rule_def, "proto", proto); - } - to_lowercase(proto); - if( safe_strcmp(proto, "udp") != 0 && safe_strcmp(proto, "tcp") != 0 && safe_strcmp(proto, "both") != 0 ) - { - char* tmp; - tmp = set_map_element(rule_def, "proto", strdup("both")); - free(tmp); - proto = (char*)get_map_element(rule_def, "proto"); - } - int include_proto = strcmp(proto, "both") == 0 ? 0 : 1; - - /* parse multi rules */ - int mask_byte_index = 0; - list* initial_mask_list = initialize_list(); - list* final_mask_list = initialize_list(); - - /* url matches are a bit of a special case, handle them first */ - /* we have to save this mask_byte_index specially, because it must be set separately, so it only gets set if packet is http request */ - int url_mask_byte_index = mask_byte_index; - - char* url_match_vars[] = { "url_contains", "url_regex", "url_exact", "url_domain_contains", "url_domain_regex", "url_domain_exact" }; - char* url_neg_match_vars[] = { "not_url_contains", "not_url_regex", "not_url_exact", "not_url_domain_contains", "not_url_domain_regex", "not_url_domain_exact" }; - char* url_prefixes[] = { " -m weburl --contains ", " -m weburl --contains_regex ", " -m weburl --matches_exactly ", " -m weburl --domain_only --contains ", " -m weburl --domain_only --contains_regex ", " -m weburl --domain_only --matches_exactly " }; - list* url_lists[6]; - int url_var_index=0; - int url_rule_count=0; - int url_is_negated=0; - - for(url_is_negated=0; url_is_negated < 2 && url_rule_count == 0; url_is_negated++) - { - char** url_vars = url_is_negated ? url_neg_match_vars : url_match_vars; - for(url_var_index=0; url_var_index < 6; url_var_index++) - { - list* url_list = get_map_element(rule_def, url_vars[url_var_index]); - if(url_list != NULL) - { - url_rule_count = url_rule_count + url_list->length; - } - url_lists[url_var_index] = url_list; - } - } - url_is_negated--; - - proto = url_rule_count > 0 ? "tcp" : proto; - int url_is_multi = url_rule_count <= 1 ? 0 : 1; - for(url_var_index=0; url_var_index < 6; url_var_index++) - { - list* url_list = url_lists[url_var_index]; - if(url_list != NULL) - { - if(url_list->length > 0) - { - unsigned long num_vals; - char** url_def = (char**)get_list_values(url_list, &num_vals); - compute_multi_rules( url_def, multi_rules, &single_check, url_is_multi, rule_prefix, url_prefixes[url_var_index], "", url_is_negated, mask_byte_index, proto, include_proto, 1 ); - free(url_def); - } - } - } - push_list(initial_mask_list, (void*)&url_is_negated); - push_list(final_mask_list, (void*)&url_is_multi); - mask_byte_index++; - - /* mark matches */ - char** mark_def = get_map_element(rule_def, "mark"); - int mark_is_negated = mark_def == NULL ? 1 : 0; - mark_def = mark_def == NULL ? get_map_element(rule_def, "not_mark") : mark_def; - mark_is_negated = mark_def == NULL ? 0 : mark_is_negated; - /* we can't do single negation with mark match, so always add seperate multi-match if mark is negated */ - int mark_is_multi = compute_multi_rules(mark_def, multi_rules, &single_check, mark_is_negated, rule_prefix, " -m mark ", " --mark ", mark_is_negated, mask_byte_index, proto, include_proto, 0) == 2; - push_list(initial_mask_list, (void*)&mark_is_negated); - push_list(final_mask_list, (void*)&mark_is_multi); - mask_byte_index++; - - /* connmark matches */ - char** connmark_def = get_map_element(rule_def, "connmark"); - int connmark_is_negated = connmark_def == NULL ? 1 : 0; - connmark_def = connmark_def == NULL ? get_map_element(rule_def, "not_connmark") : connmark_def; - connmark_is_negated = connmark_def == NULL ? 0 : connmark_is_negated; - int connmark_is_multi = compute_multi_rules(connmark_def, multi_rules, &single_check, 0, rule_prefix, " -m connmark ", " --mark ", connmark_is_negated, mask_byte_index, proto, include_proto, 0) == 2; - push_list(initial_mask_list, (void*)&connmark_is_negated); - push_list(final_mask_list, (void*)&connmark_is_multi); - mask_byte_index++; - - /* - * for ingress source = remote, destination = local - * for egress source = local, destination = remote - * - * addresses are a bit tricky, since we need to handle 3 different kinds of matches: ips, ip ranges and macs - */ - char*** src_def = get_map_element(rule_def, (is_ingress ? "remote_addr" : "local_addr")); - char*** not_src_def = get_map_element(rule_def, (is_ingress ? "not_remote_addr" : "not_local_addr")); - int src_is_negated = src_def == NULL && not_src_def != NULL ? 1 : 0; - src_def = src_is_negated == 1 ? not_src_def : src_def; - - char*** dst_def = get_map_element(rule_def, (is_ingress ? "local_addr" : "remote_addr")); - char*** not_dst_def = get_map_element(rule_def, (is_ingress ? "not_local_addr" : "not_remote_addr")); - int dst_is_negated = dst_def == NULL && not_dst_def != NULL ? 1 : 0; - dst_def = dst_is_negated == 1 ? not_dst_def : dst_def; - - char*** addr_defs[2] = { src_def, dst_def }; - int addr_negated[2] = { src_is_negated, dst_is_negated }; - char* addr_prefix1[2][3] = { { " -s ", " -m iprange ", " -m mac --mac-source " }, { " -d", "-m iprange ", NULL } }; - char* addr_prefix2[2][3] = { {"", " --src-range ", "" }, { "", " --dst-range ", NULL } }; - - int addr_index = 0; - int is_true = 1; - int is_false = 0; - for(addr_index = 0; addr_index < 2; addr_index++) - { - char*** addrs = addr_defs[addr_index]; - if(addrs != NULL) - { - int total_rules = 0; - int test_list_index; - for(test_list_index=0; test_list_index < 3; test_list_index++) - { - char** test_list = addrs[test_list_index]; - if(test_list != NULL && addr_prefix1[addr_index][test_list_index] != NULL) - { - while(test_list[0] != NULL){ test_list++; total_rules++; } - } - } - int is_multi = total_rules > 1 ? 1 : 0; - int is_negated = addr_negated[addr_index]; - //printf("is negated = %d for addr_index = %d\n", is_negated, addr_index); - - for(test_list_index=0; test_list_index < 3; test_list_index++) - { - char** test_list = addrs[test_list_index]; - if(test_list != NULL && addr_prefix1[addr_index][test_list_index] != NULL) - { - if(test_list[0] != NULL) - { - compute_multi_rules(test_list, multi_rules, &single_check, is_multi, rule_prefix, addr_prefix1[addr_index][test_list_index], addr_prefix2[addr_index][test_list_index],is_negated, mask_byte_index, proto, include_proto, 0); - } - } - } - - push_list(initial_mask_list, (void*)(addr_negated + addr_index)); - push_list(final_mask_list, (void*)(is_multi == 1 ? &is_true : &is_false) ); - mask_byte_index++; - } - } - - char** sport_def = get_map_element(rule_def, (is_ingress ? "remote_port" : "local_port")); - int sport_is_negated = sport_def == NULL ? 1 : 0; - sport_def = sport_def == NULL ? get_map_element(rule_def, (is_ingress ? "not_remote_port" : "not_local_port")) : sport_def; - sport_is_negated = sport_def == NULL ? 0 : sport_is_negated; - int sport_is_multi = compute_multi_rules(sport_def, multi_rules, &single_check, 0, rule_prefix, " --sport ", "", sport_is_negated, mask_byte_index, proto, 1, 0) == 2; - push_list(initial_mask_list, (void*)&sport_is_negated); - push_list(final_mask_list, (void*)&sport_is_multi); - mask_byte_index++; - - char** dport_def = get_map_element(rule_def, (is_ingress ? "local_port" : "remote_port")); - int dport_is_negated = dport_def == NULL ? 1 : 0; - dport_def = dport_def == NULL ? get_map_element(rule_def, (is_ingress ? "not_local_port" : "not_remote_port")) : dport_def; - dport_is_negated = dport_def == NULL ? 0 : dport_is_negated; - int dport_is_multi = compute_multi_rules(dport_def, multi_rules, &single_check, 0, rule_prefix, " --dport ", "", dport_is_negated, mask_byte_index, proto, 1, 0) == 2; - push_list(initial_mask_list, (void*)&dport_is_negated); - push_list(final_mask_list, (void*)&dport_is_multi); - mask_byte_index++; - - list* all_rules = initialize_list(); - - //if no target_options specified, make sure it's an empty string, not null - target_options = (target_options == NULL) ? "" : target_options; - //if target_options is empty and we're rejecting and proto is tcp, set options to --reject-with tcp-reset instead of default - target_options = strlen(target_options) == 0 && (strcmp(proto, "tcp") == 0) && strcmp(target, "REJECT") == 0 ? " --reject-with tcp-reset " : target_options; - if(multi_rules->length > 0) - { - if(strlen(single_check) > 0) - { - char* dummy_multi[] = { single_check, NULL }; - int requires_proto = strcmp(proto, "both") == 0 && sport_def == NULL && dport_def == NULL ? 0 : 1; - compute_multi_rules(dummy_multi, multi_rules, &single_check, 1, rule_prefix, " ", "", 0, mask_byte_index, proto, requires_proto, 0); - mask_byte_index++; - } - - /* - printf("final mask length = %ld\n", final_mask_list->length); - printf("src is multi = %d\n", src_is_multi); - unsigned long mi; - int* one = shift_list(final_mask_list); - int* two = shift_list(final_mask_list); - printf("one = %d, two = %d\n", *one, *two); - unshift_list(final_mask_list, two); - unshift_list(final_mask_list, one); - */ - - unsigned long initial_url_mark = 0x01000000 * url_is_negated * url_is_multi; - unsigned long initial_main_mark = 0; - unsigned long final_match = 0; - int next_mask_index; - for(next_mask_index = 0; next_mask_index length > 0) - { - next_is_multi = shift_list(final_mask_list); - } - else - { - *next_is_multi = 1; - } - - unsigned long next_mark_bit = 0x01000000 * (unsigned long)pow(2, next_mask_index) * (*next_is_multi); - final_match = final_match + next_mark_bit; - if(initial_mask_list->length > 0) - { - int* is_negation = (int*)shift_list(initial_mask_list); - if(*is_negation == 1 && next_mask_index != url_mask_byte_index ) - { - //printf("nonzero byte index for main mark = %d\n", next_mask_index); - initial_main_mark = initial_main_mark + next_mark_bit; - } - } - /* else it's last single_check mark which is never initialized to one */ - } - - if(initial_main_mark > 0) - { - //set main_mark unconditionally - char mark[12]; - sprintf(mark, "0x%lX", initial_main_mark); - push_list(all_rules, dynamic_strcat(4, rule_prefix, " -j CONNMARK --set-mark ", mark, "/0xFF000000" )); - } - if(initial_url_mark > 0) //do url_mark second since because in order to set main mark we use full mask of 0xFF000000 - { - //set proper mark if this is an http request - char mark[12]; - sprintf(mark, "0x%lX", initial_url_mark); - push_list(all_rules, dynamic_strcat(5, rule_prefix, " -p tcp -m weburl --contains http -j CONNMARK --set-mark ", mark, "/", mark)); - } - - //put all rules in place from multi_rules list - while(multi_rules->length > 0) - { - push_list(all_rules, shift_list(multi_rules)); - } - unsigned long tmp_length; - destroy_list(multi_rules, DESTROY_MODE_IGNORE_VALUES, &tmp_length); - - //if final mark matches perfectly with mask of 0xFF000000, jump to (REJECT/ACCEPT) target - char final_match_str[12]; - sprintf(final_match_str, "0x%lX", final_match); - - //if we're rejecting, no target options are specified, and no proto is specified add two rules: one for tcp with tcp-reject, and one for everything else - if(safe_strcmp(target, "REJECT") == 0 && safe_strcmp(target_options, "") == 0 && safe_strcmp(proto, "both")) - { - push_list(all_rules, dynamic_strcat(4, rule_prefix, " -p tcp -m connmark --mark ", final_match_str, "/0xFF000000 -j REJECT --reject-with tcp-reset")); - push_list(all_rules, dynamic_strcat(4, rule_prefix, " -m connmark --mark ", final_match_str, "/0xFF000000 -j REJECT")); - - } - else - { - char* final_proto = strstr(target_options, "tcp-reset") == NULL ? "" : " -p tcp "; - push_list(all_rules, dynamic_strcat(7, rule_prefix, final_proto, " -m connmark --mark ", final_match_str, "/0xFF000000 -j ", target, target_options )); - } - //if final mark does not match (i.e. we didn't reject), unconditionally reset mark to 0x0 with mask of 0xFF000000 - push_list(all_rules, dynamic_strcat(2, rule_prefix, " -j CONNMARK --set-mark 0x0/0xFF000000" )); - } - else - { - if( strcmp(proto, "both") == 0 ) - { - if( dport_def == NULL && sport_def == NULL ) - { - if(safe_strcmp(target, "REJECT") == 0 && safe_strcmp(target_options, "") == 0 ) - { - push_list(all_rules, dynamic_strcat(4, rule_prefix, " -p tcp ", single_check, " -j REJECT --reject-with tcp-reset")); - } - push_list(all_rules, dynamic_strcat(5, rule_prefix, single_check, " -j ",target, target_options )); - } - else - { - if(safe_strcmp(target, "REJECT") == 0 && safe_strcmp(target_options, "") == 0 ) - { - push_list(all_rules, dynamic_strcat(4, rule_prefix, " -p tcp ", single_check, " -j REJECT --reject-with tcp-reset" )); - } - else - { - push_list(all_rules, dynamic_strcat(6, rule_prefix, " -p tcp ", single_check, " -j ", target, target_options )); - } - push_list(all_rules, dynamic_strcat(6, rule_prefix, " -p udp ", single_check, " -j ", target, target_options )); - } - } - else - { - push_list(all_rules, dynamic_strcat(8, rule_prefix, " -p ", proto, " ", single_check, " -j ", target, target_options )); - } - } - - /* handle very special case: if we're white-listing a URL we need to make - * sure other, non-request packets in connection get through too. So, we allow all traffic - * with a destination port of 80 that is NOT an HTTP request. This should allow - * HTTP connections to persist but prevent connections to any websites but those - * specified - */ - if(url_rule_count > 0 && safe_strcmp(target, "ACCEPT") == 0 && is_ingress == 0) - { - push_list(all_rules, dynamic_strcat(2, rule_prefix, " -p tcp -m weburl --contains http -j CONNMARK --set-mark 0xFF000000/0xFF000000" )); - push_list(all_rules, dynamic_strcat(2, rule_prefix, " -p tcp --dport 80 -m connmark ! --mark 0xFF000000/0xFF000000 -j ACCEPT " )); - push_list(all_rules, dynamic_strcat(2, rule_prefix, " -j CONNMARK --set-mark 0x0/0xFF000000" )); - } - - unsigned long num_rules; - char** block_rule_list = (char**) destroy_list( all_rules, DESTROY_MODE_RETURN_VALUES, &num_rules); - - return block_rule_list; -} - -/* returns 0 if no rules found, 1 if one rule found AND included in single_check, otherwise 2 */ -int compute_multi_rules(char** def, list* multi_rules, char** single_check, int never_single, char* rule_prefix, char* test_prefix1, char* test_prefix2, int is_negation, int mask_byte_index, char* proto, int requires_proto, int quoted_args) -{ - int parse_type = 0; - if(def != NULL) - { - int num_rules; - for(num_rules=0; def[num_rules] != NULL; num_rules++){} - if(num_rules == 1 && !never_single) - { - parse_type = 1; - char* tmp = dynamic_strcat(7, " ", test_prefix1, (is_negation ? " ! " : " "), test_prefix2, (quoted_args ? " \"" : " "), def[0], (quoted_args ? "\" " : " ") ); - dcat_and_free(&tmp, single_check, 1, 1 ); - } - else - { - parse_type = 2; - unsigned long mask = 0x01000000 * (unsigned long)pow(2, mask_byte_index); - char mask_str[12]; - sprintf(mask_str, "0x%lX", mask); - char* connmark_part = dynamic_strcat(4, " -j CONNMARK --set-mark ", (is_negation ? "0x0" : mask_str), "/", mask_str); - - int rule_index =0; - for(rule_index=0; def[rule_index] != NULL; rule_index++) - { - char* common_part = dynamic_strcat(7, test_prefix1, " ", test_prefix2, (quoted_args ? " \"" : " "), def[rule_index], (quoted_args ? "\" " : " "), connmark_part); - if(strcmp(proto, "both") == 0) - { - if(requires_proto) - { - push_list(multi_rules, dynamic_strcat(3, rule_prefix, " -p tcp ", common_part)); - push_list(multi_rules, dynamic_strcat(3, rule_prefix, " -p udp ", common_part)); - } - else - { - push_list(multi_rules, dynamic_strcat(3, rule_prefix, " ", common_part )); - } - } - else - { - push_list(multi_rules, dynamic_strcat(5, rule_prefix, " -p ", proto, " ", common_part)); - } - free(common_part); - } - free(connmark_part); - } - } - return parse_type; -} - -string_map* get_rule_definition(char* package, char* section) -{ - string_map* definition = NULL; - struct uci_context *ctx; - struct uci_package *p = NULL; - ctx = uci_alloc_context(); - if(uci_load(ctx, package, &p) == UCI_OK) - { - struct uci_ptr ptr; - char* lookup_str = dynamic_strcat(3, package, ".", section); - int ret_value = uci_lookup_ptr(ctx, &ptr, lookup_str, 1); - if(ret_value == UCI_OK) - { - struct uci_section *s = ptr.s; - if(s != NULL) - { - struct uci_element *e; - definition = initialize_string_map(1); - - uci_foreach_element(&s->options, e) - { - char* option_name = strdup(e->name); - to_lowercase(option_name); - char* option_value = get_option_value_string(uci_to_option(e)); - parse_option(option_name, option_value, definition); - free(option_name); - free(option_value); - } - } - } - } - uci_free_context(ctx); - - return definition; -} - -int parse_option(char* option_name, char* option_value, string_map* definition) -{ - int valid_option = 0; - if( safe_strcmp(option_name, "proto") == 0 || - safe_strcmp(option_name, "layer7") == 0 || - safe_strcmp(option_name, "ipp2p") == 0 || - safe_strcmp(option_name, "max_pkt_size") == 0 || - safe_strcmp(option_name, "min_pkt_size") ==0 - ) - { - valid_option = 1; - set_map_element(definition, option_name, strdup(option_value)); - } - else if( safe_strcmp(option_name, "active_hours") == 0 || - safe_strcmp(option_name, "active_weekly_ranges") == 0 || - safe_strcmp(option_name, "active_weekdays") == 0 - ) - { - to_lowercase(option_value); - if( safe_strcmp(option_value, "all") != 0 ) - { - valid_option = 1; - set_map_element(definition, option_name, strdup(option_value)); - } - } - else if( safe_strcmp(option_name, "mark") == 0 || - safe_strcmp(option_name, "connmark") == 0 || - safe_strcmp(option_name, "not_mark") == 0 || - safe_strcmp(option_name, "not_connmark") == 0 - ) - { - valid_option = 1; - set_map_element(definition, option_name, parse_marks(option_value, 0xFFFFFFFF)); - } - else if(safe_strcmp(option_name, "remote_addr") == 0 || - safe_strcmp(option_name, "local_addr") == 0 || - safe_strcmp(option_name, "not_remote_addr") == 0 || - safe_strcmp(option_name, "not_local_addr") == 0) - { - char*** parsed_addr = parse_ips_and_macs(option_value); - if(parsed_addr != NULL) - { - valid_option = 1; - if( safe_strcmp(option_name, "not_remote_addr") == 0 || safe_strcmp(option_name, "remote_addr") == 0 ) - { - parsed_addr[MATCH_MAC_INDEX][0] = NULL; //doesn't make sense to match remote MAC address - } - set_map_element(definition, option_name, parsed_addr); - } - } - else if(safe_strcmp(option_name, "remote_port") == 0 || - safe_strcmp(option_name, "local_port") == 0 || - safe_strcmp(option_name, "not_remote_port") == 0 || - safe_strcmp(option_name, "not_local_port") == 0) - { - char** parsed_ports = parse_ports(option_value); - if(parsed_ports != NULL) - { - valid_option = 1; - set_map_element(definition, option_name, parsed_ports); - } - } - else if(truncate_if_starts_with(option_name, "url_contains") || - truncate_if_starts_with(option_name, "url_regex") || - truncate_if_starts_with(option_name, "url_exact") || - truncate_if_starts_with(option_name, "url_domain_contains") || - truncate_if_starts_with(option_name, "url_domain_regex") || - truncate_if_starts_with(option_name, "url_domain_exact") || - truncate_if_starts_with(option_name, "not_url_contains") || - truncate_if_starts_with(option_name, "not_url_regex") || - truncate_if_starts_with(option_name, "not_url_exact") || - truncate_if_starts_with(option_name, "not_url_domain_contains") || - truncate_if_starts_with(option_name, "not_url_domain_regex") || - truncate_if_starts_with(option_name, "not_url_domain_exact")) - { - /* - * may be a quoted list of urls to block, so attempt to parse this - * if no quotes found, match on unquoted expresssion - * we don't need to de-escape quotes because when we define rule, - * we call iptables from system, and through the shell, which will de-escape quotes for us - */ - list* parsed_quoted = parse_quoted_list(option_value, '\"', '\\', 0); - list* old_parsed = get_map_element(definition, option_name); - if(old_parsed != NULL) - { - while(parsed_quoted->length > 0) - { - push_list(old_parsed, shift_list(parsed_quoted)); - } - free(parsed_quoted); - parsed_quoted = old_parsed; - } - if(parsed_quoted->length > 0) - { - valid_option = 1; - set_map_element(definition, option_name, parsed_quoted); - } - } - return valid_option; -} - -// this function dynamically allocates memory for -// the option string, but since this program exits -// almost immediately (after printing variable info) -// the massive memory leak we're opening up shouldn't -// cause any problems. This is your reminder/warning -// that this might be an issue if you use this code to -// do anything fancy. -char* get_option_value_string(struct uci_option* uopt) -{ - char* opt_str = NULL; - if(uopt->type == UCI_TYPE_STRING) - { - opt_str = strdup(uopt->v.string); - } - if(uopt->type == UCI_TYPE_LIST) - { - struct uci_element* e; - uci_foreach_element(&uopt->v.list, e) - { - if(opt_str == NULL) - { - opt_str = strdup(e->name); - } - else - { - char* tmp; - tmp = dynamic_strcat(3, opt_str, " ", e->name); - free(opt_str); - opt_str = tmp; - } - } - } - - return opt_str; -} - -char*** parse_ips_and_macs(char* addr_str) -{ - unsigned long num_pieces; - char** addr_parts = split_on_separators(addr_str, ",", 1, -1, 0, &num_pieces); - list* ip_list = initialize_list(); - list* ip_range_list = initialize_list(); - list* mac_list = initialize_list(); - - int ip_part_index; - for(ip_part_index=0; addr_parts[ip_part_index] != NULL; ip_part_index++) - { - char* next_str = addr_parts[ip_part_index]; - if(strchr(next_str, ':')) - { - trim_flanking_whitespace(next_str); - if(strlen(next_str) == 17) - { - push_list(mac_list, trim_flanking_whitespace(next_str)); - } - } - else if(strchr(next_str, '-') != NULL) - { - char** range_parts = split_on_separators(next_str, "-", 1, 2, 1, &num_pieces); - char* start = trim_flanking_whitespace(range_parts[0]); - char* end = trim_flanking_whitespace(range_parts[1]); - int start_ip[4]; - int end_ip[4]; - int start_valid = sscanf(start, "%d.%d.%d.%d", start_ip, start_ip+1, start_ip+2, start_ip+3); - int end_valid = sscanf(end, "%d.%d.%d.%d", end_ip, end_ip+1, end_ip+2, end_ip+3); - - if(start_valid == 4 && end_valid == 4) - { - //get_ip_range_strs(start_ip, end_ip, "", 4, ip_list); - push_list(ip_range_list, trim_flanking_whitespace(next_str)); - } - - free(start); - free(end); - free(range_parts); - //free(next_str); - } - else - { - int parsed_ip[4]; - int valid = sscanf(next_str, "%d.%d.%d.%d", parsed_ip, parsed_ip+1, parsed_ip+2, parsed_ip+3); - if(valid == 4) - { - push_list(ip_list, trim_flanking_whitespace(next_str)); - } - } - } - free(addr_parts); - - unsigned long num1, num2, num3; - char*** return_value = (char***)malloc(3*sizeof(char**)); - return_value[MATCH_IP_INDEX] = (char**)destroy_list(ip_list, DESTROY_MODE_RETURN_VALUES, &num1); - return_value[MATCH_IP_RANGE_INDEX] = (char**)destroy_list(ip_range_list, DESTROY_MODE_RETURN_VALUES, &num2); - return_value[MATCH_MAC_INDEX] = (char**)destroy_list(mac_list, DESTROY_MODE_RETURN_VALUES, &num3); - - if(num1 + num2 + num3 == 0) - { - free(return_value[0]); - free(return_value[1]); - free(return_value[2]); - free(return_value); - return_value = NULL; - } - return return_value; -} - -char** parse_ports(char* port_str) -{ - unsigned long num_pieces; - char** ports = split_on_separators(port_str, ",", 1, -1, 0, &num_pieces); - int port_index = 0; - for(port_index=0; ports[port_index] != NULL; port_index++) - { - char* dash_ptr; - while((dash_ptr=strchr(ports[port_index], '-')) != NULL) - { - dash_ptr[0] = ':'; - } - trim_flanking_whitespace( ports[port_index] ); - } - return ports; -} - -/* - * parses a list of marks/connmarks - * the max_mask parameter specfies a maximal mask that will be used - * when matching marks/connmarks. If a user-defined mask is specified - * (by defining [mark]/[mask]) this is bitwise-anded with the maximum - * mask to get the final mask. This is especially necessary for - * connmarks, because the mechanism to handle negation when multiple - * test rules are needed uses the last (high) byte of the connmark - * address space, so this HAS to be masked out when matching - * connmarks, using max_mask=0x00FFFFFF - */ -char** parse_marks(char* list_str, unsigned long max_mask) -{ - char** marks = NULL; - if(list_str != NULL) - { - unsigned long num_pieces; - marks = split_on_separators(list_str, ",", 1, -1, 0, &num_pieces); - if(marks[0] == NULL) - { - free(marks); - marks = NULL; - } - else - { - int mark_index; - for(mark_index = 0; marks[mark_index] != NULL; mark_index++) - { - trim_flanking_whitespace(marks[mark_index]); - if(max_mask != 0xFFFFFFFF) - { - - char* m = marks[mark_index]; - char* mask_start; - if( (mask_start = strchr(m, '/')) != NULL ) - { - unsigned long mask = 0xFFFFFFFF; - mask_start++; - sscanf(mask_start, "%lX", &mask); - - mask = mask & max_mask; - - *(mask_start) = '\0'; - char new_mask_str[12]; - sprintf(new_mask_str, "0x%lX", mask); - marks[mark_index] = dynamic_strcat(2, m, new_mask_str); - } - else - { - char new_mask_str[12]; - sprintf(new_mask_str, "0x%lX", max_mask); - marks[mark_index] = dynamic_strcat(3, m, "/", new_mask_str); - } - free(m); - } - } - } - } - return marks; -} - -/* - * parses list of quoted strings, ignoring escaped quote characters that are not themselves escaped - * Note that we don't de-escape anything here. If necessary that should be done elsewhere. - */ -list* parse_quoted_list(char* list_str, char quote_char, char escape_char, char add_remainder_if_uneven_quotes) -{ - long num_quotes = 0; - long list_index = 0; - char previous_is_quoted = 0; - for(list_index=0; list_str[list_index] != '\0'; list_index++) - { - num_quotes = num_quotes + ( list_str[list_index] == quote_char && !previous_is_quoted ? 1 : 0); - previous_is_quoted = list_str[list_index] == escape_char && !previous_is_quoted ? 1 : 0; - } - - char** pieces = (char**)malloc( ((long)(num_quotes/2)+2) * sizeof(char*) ); - long piece_index = 0; - long next_start_index=-1; - previous_is_quoted = 0; - for(list_index=0; list_str[list_index] != '\0'; list_index++) - { - if( list_str[list_index] == quote_char && !previous_is_quoted ) - { - if(next_start_index < 0) - { - next_start_index = list_index+1; - } - else - { - long length = list_index-next_start_index; - char* next_piece = (char*)malloc( (1+length)*sizeof(char) ); - memcpy(next_piece, list_str+next_start_index, length); - next_piece[length] = '\0'; - pieces[piece_index] = next_piece; - piece_index++; - next_start_index = -1; - } - } - previous_is_quoted = list_str[list_index] == escape_char && !previous_is_quoted ? 1 : 0; - } - if(add_remainder_if_uneven_quotes && next_start_index >= 0) - { - long length = 1+list_index-next_start_index; - char* next_piece = (char*)malloc( (1+length)*sizeof(char) ); - memcpy(next_piece, list_str+next_start_index, length); - next_piece[length] = '\0'; - pieces[piece_index] = next_piece; - piece_index++; - } - pieces[piece_index] = NULL; - - list* quoted_list = initialize_list(); - if(pieces[0] != NULL) - { - for(piece_index=0; pieces[piece_index] != NULL; piece_index++) - { - push_list(quoted_list, pieces[piece_index]); - //don't free pieces[piece], we're just putting it in list - } - } - else - { - //if no quotes at all, just return list_str - push_list(quoted_list, strdup(list_str)); - } - free(pieces);//but do free array of char* pointers, we don't need it anymore - - return quoted_list; -} - -int truncate_if_starts_with(char* test_str, char* prefix) -{ - int prefix_length = strlen(prefix); - int test_length = strlen(test_str); - int matches = 0; - if(prefix_length <= test_length) - { - matches = strncmp(test_str, prefix, prefix_length) == 0 ? 1 : 0; - if(matches) - { - test_str[prefix_length] = '\0'; - } - } - return matches; -} diff --git a/package/jsda/gargoyle-firewall-util/src/print_quotas.c b/package/jsda/gargoyle-firewall-util/src/print_quotas.c deleted file mode 100644 index 0190a9fd27..0000000000 --- a/package/jsda/gargoyle-firewall-util/src/print_quotas.c +++ /dev/null @@ -1,410 +0,0 @@ -/* print_quotas -- Used to print quota data from iptables rules that use the "bandwidth" module - * Originally designed for use with Gargoyle router firmware (gargoyle-router.com) - * - * - * Copyright © 2009-2010 by Eric Bishop - * - * This file is free software: you may copy, redistribute 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 file 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 -#define malloc safe_malloc -#define strdup safe_strdup - -list* get_all_sections_of_type(struct uci_context *ctx, char* package, char* section_type); -void backup_quota(char* quota_id, char* quota_backup_dir); -char* get_uci_option(struct uci_context* ctx,char* package_name, char* section_name, char* option_name); -char* get_option_value_string(struct uci_option* uopt); - -int main(void) -{ - struct uci_context *ctx = uci_alloc_context(); - list* quota_sections = get_all_sections_of_type(ctx, "firewall", "quota"); - unlock_bandwidth_semaphore_on_exit(); - - /* for each ip have uint64_t[6], */ - string_map *id_ip_to_bandwidth = initialize_string_map(1); - string_map *id_ip_to_percents = initialize_string_map(1); - string_map *id_ip_to_limits = initialize_string_map(1); - list *id_to_time = initialize_list(); - - while(quota_sections->length > 0) - { - char* next_quota = shift_list(quota_sections); - - /* base id for quota is the ip associated with it*/ - char *id = get_uci_option(ctx, "firewall", next_quota, "id"); - char* ip = get_uci_option(ctx, "firewall", next_quota, "ip"); - if(ip == NULL) - { - ip = strdup("ALL"); - } - else if(strcmp(ip, "") == 0) - { - free(ip); - ip = strdup("ALL"); - } - if(id == NULL) - { - id = strdup(ip); - } - else if(strcmp(id, "") == 0) - { - free(id); - id = strdup(ip); - } - - string_map* ip_to_bandwidth = get_string_map_element(id_ip_to_bandwidth, id); - ip_to_bandwidth = ip_to_bandwidth == NULL ? initialize_string_map(1) : ip_to_bandwidth; - set_string_map_element(id_ip_to_bandwidth, id, ip_to_bandwidth); - - string_map* ip_to_percents = get_string_map_element(id_ip_to_percents, id); - ip_to_percents = ip_to_percents == NULL ? initialize_string_map(1) : ip_to_percents; - set_string_map_element(id_ip_to_percents, id, ip_to_percents); - - string_map* ip_to_limits = get_string_map_element(id_ip_to_limits, id); - ip_to_limits = ip_to_limits == NULL ? initialize_string_map(1) : ip_to_limits; - set_string_map_element(id_ip_to_limits, id, ip_to_limits); - - char* offpeak_hours = get_uci_option(ctx, "firewall", next_quota, "offpeak_hours"); - char* offpeak_weekdays = get_uci_option(ctx, "firewall", next_quota, "offpeak_weekdays"); - char* offpeak_weekly_ranges = get_uci_option(ctx, "firewall", next_quota, "offpeak_weekly_ranges"); - char* onpeak_hours = get_uci_option(ctx, "firewall", next_quota, "onpeak_hours"); - char* onpeak_weekdays = get_uci_option(ctx, "firewall", next_quota, "onpeak_weekdays"); - char* onpeak_weekly_ranges = get_uci_option(ctx, "firewall", next_quota, "onpeak_weekly_ranges"); - if(offpeak_hours != NULL || offpeak_weekdays != NULL || offpeak_weekly_ranges != NULL || onpeak_hours != NULL || onpeak_weekdays != NULL || onpeak_weekly_ranges != NULL) - { - unsigned char is_off_peak = (offpeak_hours != NULL || offpeak_weekdays != NULL || offpeak_weekly_ranges != NULL) ? 1 : 0; - char* hours_var = is_off_peak ? offpeak_hours : onpeak_hours; - char* weekdays_var = is_off_peak ? offpeak_weekdays : onpeak_weekdays; - char* weekly_ranges_var = is_off_peak ? offpeak_weekly_ranges : onpeak_weekly_ranges; - char* active_var = is_off_peak ? strdup("except") : strdup("only"); - - if(weekly_ranges_var != NULL) - { - if(hours_var != NULL) { free(hours_var); hours_var=NULL; } - if(weekdays_var != NULL) { free(weekly_ranges_var); weekly_ranges_var=NULL; } - } - hours_var = hours_var == NULL ? strdup("") : hours_var; - weekdays_var = weekdays_var == NULL ? strdup("") : weekdays_var; - weekly_ranges_var = weekly_ranges_var == NULL ? strdup("") : weekly_ranges_var; - push_list(id_to_time, dynamic_strcat(11, "quotaTimes[\"", id, "\"] = [\"", hours_var, "\", \"", weekdays_var, "\", \"", weekly_ranges_var ,"\", \"", active_var, "\"];")); - - free(hours_var); - free(weekdays_var); - free(weekly_ranges_var); - free(active_var); - } - else - { - push_list(id_to_time, dynamic_strcat(3, "quotaTimes[\"", id, "\"] = [\"\", \"\", \"\", \"always\"];")); - } - - char* types[] = { "combined_limit", "ingress_limit", "egress_limit" }; - char* postfixes[] = { "_combined", "_ingress", "_egress" }; - - int type_index; - for(type_index=0; type_index < 3; type_index++) - { - char* limit = get_uci_option(ctx, "firewall", next_quota, types[type_index]); - if(limit != NULL) - { - char* type_id = dynamic_strcat(2, id, postfixes[type_index]); - ip_bw* ip_buf; - unsigned long num_ips = 0; - int query_succeeded = get_all_bandwidth_usage_for_rule_id(type_id, &num_ips, &ip_buf, 5000); - if(query_succeeded && num_ips > 0) - { - unsigned long ip_index = 0; - for(ip_index = 0; ip_index < num_ips; ip_index++) - { - ip_bw next = ip_buf[ip_index]; - char* next_ip = NULL; - if(next.ip == 0) - { - next_ip = strdup(ip); - } - else - { - struct in_addr addr; - addr.s_addr = next.ip; - next_ip = strdup(inet_ntoa(addr)); - } - - uint64_t *bw_list = get_string_map_element(ip_to_bandwidth,next_ip); - if(bw_list == NULL) - { - bw_list = (uint64_t*)malloc(sizeof(uint64_t)*6); - bw_list[0] = 0; - bw_list[1] = 0; - bw_list[2] = 0; - bw_list[3] = 0; - bw_list[4] = 0; - bw_list[5] = 0; - set_string_map_element(ip_to_bandwidth, next_ip, bw_list); - } - bw_list[type_index] = 1; - bw_list[type_index+3] = next.bw; - - char bw_str[50]; - sprintf(bw_str, "%lld", next.bw); - double bw_percent; - double bw_limit; - uint64_t bw_limit_64; - sscanf(bw_str, "%lf", &bw_percent); - sscanf(limit, "%lf", &bw_limit); - sscanf(limit, "%lld", &bw_limit_64); - if(bw_limit > 0) - { - bw_percent = (bw_percent*100.0)/bw_limit; - bw_percent = bw_percent > 100.0 ? 100.0 : bw_percent; - } - else - { - bw_percent = 100.0; - } - - double* percent_list = get_string_map_element(ip_to_percents, next_ip); - if(percent_list == NULL) - { - percent_list = (double*)malloc(sizeof(double)*3); - percent_list[0] = -1; - percent_list[1] = -1; - percent_list[2] = -1; - set_string_map_element(ip_to_percents, next_ip, percent_list); - } - percent_list[type_index] = bw_percent; - - uint64_t* limit_list = get_string_map_element(ip_to_limits, next_ip); - if(limit_list == NULL) - { - limit_list = (uint64_t*)malloc(sizeof(uint64_t)*3); - limit_list[0] = -1; - limit_list[1] = -1; - limit_list[2] = -1; - set_string_map_element(ip_to_limits, next_ip, limit_list); - } - limit_list[type_index] = bw_limit_64; - } - } - free(type_id); - free(limit); - } - } - free(id); - free(ip); - free(next_quota); - } - - unsigned long num_ids; - char** id_list = (char**)get_string_map_keys(id_ip_to_bandwidth, &num_ids); - printf("var quotaIdList = [ "); - char print_comma[10] = ""; - unsigned long id_index; - for(id_index=0; id_index < num_ids; id_index++) - { - printf("%s\"%s\"", print_comma, id_list[id_index]); - sprintf(print_comma, ", "); - } - printf(" ];\n"); - - printf("var quotaIpLists = [];\n"); - for(id_index=0; id_index < num_ids; id_index++) - { - string_map* ip_to_bandwidth = get_string_map_element(id_ip_to_bandwidth, id_list[id_index]); - if(ip_to_bandwidth != NULL) - { - unsigned long num_ips = 0; - unsigned long ip_index = 0; - char** ip_list = (char**)get_string_map_keys(ip_to_bandwidth, &num_ips); - printf("quotaIpLists[\"%s\"] = [ ", id_list[id_index]); - sprintf(print_comma, ""); - for(ip_index=0; ip_index < num_ips; ip_index++) - { - printf("%s\"%s\"", print_comma, ip_list[ip_index]); - sprintf(print_comma, ", "); - } - printf("];\n"); - } - } - - printf("var quotaTimes = new Array();\n"); - printf("var quotaUsed = new Array();\n"); - printf("var quotaLimits = new Array();\n"); - printf("var quotaPercents = new Array();\n"); - - char* next_time = shift_list(id_to_time); - while(next_time != NULL) - { - printf("%s\n", next_time); - next_time = shift_list(id_to_time); - } - - for(id_index=0; id_index < num_ids; id_index++) - { - char* next_id = id_list[id_index]; - string_map* ip_to_bandwidth = get_string_map_element(id_ip_to_bandwidth, next_id); - string_map* ip_to_percents = get_string_map_element(id_ip_to_percents, next_id); - string_map* ip_to_limits = get_string_map_element(id_ip_to_limits, next_id); - - printf("quotaUsed[ \"%s\" ] = [];\n", next_id); - printf("quotaPercents[ \"%s\" ] = [];\n", next_id); - printf("quotaLimits[ \"%s\" ] = [];\n", next_id); - - if(ip_to_bandwidth != NULL) - { - unsigned long num_ips; - unsigned long ip_index = 0; - char** ip_list = (char**)get_string_map_keys(ip_to_bandwidth, &num_ips); - for(ip_index=0; ip_index < num_ips; ip_index++) - { - char* next_ip = ip_list[ip_index]; - uint64_t* used = (uint64_t*)get_string_map_element(ip_to_bandwidth, next_ip); - double* percents = (double*)get_string_map_element(ip_to_percents, next_ip); - uint64_t* limits = (uint64_t*)get_string_map_element(ip_to_limits, next_ip); - - if(used != NULL) - { - int type_index; - printf("quotaUsed[ \"%s\" ][ \"%s\" ] = [ ", next_id, next_ip); - sprintf(print_comma, ""); - for(type_index=0; type_index < 3; type_index++) - { - if(!used[type_index]) - { - printf("%s-1", print_comma); - } - else - { - printf("%s%lld", print_comma, (long long int)used[type_index+3]); - } - sprintf(print_comma, ", "); - } - printf(" ];\n"); - - printf("quotaPercents[ \"%s\" ][ \"%s\" ] = [ ", next_id, next_ip); - sprintf(print_comma, ""); - for(type_index=0; type_index < 3; type_index++) - { - printf("%s%6.3lf", print_comma, percents[type_index]); - sprintf(print_comma, ", "); - } - printf(" ];\n"); - - printf("quotaLimits[ \"%s\" ][ \"%s\" ] = [ ", next_id, next_ip); - sprintf(print_comma, ""); - for(type_index=0; type_index < 3; type_index++) - { - printf("%s%lld", print_comma,limits[type_index]); - sprintf(print_comma, ", "); - } - printf(" ];\n"); - } - } - } - } - - unsigned long num; - destroy_list(quota_sections, DESTROY_MODE_FREE_VALUES, &num); - uci_free_context(ctx); - - return 0; -} - -list* get_all_sections_of_type(struct uci_context *ctx, char* package, char* section_type) -{ - - struct uci_package *p = NULL; - struct uci_element *e = NULL; - - list* sections_of_type = initialize_list(); - if(uci_load(ctx, package, &p) == UCI_OK) - { - uci_foreach_element( &p->sections, e) - { - struct uci_section *section = uci_to_section(e); - if(safe_strcmp(section->type, section_type) == 0) - { - push_list(sections_of_type, strdup(section->e.name)); - } - } - } - return sections_of_type; -} - -char* get_uci_option(struct uci_context* ctx, char* package_name, char* section_name, char* option_name) -{ - char* option_value = NULL; - struct uci_ptr ptr; - char* lookup_str = dynamic_strcat(5, package_name, ".", section_name, ".", option_name); - int ret_value = uci_lookup_ptr(ctx, &ptr, lookup_str, 1); - if(ret_value == UCI_OK) - { - if( !(ptr.flags & UCI_LOOKUP_COMPLETE)) - { - ret_value = UCI_ERR_NOTFOUND; - } - else - { - struct uci_element *e = (struct uci_element*)ptr.o; - option_value = get_option_value_string(uci_to_option(e)); - } - } - free(lookup_str); - - return option_value; -} - -// this function dynamically allocates memory for -// the option string, but since this program exits -// almost immediately (after printing variable info) -// the massive memory leak we're opening up shouldn't -// cause any problems. This is your reminder/warning -// that this might be an issue if you use this code to -// do anything fancy. -char* get_option_value_string(struct uci_option* uopt) -{ - char* opt_str = NULL; - if(uopt->type == UCI_TYPE_STRING) - { - opt_str = strdup(uopt->v.string); - } - if(uopt->type == UCI_TYPE_LIST) - { - struct uci_element* e; - uci_foreach_element(&uopt->v.list, e) - { - if(opt_str == NULL) - { - opt_str = strdup(e->name); - } - else - { - char* tmp; - tmp = dynamic_strcat(3, opt_str, " ", e->name); - free(opt_str); - opt_str = tmp; - } - } - } - - return opt_str; -} diff --git a/package/jsda/gargoyle-firewall-util/src/restore_quotas.c b/package/jsda/gargoyle-firewall-util/src/restore_quotas.c deleted file mode 100644 index dac4c63f4d..0000000000 --- a/package/jsda/gargoyle-firewall-util/src/restore_quotas.c +++ /dev/null @@ -1,1071 +0,0 @@ -/* restore_quotas -- Used to initialize and restore bandwidth quotas based on UCI config files - * and any previously saved quota data in /usr/data/quotas - * Originally designed for use with Gargoyle router firmware (gargoyle-router.com) - * - * - * Copyright © 2009-2010 by Eric Bishop - * - * This file is free software: you may copy, redistribute 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 file 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 -#include -#include -#define malloc safe_malloc -#define strdup safe_strdup - -#define INGRESS_INDEX 0 -#define EGRESS_INDEX 1 -#define COMBINED_INDEX 2 - -void restore_backup_for_id(char* id, char* quota_backup_dir, unsigned char is_individual_other, list* defined_ip_groups); -uint32_t ip_to_host_int(char* ip_str); -uint32_t* ip_range_to_host_ints(char* ip_str); -list* filter_group_from_list(list** orig_ip_list, char* ip_group_str); - -void delete_chain_from_table(char* table, char* delete_chain); -void run_shell_command(char* command, int free_command_str); -void free_split_pieces(char** split_pieces); - -list* get_all_sections_of_type(struct uci_context *ctx, char* package, char* section_type); -char* get_uci_option(struct uci_context* ctx,char* package_name, char* section_name, char* option_name); -char* get_option_value_string(struct uci_option* uopt); - -int main(int argc, char** argv) -{ - - char* wan_if = NULL; - char* local_subnet = NULL; - char* death_mark = NULL; - char* death_mask = NULL; - char* crontab_line = NULL; - int ret; - - unsigned char full_qos_active = 0; - - char c; - while((ret = getopt(argc, argv, "W:w:s:S:d:D:m:M:c:C:qQ")) != -1) //section, page, css includes, javascript includes, title, output interface variables - { - c = ret; - switch(c) - { - case 'W': - case 'w': - wan_if = strdup(optarg); - break; - case 'S': - case 's': - local_subnet = strdup(optarg); - break; - case 'D': - case 'd': - death_mark = strdup(optarg); - break; - case 'M': - case 'm': - death_mask = strdup(optarg); - break; - case 'C': - case 'c': - crontab_line = strdup(optarg); - break; - case 'Q': - case 'q': - full_qos_active = 1; - break; - } - } - - /* even if parameters are wrong, whack old rules */ - char quota_table[] = "mangle"; - char crontab_dir[] = "/etc/crontabs/"; - char crontab_file_path[] = "/etc/crontabs/root"; - delete_chain_from_table(quota_table, "egress_quotas"); - delete_chain_from_table(quota_table, "ingress_quotas"); - delete_chain_from_table(quota_table, "combined_quotas"); - delete_chain_from_table(quota_table, "forward_quotas"); - delete_chain_from_table("nat", "quota_redirects"); - - if(wan_if == NULL) - { - fprintf(stderr, "ERRROR: No wan interface specified\n"); - return 0; - } - if(local_subnet == NULL) - { - fprintf(stderr, "ERRROR: No local subnet specified\n"); - return 0; - } - if(death_mark == NULL) - { - fprintf(stderr, "ERRROR: No death mark specified\n"); - return 0; - } - if(death_mask == NULL) - { - fprintf(stderr, "ERRROR: No death mask specified\n"); - return 0; - } - - struct uci_context *ctx = uci_alloc_context(); - struct uci_ptr ptr; - - list* quota_sections = get_all_sections_of_type(ctx, "firewall", "quota"); - if(quota_sections->length > 0) - { - /* load defined base ids */ - string_map* defined_base_ids = initialize_string_map(0); - string_map* upload_qos_marks = initialize_string_map(0); - string_map* download_qos_marks = initialize_string_map(0); - - long_map* up_speeds = initialize_long_map(); - long_map* down_speeds = initialize_long_map(); - list* quota_section_buf = initialize_list(); - while(quota_sections->length > 0) - { - char* next_quota = shift_list(quota_sections); - char* base_id = get_uci_option(ctx, "firewall", next_quota, "id"); - char* exceeded_up_speed_str = get_uci_option(ctx, "firewall", next_quota, "exceeded_up_speed"); - char* exceeded_down_speed_str = get_uci_option(ctx, "firewall", next_quota, "exceeded_down_speed"); - - if(base_id != NULL) - { - //D, for dummy place holder - char* oldval = set_string_map_element(defined_base_ids, base_id, strdup("D") ); - if(oldval != NULL) { free(oldval); } - } - push_list(quota_section_buf, next_quota); - - if(exceeded_up_speed_str != NULL && exceeded_down_speed_str != NULL) - { - long up; - long down; - if(sscanf(exceeded_up_speed_str, "%ld", &up) > 0 && sscanf(exceeded_down_speed_str, "%ld", &down) > 0 ) - { - if(up > 0 && down > 0) - { - char* oldval = set_long_map_element(up_speeds, up, strdup(exceeded_up_speed_str) ); - if(oldval != NULL) { free(oldval); } - oldval = set_long_map_element(down_speeds, down, strdup(exceeded_down_speed_str) ); - if(oldval != NULL) { free(oldval); } - } - } - } - free(base_id); - free(exceeded_up_speed_str); - free(exceeded_down_speed_str); - } - unsigned long num_destroyed; - destroy_list(quota_sections, DESTROY_MODE_FREE_VALUES, &num_destroyed); - quota_sections = quota_section_buf; - - /* initialize qos mark maps */ - unsigned long mark_band = 2; - int upload_shift = 0; - int download_shift = 8; - while(up_speeds->num_elements > 0) - { - unsigned long mark = mark_band << upload_shift; - char mark_str[10]; - unsigned long smallest_speed; - char* next_up_speed = remove_smallest_long_map_element(up_speeds, &smallest_speed); - sprintf(mark_str, "%ld", mark); - set_string_map_element(upload_qos_marks, next_up_speed, strdup(mark_str)); - free(next_up_speed); - mark_band++; - } - mark_band = 2; - while(down_speeds->num_elements > 0) - { - unsigned long mark = mark_band << download_shift; - char mark_str[10]; - unsigned long smallest_speed; - char* next_down_speed = remove_smallest_long_map_element(down_speeds, &smallest_speed); - sprintf(mark_str, "%ld", mark); - set_string_map_element(download_qos_marks, next_down_speed, strdup(mark_str)); - free(next_down_speed); - mark_band++; - } - - /* initialize chains */ - run_shell_command(dynamic_strcat(3, "iptables -t ", quota_table, " -N forward_quotas 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(3, "iptables -t ", quota_table, " -N egress_quotas 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(3, "iptables -t ", quota_table, " -N ingress_quotas 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(3, "iptables -t ", quota_table, " -N combined_quotas 2>/dev/null"), 1); - - run_shell_command("iptables -t nat -N quota_redirects 2>/dev/null", 0); - run_shell_command("iptables -t nat -A quota_redirects -j CONNMARK --set-mark 0x0/0xFF000000 2>/dev/null", 0); - run_shell_command("iptables -t nat -I zone_lan_prerouting -j quota_redirects 2>/dev/null", 0); - - char* no_death_mark_test = dynamic_strcat(3, " -m connmark --mark 0x0/", death_mask, " "); - run_shell_command(dynamic_strcat(6, "iptables -t ", quota_table, " -I INPUT 1 -i ", wan_if, no_death_mark_test, " -j ingress_quotas 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(6, "iptables -t ", quota_table, " -I INPUT 2 -i ", wan_if, no_death_mark_test, " -j combined_quotas 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(6, "iptables -t ", quota_table, " -I OUTPUT 1 -o ", wan_if, no_death_mark_test, " -j egress_quotas 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(6, "iptables -t ", quota_table, " -I OUTPUT 2 -o ", wan_if, no_death_mark_test, " -j combined_quotas 2>/dev/null"), 1); - - run_shell_command(dynamic_strcat(3, "iptables -t ", quota_table, " -I FORWARD -j forward_quotas 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(6, "iptables -t ", quota_table, " -A forward_quotas -o ", wan_if, no_death_mark_test, " -j egress_quotas 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(6, "iptables -t ", quota_table, " -A forward_quotas -i ", wan_if, no_death_mark_test, " -j ingress_quotas 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(6, "iptables -t ", quota_table, " -A forward_quotas -i ", wan_if, no_death_mark_test, " -j CONNMARK --set-mark 0x0F000000/0x0F000000 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(6, "iptables -t ", quota_table, " -A forward_quotas -o ", wan_if, no_death_mark_test, " -j CONNMARK --set-mark 0x0F000000/0x0F000000 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(3, "iptables -t ", quota_table, " -A forward_quotas -m connmark --mark 0x0F000000/0x0F000000 -j combined_quotas 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(3, "iptables -t ", quota_table, " -A forward_quotas -j CONNMARK --set-mark 0x0/0x0F000000 2>/dev/null"), 1); - free(no_death_mark_test); - - run_shell_command(dynamic_strcat(5, "iptables -t ", quota_table, " -A egress_quotas -j CONNMARK --set-mark 0x0/", death_mask, " 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(5, "iptables -t ", quota_table, " -A ingress_quotas -j CONNMARK --set-mark 0x0/", death_mask, " 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(5, "iptables -t ", quota_table, " -A combined_quotas -j CONNMARK --set-mark 0x0/", death_mask, " 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(3, "iptables -t ", quota_table, " -A egress_quotas -j CONNMARK --set-mark 0x0/0xFF000000 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(3, "iptables -t ", quota_table, " -A ingress_quotas -j CONNMARK --set-mark 0x0/0xFF000000 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(3, "iptables -t ", quota_table, " -A combined_quotas -j CONNMARK --set-mark 0x0/0xFF000000 2>/dev/null"), 1); - - /* add rules */ - char* set_death_mark = dynamic_strcat(5, " -j CONNMARK --set-mark ", death_mark, "/", death_mask, " "); - list* other_quota_section_names = initialize_list(); - list* defined_ip_groups = initialize_list(); - - unlock_bandwidth_semaphore_on_exit(); - while(quota_sections->length > 0 || other_quota_section_names->length > 0) - { - char* next_quota = NULL; - int process_other_quota = 0; - if(quota_sections->length > 0) - { - next_quota = shift_list(quota_sections); - } - else - { - process_other_quota = 1; - next_quota = shift_list(other_quota_section_names); - } - - char* quota_enabled_var = get_uci_option(ctx, "firewall", next_quota, "enabled"); - int enabled = 1; - if(quota_enabled_var != NULL) - { - if(strcmp(quota_enabled_var, "0") == 0) - { - enabled = 0; - } - } - free(quota_enabled_var); - - if(enabled) - { - char* ip = get_uci_option(ctx, "firewall", next_quota, "ip"); - char* exceeded_up_speed_str = NULL; - char* exceeded_down_speed_str = NULL; - if(!full_qos_active) /* without defined up/down speeds we always set hard cutoff, which is what we want when full qos is active */ - { - exceeded_up_speed_str = get_uci_option(ctx, "firewall", next_quota, "exceeded_up_speed"); - exceeded_down_speed_str = get_uci_option(ctx, "firewall", next_quota, "exceeded_down_speed"); - } - if(exceeded_up_speed_str == NULL) { exceeded_up_speed_str = strdup(" "); } - if(exceeded_down_speed_str == NULL) { exceeded_down_speed_str = strdup(" "); } - - - if(ip == NULL) { ip = strdup("ALL"); } - if(strlen(ip) == 0) { ip = strdup("ALL"); } - - /* remove spaces in ip range definitions */ - while(strstr(ip, " -") != NULL) - { - char* tmp_ip = ip; - ip = dynamic_replace(ip, " -", "-"); - free(tmp_ip); - } - while(strstr(ip, "- ") != NULL) - { - char* tmp_ip = ip; - ip = dynamic_replace(ip, "- ", "-"); - free(tmp_ip); - } - - if( (strcmp(ip, "ALL_OTHERS_COMBINED") == 0 || strcmp(ip, "ALL_OTHERS_INDIVIDUAL") == 0) && (!process_other_quota) ) - { - push_list(other_quota_section_names, strdup(next_quota)); - } - else - { - unsigned char is_individual_other = strcmp(ip, "ALL_OTHERS_INDIVIDUAL") == 0 ? 1 : 0; - if( strcmp(ip, "ALL_OTHERS_COMBINED") != 0 && strcmp(ip, "ALL_OTHERS_INDIVIDUAL") != 0 && strcmp(ip, "ALL") != 0 ) - { - /* this is an explicitly defined ip or ip range, so save it for later, to deal with individual other overlap problem */ - push_list(defined_ip_groups, strdup(ip)); - } - - /* compute proper base id for rule, adding variable to uci if necessary */ - char* quota_base_id = get_uci_option(ctx, "firewall", next_quota, "id"); - if(quota_base_id == NULL) - { - char id_breaks[] = { ',', ' ', '\t'}; - unsigned long num_pieces; - char** split_ip = split_on_separators(ip, id_breaks, 3, -1, 0, &num_pieces); - char* first_ip = dynamic_replace(split_ip[0], "/", "_"); - free_null_terminated_string_array(split_ip); - - quota_base_id = strdup(first_ip); - unsigned long next_postfix_count = 0; - while( get_string_map_element(defined_base_ids, quota_base_id) != NULL) - { - char next_postfix[20]; - if(next_postfix_count > 25) - { - sprintf(next_postfix, "_%c", ('A' + next_postfix_count)); - } - else - { - sprintf(next_postfix, "_Z%ld", (next_postfix_count - 25)); - } - free(quota_base_id); - quota_base_id = dynamic_strcat(2, first_ip, next_postfix); - } - free(first_ip); - - /* D for dummy place holder */ - set_string_map_element(defined_base_ids, quota_base_id, strdup("D")); - - /* add id we've decided on to UCI */ - char* var_set = dynamic_strcat(4, "firewall.", next_quota, ".id=", quota_base_id); - if (uci_lookup_ptr(ctx, &ptr, var_set, true) == UCI_OK) - { - uci_set(ctx, &ptr); - } - } - - char* ignore_backup = get_uci_option(ctx, "firewall", next_quota, "ignore_backup_at_next_restore"); - int do_restore = 1; - if(ignore_backup != NULL) - { - do_restore = strcmp(ignore_backup, "1") == 0 ? 0 : 1; - if(!do_restore) - { - //remove variable from uci - char* var_name = dynamic_strcat(3, "firewall.", next_quota, ".ignore_backup_at_next_restore"); - if (uci_lookup_ptr(ctx, &ptr, var_name, true) == UCI_OK) - { - uci_delete(ctx, &ptr); - } - free(var_name); - } - } - free(ignore_backup); - - char* reset_interval = get_uci_option(ctx, "firewall", next_quota, "reset_interval"); - char* reset = strdup(""); - if(reset_interval != NULL) - { - char* reset_time = get_uci_option(ctx, "firewall", next_quota, "reset_time"); - - char* interval_option = strdup(" --reset_interval "); - reset = dcat_and_free(&reset, &interval_option, 1, 1); - reset = dcat_and_free(&reset, &reset_interval, 1, 1); - if(reset_time != NULL) - { - char* reset_option = strdup(" --reset_time "); - reset = dcat_and_free(&reset, &reset_option, 1, 1); - reset = dcat_and_free(&reset, &reset_time, 1, 1); - } - } - - char* time_match_str = strdup(""); - - char* offpeak_hours = get_uci_option(ctx, "firewall", next_quota, "offpeak_hours"); - char* offpeak_weekdays = get_uci_option(ctx, "firewall", next_quota, "offpeak_weekdays"); - char* offpeak_weekly_ranges = get_uci_option(ctx, "firewall", next_quota, "offpeak_weekly_ranges"); - - char* onpeak_hours = get_uci_option(ctx, "firewall", next_quota, "onpeak_hours"); - char* onpeak_weekdays = get_uci_option(ctx, "firewall", next_quota, "onpeak_weekdays"); - char* onpeak_weekly_ranges = get_uci_option(ctx, "firewall", next_quota, "onpeak_weekly_ranges"); - - if(offpeak_hours != NULL || offpeak_weekdays != NULL || offpeak_weekly_ranges != NULL || onpeak_hours != NULL || onpeak_weekdays != NULL || onpeak_weekly_ranges != NULL) - { - unsigned char is_off_peak = (offpeak_hours != NULL || offpeak_weekdays != NULL || offpeak_weekly_ranges != NULL) ? 1 : 0; - char* hours_var = is_off_peak ? offpeak_hours : onpeak_hours; - char* weekdays_var = is_off_peak ? offpeak_weekdays : onpeak_weekdays; - char* weekly_ranges_var = is_off_peak ? offpeak_weekly_ranges : onpeak_weekly_ranges; - - char *timerange_match = is_off_peak ? strdup(" -m timerange ! ") : strdup(" -m timerange "); - char *hour_match = strdup(" --hours \""); - char *weekday_match = strdup(" --weekdays \""); - char *weekly_match = strdup(" --weekly_ranges \""); - char *quote_end = strdup("\" "); - - time_match_str = dcat_and_free(&time_match_str, &timerange_match, 1,1); - if(hours_var != NULL && weekly_ranges_var == NULL) - { - time_match_str = dcat_and_free(&time_match_str, &hour_match, 1, 1); - time_match_str = dcat_and_free(&time_match_str, &hours_var, 1, 1); - time_match_str = dcat_and_free(&time_match_str, "e_end, 1, 0); - } - if(weekdays_var != NULL && weekly_ranges_var == NULL) - { - time_match_str = dcat_and_free(&time_match_str, &weekday_match, 1, 1); - time_match_str = dcat_and_free(&time_match_str, &weekdays_var, 1, 1); - time_match_str = dcat_and_free(&time_match_str, "e_end, 1, 0); - } - if(weekly_ranges_var != NULL) - { - time_match_str = dcat_and_free(&time_match_str, &weekly_match, 1, 1); - time_match_str = dcat_and_free(&time_match_str, &weekly_ranges_var, 1, 1); - time_match_str = dcat_and_free(&time_match_str, "e_end, 1, 0); - } - free(quote_end); - } - - char* types[] = { "ingress_limit", "egress_limit", "combined_limit" }; - char* postfixes[] = { "_ingress", "_egress", "_combined" }; - char* chains[] = { "ingress_quotas", "egress_quotas", "combined_quotas" }; - - int type_index; - for(type_index=0; type_index < 3; type_index++) - { - char** ip_egress_tests = NULL; - char* applies_to = strdup("combined"); - char* subnet_definition = strdup(""); - - char* limit = get_uci_option(ctx, "firewall", next_quota, types[type_index]); - - char* type_id = dynamic_strcat(2, quota_base_id, postfixes[type_index] ); - - char* up_qos_mark = get_string_map_element(upload_qos_marks, exceeded_up_speed_str); - char* down_qos_mark = get_string_map_element(download_qos_marks, exceeded_down_speed_str); - if(full_qos_active) - { - up_qos_mark = get_uci_option(ctx, "firewall", next_quota, "exceeded_up_class_mark"); - down_qos_mark = get_uci_option(ctx, "firewall", next_quota, "exceeded_down_class_mark"); - } - - /* - * need to do ip test even if limit is null, because ALL_OTHERS quotas should not apply when any of the three types of explicit limit is defined - * and we therefore need to use this test to set mark indicating an explicit quota has been checked - */ - char* ip_test = strdup(""); - if( strcmp(ip, "ALL_OTHERS_COMBINED") != 0 && strcmp(ip, "ALL_OTHERS_INDIVIDUAL") != 0 && strcmp(ip, "ALL") != 0 ) - { - - char* src_test = strstr(ip, "-") == NULL ? dynamic_strcat(3, " --src ", ip, " ") : dynamic_strcat(3, " -m iprange --src-range ", ip, " "); - char* dst_test = strstr(ip, "-") == NULL ? dynamic_strcat(3, " --dst ", ip, " ") : dynamic_strcat(3, " -m iprange --dst-range ", ip, " "); - - if(strstr(ip, ",") != NULL || strstr(ip, " ") != NULL || strstr(ip, "\t") != NULL ) - { - char ip_breaks[] = { ',', ' ', '\t' }; - unsigned long num_ips = 0; - char** ip_list = split_on_separators(ip, ip_breaks, 3, -1, 0, &num_ips); - unsigned long ip_index; - for(ip_index=0; ip_index < num_ips; ip_index++) - { - char *next_ip = ip_list[ip_index]; - char* egress_test = strstr(next_ip, "-") == NULL ? dynamic_strcat(3, " --src ", next_ip, " ") : dynamic_strcat(3, " -m iprange --src-range ", next_ip, " "); - char* ingress_test = strstr(next_ip, "-") == NULL ? dynamic_strcat(3, " --dst ", next_ip, " ") : dynamic_strcat(3, " -m iprange --dst-range ", next_ip, " "); - - if(strcmp(types[type_index], "egress_limit") == 0) - { - run_shell_command(dynamic_strcat(6, "iptables -t ", quota_table, " -A ", chains[type_index], egress_test, " -j CONNMARK --set-mark 0x0F000000/0x0F000000 2>/dev/null"), 1); - } - else if(strcmp(types[type_index], "ingress_limit") == 0) - { - run_shell_command(dynamic_strcat(6, "iptables -t ", quota_table, " -A ", chains[type_index], ingress_test, " -j CONNMARK --set-mark 0x0F000000/0x0F000000 2>/dev/null"), 1); - } - else if(strcmp(types[type_index], "combined_limit") == 0) - { - run_shell_command(dynamic_strcat(8, "iptables -t ", quota_table, " -A ", chains[type_index], " -i ", wan_if, ingress_test, " -j CONNMARK --set-mark 0x0F000000/0x0F000000 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(8, "iptables -t ", quota_table, " -A ", chains[type_index], " -o ", wan_if, egress_test, " -j CONNMARK --set-mark 0x0F000000/0x0F000000 2>/dev/null"), 1); - } - ip_list[ip_index] = egress_test; - free(next_ip); - free(ingress_test); - } - ip_egress_tests = ip_list; - char* rule_end = strdup(" -m connmark --mark 0x0F000000/0x0F000000 "); - ip_test = dcat_and_free(&ip_test, &rule_end, 1, 1); - } - else if(strcmp(types[type_index], "egress_limit") == 0) - { - ip_test=dcat_and_free(&ip_test, &src_test, 1, 0); - } - else if(strcmp(types[type_index], "ingress_limit") == 0) - { - ip_test=dcat_and_free(&ip_test, &dst_test, 1, 0); - } - else if(strcmp(types[type_index], "combined_limit") == 0) - { - run_shell_command(dynamic_strcat(8, "iptables -t ", quota_table, " -A ", chains[type_index], " -i ", wan_if, dst_test, " -j CONNMARK --set-mark 0x0F000000/0x0F000000 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(8, "iptables -t ", quota_table, " -A ", chains[type_index], " -o ", wan_if, src_test, " -j CONNMARK --set-mark 0x0F000000/0x0F000000 2>/dev/null"), 1); - char* rule_end = strdup(" -m connmark --mark 0x0F000000/0x0F000000 "); - ip_test = dcat_and_free(&ip_test, &rule_end, 1, 1); - } - run_shell_command(dynamic_strcat(6, "iptables -t ", quota_table, " -A ", chains[type_index], ip_test, " -j CONNMARK --set-mark 0xF0000000/0xF0000000 2>/dev/null"), 1); - free(dst_test); - free(src_test); - } - else if( strcmp(ip, "ALL_OTHERS_COMBINED") == 0 || strcmp(ip, "ALL_OTHERS_INDIVIDUAL") == 0 ) - { - char* rule_end = strdup(" -m connmark --mark 0x0/0xF0000000 "); - ip_test=dcat_and_free(&ip_test, &rule_end, 1, 1); - if(strcmp(ip, "ALL_OTHERS_INDIVIDUAL") == 0) - { - free(applies_to); - if(strcmp(types[type_index], "egress_limit") == 0) - { - char* subnet_test = dynamic_strcat(3, " -s ", local_subnet, " "); - ip_test = dcat_and_free(&subnet_test, &ip_test, 1, 1); - applies_to = strdup("individual_src"); - } - else if(strcmp(types[type_index], "ingress_limit") == 0) - { - char* subnet_test = dynamic_strcat(3, " -d ", local_subnet, " "); - ip_test = dcat_and_free(&subnet_test, &ip_test, 1, 1); - applies_to = strdup("individual_dst"); - } - else if(strcmp(types[type_index], "combined_limit") == 0) - { - applies_to = strdup("individual_local"); - } - - char *subnet_option = strdup(" --subnet "); - subnet_definition = dcat_and_free(&subnet_definition, &subnet_option, 1, 1); - subnet_definition = dcat_and_free(&subnet_definition, &local_subnet, 1, 0); - } - } - - if(up_qos_mark != NULL && down_qos_mark != NULL) - { - char* set_egress_mark = dynamic_strcat(2, " -j MARK --set-mark ", up_qos_mark); - char* set_ingress_mark = dynamic_strcat(2, " -j MARK --set-mark ", down_qos_mark); - if(type_index == EGRESS_INDEX || type_index == INGRESS_INDEX) - { - int other_type_index= type_index == EGRESS_INDEX ? INGRESS_INDEX : EGRESS_INDEX; - char* other_limit = get_uci_option(ctx, "firewall", next_quota, types[other_type_index]); - if(other_limit != NULL) - { - char* other_type_id = dynamic_strcat(2, quota_base_id, postfixes[other_type_index] ); - if(type_index == EGRESS_INDEX) - { - run_shell_command(dynamic_strcat(10, "iptables -t ", quota_table, " -A ", chains[type_index], ip_test, time_match_str, " -m bandwidth --id \"", other_type_id, "\" --bcheck_with_src_dst_swap ", set_egress_mark), 1); - } - else - { - run_shell_command(dynamic_strcat(10, "iptables -t ", quota_table, " -A ", chains[type_index], ip_test, time_match_str, " -m bandwidth --id \"", other_type_id, "\" --bcheck_with_src_dst_swap ", set_ingress_mark), 1); - } - free(other_type_id); - } - free(other_limit); - } - free(set_egress_mark); - free(set_ingress_mark); - } - - if(limit != NULL) - { - if(up_qos_mark != NULL && down_qos_mark != NULL) - { - char* set_egress_mark = dynamic_strcat(2, " -j MARK --set-mark ", up_qos_mark); - char* set_ingress_mark = dynamic_strcat(2, " -j MARK --set-mark ", down_qos_mark); - if(strcmp(types[type_index], "egress_limit") == 0) - { - run_shell_command(dynamic_strcat(15, "iptables -t ", quota_table, " -A ", chains[type_index], ip_test, time_match_str, " -m bandwidth --id \"", type_id, "\" --type ", applies_to, subnet_definition, " --greater_than ", limit, reset, set_egress_mark), 1); - } - else if(strcmp(types[type_index], "ingress_limit") == 0) - { - run_shell_command(dynamic_strcat(15, "iptables -t ", quota_table, " -A ", chains[type_index], ip_test, time_match_str, " -m bandwidth --id \"", type_id, "\" --type ", applies_to, subnet_definition, " --greater_than ", limit, reset, set_ingress_mark), 1); - } - else //combined - { - run_shell_command(dynamic_strcat(14, "iptables -t ", quota_table, " -A ", chains[type_index], ip_test, time_match_str, " -m bandwidth --id \"", type_id, "\" --type ", applies_to, subnet_definition, " --greater_than ", limit, reset), 1); - run_shell_command(dynamic_strcat(13, "iptables -t ", quota_table, " -A ", chains[type_index], " -o ", wan_if, " ", ip_test, time_match_str, " -m bandwidth --id \"", type_id, "\" --bcheck ", set_egress_mark), 1); //egress - run_shell_command(dynamic_strcat(13, "iptables -t ", quota_table, " -A ", chains[type_index], " -i ", wan_if, " ", ip_test, time_match_str, " -m bandwidth --id \"", type_id, "\" --bcheck_with_src_dst_swap ", set_ingress_mark), 1); //ingress - } - free(set_egress_mark); - free(set_ingress_mark); - } - else - { - //insert quota block rule - run_shell_command(dynamic_strcat(15, "iptables -t ", quota_table, " -A ", chains[type_index], ip_test, time_match_str, " -m bandwidth --id \"", type_id, "\" --type ", applies_to, subnet_definition, " --greater_than ", limit, reset, set_death_mark), 1); - - //insert redirect rule - if(strcmp(ip, "ALL") == 0 || strcmp(ip, "ALL_OTHERS_INDIVIDUAL") == 0) - { - char* check_str = (strcmp(types[type_index], "ingress_limit") == 0) ? strdup(" --bcheck_with_src_dst_swap ") : strdup(" --bcheck "); - run_shell_command(dynamic_strcat(7, "iptables -t nat -A quota_redirects -p tcp ", time_match_str, " -m multiport --destination-port 80,443 -m bandwidth ", check_str, " --id \"", type_id, "\" -j REDIRECT "), 1); - free(check_str); - } - else if(strcmp(ip, "ALL_OTHERS_COMBINED") == 0) - { - run_shell_command(dynamic_strcat(5, "iptables -t nat -A quota_redirects -p tcp ", time_match_str, " -m connmark --mark 0x0/0xF0000000 -m multiport --destination-port 80,443 -m bandwidth --bcheck --id \"", type_id, "\" -j REDIRECT "), 1); - } - else - { - if(ip_egress_tests != NULL) - { - unsigned long egress_test_index; - for(egress_test_index=0; ip_egress_tests[egress_test_index] != NULL; egress_test_index++ ) - { - run_shell_command(dynamic_strcat(3, "iptables -t nat -A quota_redirects ", ip_egress_tests[egress_test_index], " -j CONNMARK --set-mark 0x0F000000/0x0F000000 2>/dev/null"), 1); - } - } - else - { - run_shell_command(dynamic_strcat(4, "iptables -t nat -A quota_redirects ", ( strstr(ip, "-") == NULL ? " --src " : " -m iprange --src-range "), ip, " -j CONNMARK --set-mark 0x0F000000/0x0F000000 2>/dev/null"), 1); - } - run_shell_command(dynamic_strcat(5, "iptables -t nat -A quota_redirects -p tcp ", time_match_str, " -m connmark --mark 0x0F000000/0x0F000000 -m multiport --destination-port 80,443 -m bandwidth --bcheck --id \"", type_id, "\" -j REDIRECT "), 1); - run_shell_command("iptables -t nat -A quota_redirects -m connmark --mark 0x0F000000/0x0F000000 -j CONNMARK --set-mark 0xF0000000/0xF0000000 2>/dev/null", 0); - run_shell_command("iptables -t nat -A quota_redirects -j CONNMARK --set-mark 0x0/0x0F000000 2>/dev/null", 0); - } - } - - //restore from backup - if(do_restore) - { - restore_backup_for_id(type_id, "/usr/data/quotas", is_individual_other, defined_ip_groups); - } - free(limit); - - } - if(strstr(ip_test, "connmark") != NULL) - { - run_shell_command(dynamic_strcat(5, "iptables -t ", quota_table, " -A ", chains[type_index], " -j CONNMARK --set-mark 0x0/0x0F000000 2>/dev/null"), 1); - } - - free(ip_test); - free(applies_to); - free(subnet_definition); - free(type_id); - if(full_qos_active) - { - free(up_qos_mark); - free(down_qos_mark); - } - if(ip_egress_tests != NULL) - { - free_null_terminated_string_array(ip_egress_tests); - } - } - free(time_match_str); - free(quota_base_id); - } - free(ip); - free(exceeded_up_speed_str); - free(exceeded_down_speed_str); - } - free(next_quota); - - } - - run_shell_command("iptables -t nat -A quota_redirects -j CONNMARK --set-mark 0x0/0xFF000000 2>/dev/null", 0); - run_shell_command(dynamic_strcat(3,"iptables -t ", quota_table, " -A egress_quotas -j CONNMARK --set-mark 0x0/0xFF000000 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(3,"iptables -t ", quota_table, " -A ingress_quotas -j CONNMARK --set-mark 0x0/0xFF000000 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(3,"iptables -t ", quota_table, " -A combined_quotas -j CONNMARK --set-mark 0x0/0xFF000000 2>/dev/null"), 1); - run_shell_command(dynamic_strcat(5,"iptables -t filter -I FORWARD -m connmark --mark ", death_mark, "/", death_mask, " -j REJECT 2>/dev/null"), 1); - - //make sure crontab is up to date - if(crontab_line != NULL) - { - FILE* crontab_file = fopen(crontab_file_path,"r"); - int cron_line_found = 0; - if(crontab_file == NULL) - { - run_shell_command(dynamic_strcat(2, "mkdir -p ", crontab_dir), 1); - } - else - { - unsigned long read_length; - char* all_cron_data = (char*)read_entire_file(crontab_file, 2048, &read_length); - fclose(crontab_file); - - unsigned long num_lines; - char linebreaks[] = { '\n', '\r' }; - char** cron_lines = split_on_separators(all_cron_data, linebreaks, 2, -1, 0, &num_lines); - int line_index = 0; - for(line_index=0; line_index < num_lines && (!cron_line_found); line_index++) - { - if(strcmp(cron_lines[line_index], crontab_line) == 0) - { - cron_line_found = 1; - } - } - free_null_terminated_string_array(cron_lines); - } - if(!cron_line_found) - { - crontab_file = fopen(crontab_file_path, "a"); - fprintf(crontab_file, "%s\n", crontab_line); - fclose(crontab_file); - } - } - } - else - { - //remove crontab line if it exists - FILE* crontab_file = fopen(crontab_file_path,"r"); - if(crontab_file != NULL) - { - unsigned long cron_line_found = 0; - unsigned long read_length; - unsigned long num_lines; - char linebreaks[] = { '\n', '\r' }; - char* all_cron_data = (char*)read_entire_file(crontab_file, 2048, &read_length); - fclose(crontab_file); - char** cron_lines = split_on_separators(all_cron_data, linebreaks, 2, -1, 0, &num_lines); - int line_index = 0; - for(line_index=0; line_index < num_lines && (!cron_line_found); line_index++) - { - if(strcmp(cron_lines[line_index], crontab_line) == 0) - { - cron_line_found = 1; - } - } - if(cron_line_found) - { - fopen(crontab_file_path, "w"); - for(line_index=0; line_index < num_lines; line_index++) - { - if(strcmp(cron_lines[line_index], crontab_line) != 0) - { - fprintf(crontab_file, "%s\n", cron_lines[line_index]); - } - } - fclose(crontab_file); - } - free_null_terminated_string_array(cron_lines); - } - } - - /* commit changes to uci, to remove ignore_backup_at_next_restore variables permanently */ - if (uci_lookup_ptr(ctx, &ptr, "firewall", true) == UCI_OK) - { - uci_commit(ctx, &ptr.p, false); - } - uci_free_context(ctx); - - return 0; -} - -void restore_backup_for_id(char* id, char* quota_backup_dir, unsigned char is_individual_other, list* defined_ip_groups) -{ - char* quota_file_path = dynamic_strcat(3, quota_backup_dir, "/quota_", id); - unsigned long num_ips = 0; - time_t last_backup = 0; - ip_bw* loaded_backup_data = load_usage_from_file(quota_file_path, &num_ips, &last_backup); - if(loaded_backup_data != NULL) - { - //printf("restoring quota... id=%s, is_individual_other=%d, num_defined_ip_groups=%d\n", id, is_individual_other, defined_ip_groups->length); - if(is_individual_other) - { - //filter out any ips in the "other" data, that have now been assigned quotas of their own. - list* ip_bw_list = initialize_list(); - int ip_index; - for(ip_index=0; ip_index < num_ips; ip_index++) - { - ip_bw* ptr = loaded_backup_data + ip_index; - push_list(ip_bw_list, ptr); - } - - unsigned long num_groups = 0; - char** group_strs = (char**)get_list_values(defined_ip_groups, &num_groups); - unsigned long group_index; - - for(group_index = 0; group_index < num_groups; group_index++) - { - filter_group_from_list(&ip_bw_list, group_strs[group_index]); - } - - - //rebuild the backup data array from the filtered list - if(num_ips != ip_bw_list->length) - { - num_ips = ip_bw_list->length; - ip_bw* adj_backup = (ip_bw*)malloc( (1+ip_bw_list->length)*sizeof(ip_bw) ); - while(ip_bw_list->length > 0) - { - ip_bw* next = pop_list(ip_bw_list); - adj_backup[ ip_bw_list->length ] = *next; - } - free(loaded_backup_data); - loaded_backup_data = adj_backup; - } - - destroy_list(ip_bw_list, DESTROY_MODE_IGNORE_VALUES, &num_groups); - free(group_strs); //don't want to destroy values, they're still contained in list, so just destroy container array - } - set_bandwidth_usage_for_rule_id(id, 1, num_ips, last_backup, loaded_backup_data, 5000); - } - free(quota_file_path); -} - -list* filter_group_from_list(list** orig_ip_bw_list, char* ip_group_str) -{ - char* dyn_group_str = strdup(ip_group_str); - - /* remove spaces in ip range definitions */ - while(strstr(dyn_group_str, " -") != NULL) - { - char* tmp_group_str = dyn_group_str; - dyn_group_str = dynamic_replace(dyn_group_str, " -", "-"); - free(tmp_group_str); - } - while(strstr(dyn_group_str, "- ") != NULL) - { - char* tmp_group_str = dyn_group_str; - dyn_group_str = dynamic_replace(dyn_group_str, "- ", "-"); - free(tmp_group_str); - } - while(strstr(dyn_group_str, " -") != NULL) - { - char* tmp_group_str = dyn_group_str; - dyn_group_str = dynamic_replace(dyn_group_str, " /", "/"); - free(tmp_group_str); - } - while(strstr(dyn_group_str, "- ") != NULL) - { - char* tmp_group_str = dyn_group_str; - dyn_group_str = dynamic_replace(dyn_group_str, "/ ", "/"); - free(tmp_group_str); - } - - char group_breaks[]= ",\t "; - unsigned long num_groups = 0; - char** split_group = split_on_separators(dyn_group_str, group_breaks, 3, -1, 0, &num_groups); - unsigned long group_index; - - for(group_index = 0; group_index < num_groups; group_index++) - { - uint32_t* range = ip_range_to_host_ints( split_group[group_index] ); - list* new_ip_bw_list = initialize_list(); - while((*orig_ip_bw_list)->length > 0) - { - ip_bw* next_ip_bw = shift_list(*orig_ip_bw_list); - uint32_t test_ip = ntohl(next_ip_bw->ip); - if(test_ip >= range[0] && test_ip <= range[1]) - { - //overlap found! filter the ip by not adding it back! - } - else - { - push_list(new_ip_bw_list, next_ip_bw); - } - } - free(range); - unsigned long num_destroyed; - destroy_list(*orig_ip_bw_list, DESTROY_MODE_IGNORE_VALUES, &num_destroyed); - *orig_ip_bw_list = new_ip_bw_list; - } - free_null_terminated_string_array(split_group); - free(dyn_group_str); - - return *orig_ip_bw_list; - -} - -uint32_t* ip_range_to_host_ints(char* ip_str) -{ - uint32_t* ret_val = (uint32_t*)malloc(2*sizeof(uint32_t)); - uint32_t start = 0; - uint32_t end = 0; - - unsigned long num_pieces = 0; - char ip_breaks[] = "/-"; - char** split_ip = split_on_separators(ip_str, ip_breaks, 2, -1, 0, &num_pieces); - start = ip_to_host_int(split_ip[0]); - if(strstr(ip_str, "/") != NULL) - { - uint32_t mask = -1; - if(strstr(split_ip[1], ".") != NULL) - { - mask = ip_to_host_int(split_ip[1]); - } - else - { - uint32_t mask_size; - sscanf(split_ip[1], "%d", &mask_size); - mask = mask << (32-mask_size); - } - start = start & mask; - end = start | ( ~mask ); - } - else if(strstr(ip_str, "-") != NULL) - { - end = ip_to_host_int(split_ip[1]); - } - else - { - end = start; - } - free_null_terminated_string_array(split_ip); - - ret_val[0] = start; - ret_val[1] = end; - return ret_val; -} - -uint32_t ip_to_host_int(char* ip_str) -{ - struct in_addr inp; - inet_aton(ip_str, &inp); - return (uint32_t)ntohl(inp.s_addr); -} - -void delete_chain_from_table(char* table, char* delete_chain) -{ - char *command = dynamic_strcat(3, "iptables -t ", table, " -L -n --line-numbers 2>/dev/null"); - unsigned long num_lines = 0; - char** table_dump = get_shell_command_output_lines(command, &num_lines ); - free(command); - - unsigned long line_index; - char* current_chain = NULL; - list* delete_commands = initialize_list(); - - for(line_index=0; line_index < num_lines; line_index++) - { - char* line = table_dump[line_index]; - unsigned long num_pieces = 0; - char whitespace[] = { '\t', ' ', '\r', '\n' }; - char** line_pieces = split_on_separators(line, whitespace, 4, -1, 0, &num_pieces); - if(strcmp(line_pieces[0], "Chain") == 0) - { - if(current_chain != NULL) { free(current_chain); } - current_chain = strdup(line_pieces[1]); - } - else - { - unsigned long line_num; - int read = sscanf(line_pieces[0], "%ld", &line_num); - - if(read > 0 && current_chain != NULL && num_pieces >1) - { - if(strcmp(line_pieces[1], delete_chain) == 0) - { - char* delete_command = dynamic_strcat(7, "iptables -t ", table, " -D ", current_chain, " ", line_pieces[0], " 2>/dev/null"); - push_list(delete_commands, delete_command); - } - } - } - - //free line_pieces - free_null_terminated_string_array(line_pieces); - } - free_null_terminated_string_array(table_dump); - - /* final two commands to flush chain being deleted and whack it */ - unshift_list(delete_commands, dynamic_strcat(5, "iptables -t ", table, " -F ", delete_chain, " 2>/dev/null")); - unshift_list(delete_commands, dynamic_strcat(5, "iptables -t ", table, " -X ", delete_chain, " 2>/dev/null")); - - /* run delete commands */ - while(delete_commands->length > 0) - { - char *next_command = (char*)pop_list(delete_commands); - run_shell_command(next_command, 1); - } -} - -void run_shell_command(char* command, int free_command_str) -{ - //printf("%s\n", command); - system(command); - if(free_command_str) - { - free(command); - } -} - -list* get_all_sections_of_type(struct uci_context *ctx, char* package, char* section_type) -{ - - struct uci_package *p = NULL; - struct uci_element *e = NULL; - - list* sections_of_type = initialize_list(); - if(uci_load(ctx, package, &p) == UCI_OK) - { - uci_foreach_element( &p->sections, e) - { - struct uci_section *section = uci_to_section(e); - if(safe_strcmp(section->type, section_type) == 0) - { - push_list(sections_of_type, strdup(section->e.name)); - } - } - } - return sections_of_type; -} - -char* get_uci_option(struct uci_context* ctx, char* package_name, char* section_name, char* option_name) -{ - char* option_value = NULL; - struct uci_ptr ptr; - char* lookup_str = dynamic_strcat(5, package_name, ".", section_name, ".", option_name); - int ret_value = uci_lookup_ptr(ctx, &ptr, lookup_str, 1); - if(ret_value == UCI_OK) - { - if( !(ptr.flags & UCI_LOOKUP_COMPLETE)) - { - ret_value = UCI_ERR_NOTFOUND; - } - else - { - struct uci_element *e = (struct uci_element*)ptr.o; - option_value = get_option_value_string(uci_to_option(e)); - } - } - free(lookup_str); - - return option_value; -} - -// this function dynamically allocates memory for -// the option string, but since this program exits -// almost immediately (after printing variable info) -// the massive memory leak we're opening up shouldn't -// cause any problems. This is your reminder/warning -// that this might be an issue if you use this code to -// do anything fancy. -char* get_option_value_string(struct uci_option* uopt) -{ - char* opt_str = NULL; - if(uopt->type == UCI_TYPE_STRING) - { - opt_str = strdup(uopt->v.string); - } - if(uopt->type == UCI_TYPE_LIST) - { - struct uci_element* e; - uci_foreach_element(&uopt->v.list, e) - { - if(opt_str == NULL) - { - opt_str = strdup(e->name); - } - else - { - char* tmp; - tmp = dynamic_strcat(3, opt_str, " ", e->name); - free(opt_str); - opt_str = tmp; - } - } - } - return opt_str; -} diff --git a/package/jsda/libericstools/Makefile b/package/jsda/libericstools/Makefile deleted file mode 100644 index e8ae3c3ff9..0000000000 --- a/package/jsda/libericstools/Makefile +++ /dev/null @@ -1,54 +0,0 @@ -# -# Copyright (C) 2006 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# -# $Id: Makefile 9907 2007-12-25 01:59:55Z nbd $ - -include $(TOPDIR)/rules.mk - -PKG_NAME:=libericstools -PKG_VERSION:=1.0.0 -PKG_RELEASE:=1 - -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) - -include $(INCLUDE_DIR)/package.mk - -define Package/libericstools - SECTION:=libs - CATEGORY:=Gargoyle - SUBMENU:=Libraries - TITLE:=Erics Tools - URL:=http://www.gargoyle-router.com - MAINTAINER:=Eric Bishop -endef - -define Package/libericstools/description - A bunch of routines/utilities written by Eric Bishop, - a library primarily used in Gargoyle Web Interface for OpenWrt -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/InstallDev - mkdir -p $(STAGING_DIR)/usr/include/ - $(CP) $(PKG_BUILD_DIR)/*.h $(STAGING_DIR)/usr/include/ - - mkdir -p $(STAGING_DIR)/usr/lib - $(CP) $(PKG_BUILD_DIR)/*.so* $(STAGING_DIR)/usr/lib/ -endef - -define Package/libericstools/install - $(INSTALL_DIR) $(1)/usr/lib - $(CP) $(PKG_BUILD_DIR)/*.so* $(1)/usr/lib/ -endef - -$(eval $(call BuildPackage,libericstools)) diff --git a/package/jsda/libericstools/src/Makefile b/package/jsda/libericstools/src/Makefile deleted file mode 100644 index ed93ebc501..0000000000 --- a/package/jsda/libericstools/src/Makefile +++ /dev/null @@ -1,78 +0,0 @@ -all: erics_tools -VERSION=1 - -ifeq ($(CC),) - CC=gcc -endif - -ifeq ($(LD),) - LD=ld -endif - -ifeq ($(AR),) - AR=ar -endif - -ifeq ($(RANLIB),) - RANLIB=ranlib -endif - -CFLAGS:=$(CFLAGS) -Os -WARNING_FLAGS=-Wall -Wstrict-prototypes -pedantic -MINIMAL_WARNING_FLAGS=-Wall -Wstrict-prototypes - -OS=$(shell uname) -ifeq ($(OS),Darwin) - LINK=$(LD) - SHLIB_EXT=dylib - SHLIB_FLAGS=-dylib - SHLIB_FILE=libericstools.$(SHLIB_EXT).$(VERSION) - CFLAGS:=$(CFLAGS) -arch i386 -else - LINK=$(CC) - SHLIB_EXT=so - SHLIB_FILE=libericstools.$(SHLIB_EXT).$(VERSION) - SHLIB_FLAGS=-shared -Wl,-soname,$(SHLIB_FILE) -endif - -test_list_and_queue: test_list_and_queue.c libericstools.a - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ -test_list_and_queue.o: test_list_and_queue.c - $(CC) $(CFLAGS) $(MINIMAL_WARNING_FLAGS) -o $@ -c $^ - -test_string: test_string.o libericstools.a - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ -test_string.o: test_string.c - $(CC) $(CFLAGS) $(MINIMAL_WARNING_FLAGS) -c $^ -o $@ - -test_map: test_map.o libericstools.a - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ -test_map.o: test_map.c - $(CC) $(CFLAGS) $(MINIMAL_WARNING_FLAGS) -c $^ -o $@ - -all: erics_tools - -erics_tools: libericstools.$(SHLIB_EXT) libericstools.a - -libericstools.a: list_static.o priority_queue_static.o tree_map_static.o string_util_static.o file_util_static.o safe_malloc_static.o - if [ -e $@ ] ; then rm $@ ; fi - $(AR) rc $@ $^ - $(RANLIB) $@ - -libericstools.$(SHLIB_EXT) : list_dyn.o priority_queue_dyn.o tree_map_dyn.o string_util_dyn.o file_util_dyn.o safe_malloc_dyn.o - if [ -e libericstools.$(SHLIB_EXT) ] ; then rm libericstools.$(SHLIB_EXT)* ; fi - $(LINK) $(LDFLAGS) $(SHLIB_FLAGS) -o $(SHLIB_FILE) $^ -lc - ln -s $(SHLIB_FILE) libericstools.$(SHLIB_EXT) - -%_dyn.o: %.c - $(CC) $(CFLAGS) -fPIC $(WARNING_FLAGS) -o $@ -c $^ - -%_static.o: %.c - $(CC) $(CFLAGS) $(WARNING_FLAGS) -o $@ -c $^ - -clean: - rm -rf *.a *.o .*sw* *~ test_map test_string test_list_and_queue - if [ "$(SHLIB_EXT)" != "" ] ; then rm -rf *.$(SHLIB_EXT)* ; fi -install: - cp *.h /usr/include - cp *.$(SHLIB_EXT)* /usr/lib diff --git a/package/jsda/libericstools/src/erics_tools.h b/package/jsda/libericstools/src/erics_tools.h deleted file mode 100644 index b6866b9773..0000000000 --- a/package/jsda/libericstools/src/erics_tools.h +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright © 2008 by Eric Bishop - * - * This work 'as-is' we provide. - * No warranty, express or implied. - * We've done our best, - * to debug and test. - * Liability for damages denied. - * - * Permission is granted hereby, - * to copy, share, and modify. - * Use as is fit, - * free or for profit. - * On this notice these rights rely. - * - * - * - * Note that unlike other portions of Gargoyle this code - * does not fall under the GPL, but the rather whimsical - * 'Poetic License' above. - * - * Basically, this library contains a bunch of utilities - * that I find useful. I'm sure other libraries exist - * that are just as good or better, but I like these tools - * because I personally wrote them, so I know their quirks. - * (i.e. I know where the bodies are buried). I want to - * make sure that I can re-use these utilities for whatever - * code I may want to write in the future be it - * proprietary or open-source, so I've put them under - * a very, very permissive license. - * - * If you find this code useful, use it. If not, don't. - * I really don't care. - * - */ - -#ifndef ERICS_TOOLS_H -#define ERICS_TOOLS_H - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#ifndef stricmp - #define stricmp strcasecmp -#endif - -/* tree_map structs / prototypes */ -typedef struct long_tree_map_node -{ - unsigned long key; - void* value; - - signed char balance; - struct long_tree_map_node* left; - struct long_tree_map_node* right; -} long_map_node; - -typedef struct -{ - long_map_node* root; - unsigned long num_elements; -} long_map; - -typedef struct -{ - long_map lm; - unsigned char store_keys; - unsigned long num_elements; -} string_map; - - -/* long map functions */ -extern long_map* initialize_long_map(void); -extern void* get_long_map_element(long_map* map, unsigned long key); -void* get_smallest_long_map_element(long_map* map, unsigned long* smallest_key); -void* get_largest_long_map_element(long_map* map, unsigned long* largest_key); -void* remove_smallest_long_map_element(long_map* map, unsigned long* smallest_key); -void* remove_largest_long_map_element(long_map* map, unsigned long* largest_key); -extern void* set_long_map_element(long_map* map, unsigned long key, void* value); -extern void* remove_long_map_element(long_map* map, unsigned long key); -extern unsigned long* get_sorted_long_map_keys(long_map* map, unsigned long* num_keys_returned); -extern void** get_sorted_long_map_values(long_map* map, unsigned long* num_values_returned); -extern void** destroy_long_map(long_map* map, int destruction_type, unsigned long* num_destroyed); -extern void apply_to_every_long_map_value(long_map* map, void (*apply_func)(unsigned long key, void* value)); - - -/* string map functions */ -extern string_map* initialize_string_map(unsigned char store_keys); -extern void* get_string_map_element(string_map* map, const char* key); -extern void* set_string_map_element(string_map* map, const char* key, void* value); -extern void* remove_string_map_element(string_map* map, const char* key); -extern char** get_string_map_keys(string_map* map, unsigned long* num_keys_returned); -extern void** get_string_map_values(string_map* map, unsigned long* num_values_returned); -extern void** destroy_string_map(string_map* map, int destruction_type, unsigned long* num_destroyed); -extern void apply_to_every_string_map_value(string_map* map, void (*apply_func)(char* key, void* value)); - -/* - * three different ways to deal with values when data structure is destroyed - */ -#define DESTROY_MODE_RETURN_VALUES 20 -#define DESTROY_MODE_FREE_VALUES 21 -#define DESTROY_MODE_IGNORE_VALUES 22 - -/* - * for convenience & backwards compatibility alias _string_map_ functions to - * _map_ functions since string map is used more often than long map - */ -#define initialize_map initialize_string_map -#define set_map_element set_string_map_element -#define get_map_element get_string_map_element -#define remove_map_element remove_string_map_element -#define get_map_keys get_string_map_keys -#define get_map_values get_string_map_values -#define destroy_map destroy_string_map - -/* list structs / prototypes */ - -typedef struct list_node_struct -{ - struct list_node_struct* next; - struct list_node_struct* previous; - void* value; -} list_node; - -typedef struct list_struct -{ - long length; - list_node* head; - list_node* tail; - -} list; - -extern list* initialize_list(void); /* O(1) */ -extern void* shift_list(list* l); /* O(1) */ -extern void unshift_list(list* l, void* value); /* O(1) */ -extern void* pop_list(list* l); /* O(1) */ -extern void push_list(list*l, void* value); /* O(1) */ -extern void** destroy_list(list* l, int destruction_type, unsigned long* num_destroyed); /* O(n) */ -extern void* list_element_at(list* l, unsigned long index); /* O(n) */ -extern void** get_list_values(list* l, unsigned long* num_values_returned); /* O(n) */ - -/* The idea behind the remove_internal_node function and - * the other functions below that perform list operations on - * list_node pointers instead of values is as follows: - * - * It is O(n) to remove arbitrary node from list. BUT, if - * we have a pointer to that node already it is O(1). So, - * provide functions to manipulate list with list_node pointers - * instead of values & a function to remove an internal node - * given a pointer to that node. This means we can have - * access to internal nodes & use another - * data structure to store internal nodes and delete in O(1) - */ -extern void remove_internal_list_node(list*l, list_node* internal); /* O(1) */ -extern list_node* create_list_node(void* value); /* O(1) */ -extern void* free_list_node(list_node* delete_node); /* O(1) */ -extern list_node* shift_list_node(list* l); /* O(1) */ -extern void unshift_list_node(list* l, list_node* new_node); /* O(1) */ -extern list_node* pop_list_node(list* l); /* O(1) */ -extern void push_list_node(list*l, list_node* new_node); /* O(1) */ - - -/* priority_queue structs / prototypes */ - -typedef struct priority_queue_node_struct -{ - unsigned long priority; - char* id; - void* value; -} priority_queue_node; - -typedef struct priority_queue_struct -{ - long_map* priorities; - string_map* ids; - priority_queue_node* first; - long length; -} priority_queue; - -extern priority_queue* initialize_priority_queue(void); -extern priority_queue_node* create_priority_node(unsigned long priority, char* id, void* value); -extern void* free_priority_queue_node(priority_queue_node* pn); -extern void push_priority_queue(priority_queue* pq, unsigned long priority, char* id, void * value); -extern void* shift_priority_queue(priority_queue* pq, unsigned long* priority, char** id); -extern void* peek_priority_queue(priority_queue* pq, unsigned long* priority, char** id, int dynamic_alloc_id); -extern void* get_priority_queue_element_with_id(priority_queue* pq, char* id, long* priority); -extern void* remove_priority_queue_element_with_id(priority_queue* pq, char* id, long* priority); -extern void push_priority_queue_node(priority_queue* pq, priority_queue_node* pn); -extern priority_queue_node* shift_priority_queue_node(priority_queue* pq); -extern priority_queue_node* get_priority_queue_node_with_id(priority_queue* pq, char* id); -extern priority_queue_node* remove_priority_queue_node_with_id(priority_queue* pq, char* id); -extern void set_priority_for_id_in_priority_queue(priority_queue* pq, char* id, unsigned long priority); -extern priority_queue_node* peek_priority_queue_node(priority_queue* pq); -extern void** destroy_priority_queue(priority_queue* pq, int destroy_mode, unsigned long* num_destroyed); - -/* string_util structs / prototypes */ - -typedef struct -{ - char* str; - int terminator; -} dyn_read_t; - -/* non-dynamic functions */ -extern char* replace_prefix(char* original, char* old_prefix, char* new_prefix); -extern char* trim_flanking_whitespace(char* str); -extern int safe_strcmp(const char* str1, const char* str2); -extern void to_lowercase(char* str); -extern void to_uppercase(char* str); - -/* dynamic functions (e.g. new memory is allocated, return values must be freed) */ -int free_null_terminated_string_array(char** strs); -char** copy_null_terminated_string_array(char** original); -extern char* dynamic_strcat(int num_strs, ...); -extern char* dcat_and_free(char** one, char** two, int free1, int free2); -extern char** split_on_separators(char* line, char* separators, int num_separators, int max_pieces, int include_remainder_at_max, unsigned long* num_pieces); /*if max_pieces < 0, it is ignored */ -extern char* join_strs(char* separator, char** parts, int max_parts, int free_parts, int free_parts_array); /*if max_parts < 0, it is ignored*/ -extern char* dynamic_replace(char* template_str, char* old_str, char* new_str); -int convert_to_regex(char* str, regex_t* p); - -/* functions to dynamically read files */ -extern dyn_read_t dynamic_read(FILE* open_file, char* terminators, int num_terminators, unsigned long* read_length); -extern int dyn_read_line(FILE* open_file, char** dest, unsigned long* read_len); -extern unsigned char* read_entire_file(FILE* in, unsigned long read_block_size, unsigned long* read_length); - -/* run a command and get (dynamically allocated) output lines */ -extern char** get_shell_command_output_lines(char* command, unsigned long* num_lines); - -/* comparison functions for qsort */ -extern int sort_string_cmp(const void *a, const void *b); -extern int sort_string_icmp(const void *a, const void *b); - -/* wrappers for qsort calls */ -extern void do_str_sort(char** string_arr, unsigned long string_arr_len); -extern void do_istr_sort(char** string_arr, unsigned long string_arr_len); - -/* safe malloc & strdup functions used by all others (actually aliased to malloc / strdup and used) */ -extern void* safe_malloc(size_t size); -extern char* safe_strdup(const char* str); - -/* utility functions to free memory */ -extern void free_if_not_null(void* p); -extern void free_and_set_null(void** p); - -/* other file utils */ - -extern int mkdir_p(const char* path, mode_t mode); /* returns 0 on success, 1 on error */ -extern void rm_r(const char* path); -extern int create_tmp_dir(const char* tmp_root, char** tmp_dir); /* returns 0 on success, 1 on error */ - -#define PATH_DOES_NOT_EXIST 0 -#define PATH_IS_REGULAR_FILE 1 -#define PATH_IS_DIRECTORY 2 -#define PATH_IS_SYMLINK 3 -#define PATH_IS_OTHER 4 - -/* -returns: - PATH_DOES_NOT_EXIST (0) if path doesn't exist - PATH_IS_REGULAR_FILE (1) if path is regular file - PATH_IS_DIRECTORY (2) if path is directory - PATH_IS_SYMLINK (3) if path is symbolic link - PATH_IS_OTHER (4) if path exists and is something else - */ -extern int path_exists(const char* path); -extern char** get_file_lines(char* file_path, unsigned long* lines_read); -#endif /* ERICS_TOOLS_H */ diff --git a/package/jsda/libericstools/src/file_util.c b/package/jsda/libericstools/src/file_util.c deleted file mode 100644 index 9859cee675..0000000000 --- a/package/jsda/libericstools/src/file_util.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright © 2008 by Eric Bishop - * - * This work ‘as-is’ we provide. - * No warranty, express or implied. - * We’ve done our best, - * to debug and test. - * Liability for damages denied. - * - * Permission is granted hereby, - * to copy, share, and modify. - * Use as is fit, - * free or for profit. - * On this notice these rights rely. - * - * - * - * Note that unlike other portions of Gargoyle this code - * does not fall under the GPL, but the rather whimsical - * 'Poetic License' above. - * - * Basically, this library contains a bunch of utilities - * that I find useful. I'm sure other libraries exist - * that are just as good or better, but I like these tools - * because I personally wrote them, so I know their quirks. - * (i.e. I know where the bodies are buried). I want to - * make sure that I can re-use these utilities for whatever - * code I may want to write in the future be it - * proprietary or open-source, so I've put them under - * a very, very permissive license. - * - * If you find this code useful, use it. If not, don't. - * I really don't care. - * - */ - -#include "erics_tools.h" -#define malloc safe_malloc -#define strdup safe_strdup - -static int __srand_called = 0; - -int create_tmp_dir(const char* tmp_root, char** tmp_dir) -{ - if(! __srand_called) - { - srand(time(NULL)); - __srand_called = 1; - } - sprintf((*tmp_dir), "%s/tmp_%d", tmp_root, rand()); - return (mkdir_p(*tmp_dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH )); -} - -/* -returns: - PATH_DOES_NOT_EXIST (0) if path doesn't exist - PATH_IS_REGULAR_FILE (1) if path is regular file - PATH_IS_DIRECTORY (2) if path is directory - PATH_IS_SYMLINK (3) if path is symbolic link - PATH_IS_OTHER (4) if path exists and is something else - */ -int path_exists(const char* path) -{ - struct stat fs; - int exists = lstat(path,&fs) >= 0 ? PATH_IS_OTHER : PATH_DOES_NOT_EXIST; - if(exists > 0) - { - exists = S_ISREG(fs.st_mode) ? PATH_IS_REGULAR_FILE : exists; - exists = S_ISDIR(fs.st_mode) ? PATH_IS_DIRECTORY : exists; - exists = S_ISLNK(fs.st_mode) ? PATH_IS_SYMLINK : exists; - } - return exists; -} - -int mkdir_p(const char* path, mode_t mode) -{ - int err=0; - struct stat fs; - - char* dup_path = strdup(path); - char* sep = strchr(dup_path, '/'); - sep = (sep == dup_path) ? strchr(sep+1, '/') : sep; - while(sep != NULL && err == 0) - { - sep[0] = '\0'; - if(stat(dup_path,&fs) >= 0) - { - if(!S_ISDIR(fs.st_mode)) - { - err = 1; - } - } - else - { - mkdir(dup_path, mode); - } - err =1; - if(stat(dup_path,&fs) >= 0) - { - err = S_ISDIR(fs.st_mode) ? 0 : 1; - } - - sep[0] = '/'; - sep = strchr(sep+1, '/'); - } - if(err == 0) - { - if(stat(dup_path,&fs) >= 0) - { - if(!S_ISDIR(fs.st_mode)) - { - err = 1; - } - } - else - { - mkdir(dup_path, mode); - } - err =1; - if(stat(dup_path,&fs) >= 0) - { - err = S_ISDIR(fs.st_mode) ? 0 : 1; - } - - } - free(dup_path); - return err; -} - -void rm_r(const char* path) -{ - struct stat fs; - if(lstat(path,&fs) >= 0) - { - if(S_ISDIR (fs.st_mode)) - { - /* remove directory recursively */ - struct dirent **entries; - int num_entry_paths; - int entry_path_index; - num_entry_paths = scandir(path, &entries, 0, alphasort); - for(entry_path_index=0; entry_path_index < num_entry_paths; entry_path_index++) - { - struct dirent *dentry = entries[entry_path_index]; - if(strcmp(dentry->d_name, "..") != 0 && strcmp(dentry->d_name, ".") != 0) - { - char* entry_path = (char*)malloc(strlen(path) + strlen(dentry->d_name) + 2); - sprintf(entry_path,"%s/%s", path, dentry->d_name); - - /* recurse */ - rm_r(entry_path); - - free(entry_path); - } - } - remove(path); - } - else - { - /* remove regular file, no need to recurse */ - remove(path); - } - } -} - -char** get_file_lines(char* file_path, unsigned long* lines_read) -{ - char** result = NULL; - int path_type = path_exists(file_path); - *lines_read = 0; - if(path_type != PATH_DOES_NOT_EXIST && path_type != PATH_IS_DIRECTORY) /* exists and is not directory */ - { - FILE* read_file = fopen(file_path, "r"); - unsigned char* file_data = NULL; - if(read_file != NULL) - { - unsigned long file_length; - file_data = read_entire_file(read_file, 1024, &file_length); - fclose(read_file); - } - if(file_data != NULL) - { - char line_seps[] = {'\r', '\n'}; - result = split_on_separators((char*)file_data, line_seps , 2, -1, 0, lines_read); - free(file_data); - } - } - return result; -} diff --git a/package/jsda/libericstools/src/list.c b/package/jsda/libericstools/src/list.c deleted file mode 100644 index 92d6283c3a..0000000000 --- a/package/jsda/libericstools/src/list.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright © 2008 by Eric Bishop - * - * This work ‘as-is’ we provide. - * No warranty, express or implied. - * We’ve done our best, - * to debug and test. - * Liability for damages denied. - * - * Permission is granted hereby, - * to copy, share, and modify. - * Use as is fit, - * free or for profit. - * On this notice these rights rely. - * - * - * - * Note that unlike other portions of Gargoyle this code - * does not fall under the GPL, but the rather whimsical - * 'Poetic License' above. - * - * Basically, this library contains a bunch of utilities - * that I find useful. I'm sure other libraries exist - * that are just as good or better, but I like these tools - * because I personally wrote them, so I know their quirks. - * (i.e. I know where the bodies are buried). I want to - * make sure that I can re-use these utilities for whatever - * code I may want to write in the future be it - * proprietary or open-source, so I've put them under - * a very, very permissive license. - * - * If you find this code useful, use it. If not, don't. - * I really don't care. - * - */ - -#include "erics_tools.h" -#define malloc safe_malloc -#define strdup safe_strdup - -list* initialize_list() -{ - list* l = (list*)malloc(sizeof(list)); - l->length = 0; - l->head = NULL; - l->tail = NULL; - return l; -} - -list_node* create_list_node(void* value) -{ - list_node* new_node = (list_node*)malloc(sizeof(list_node)); - new_node->value = value; - new_node->previous = NULL; - new_node->next = NULL; - return new_node; -} - -void* free_list_node(list_node* delete_node) -{ - void* value = NULL; - if(delete_node != NULL) - { - value = delete_node->value; - free(delete_node); - } - return value; -} - -list_node* shift_list_node(list* l) -{ - list_node* return_node = NULL; - if(l != NULL) - { - if(l->head != NULL) - { - return_node = l->head; - - l->head = l->head->next; - if(l->head != NULL) { l->head->previous = NULL; } - l->tail = l->tail == return_node ? NULL : l->tail; - l->length = l->length -1; - - return_node->previous = NULL; - return_node->next = NULL; - } - } - return return_node; -} - -void unshift_list_node(list* l, list_node* new_node) -{ - if(l != NULL && new_node != NULL) - { - new_node->previous = NULL; - if(l->head == NULL) /* list is empty */ - { - new_node->next = NULL; - l->tail = new_node; - } - else - { - new_node->next = l->head; - l->head->previous = new_node; - - } - l->head = new_node; - l->length = l->length +1; - } -} - -list_node* pop_list_node(list* l) -{ - list_node* return_node = NULL; - if(l != NULL) - { - if(l->tail != NULL) - { - return_node = l->tail; - l->tail = l->tail->previous; - if(l->tail != NULL) { l->tail->next = NULL; } - l->head = l->head == return_node ? NULL : l->head; - l->length = l->length -1; - - return_node->previous = NULL; - return_node->next = NULL; - } - } - return return_node; - -} - -void push_list_node(list* l, list_node* new_node) -{ - if(l != NULL && new_node != NULL) - { - new_node->next = NULL; - if(l->tail == NULL) /* list is empty */ - { - new_node->previous = NULL; - l->head = new_node; - } - else - { - new_node->previous = l->tail; - l->tail->next = new_node; - } - l->tail = new_node; - l->length = l->length +1; - } -} - -void* shift_list(list* l) -{ - return free_list_node ( shift_list_node(l) ); -} - -void unshift_list(list* l, void* value) -{ - list_node* new_node = create_list_node(value); - unshift_list_node(l, new_node); -} - -void* pop_list(list* l) -{ - return free_list_node ( pop_list_node(l) ); -} - -void push_list(list*l, void* value) -{ - list_node* new_node = create_list_node(value); - push_list_node(l, new_node); -} - -void remove_internal_list_node(list* l, list_node* internal) -{ - /* note we assume internal is in l, otherwise everything gets FUBAR! */ - if(l != NULL && internal != NULL) - { - list_node* next = internal->next; - list_node* previous = internal->previous; - if(previous == NULL) /* internal is head */ - { - l->head = next; - if(l->head != NULL) { l->head->previous = NULL; } - } - if(next == NULL) /* internal is tail */ - { - l->tail = previous; - if(l->tail != NULL) { l->tail->next = NULL; } - } - if(previous != NULL && next != NULL) - { - previous->next = next; - next->previous = previous; - } - internal->next = NULL; - internal->previous = NULL; - - l->length = l->length - 1; - } -} - -void** destroy_list(list* l, int destruction_type, unsigned long* num_values) -{ - void** values = NULL; - unsigned long value_index = 0; - if(l != NULL) - { - if(destruction_type == DESTROY_MODE_RETURN_VALUES) - { - values = (void**)malloc((1+l->length)*sizeof(void*)); - } - - - for(value_index=0; l->length > 0; value_index++) - { - void* value = shift_list(l); - if(destruction_type == DESTROY_MODE_RETURN_VALUES) - { - values[value_index] = value; - } - else if(destruction_type == DESTROY_MODE_FREE_VALUES) - { - free(value); - } - } - if(destruction_type == DESTROY_MODE_RETURN_VALUES) - { - values[value_index] = NULL; - } - free(l); - } - *num_values = value_index; - return values; -} - -void* list_element_at(list* l, unsigned long index) -{ - void* return_value = NULL; - if(l != NULL) - { - unsigned long current_index = index - (unsigned long)((l->length)/2) > 0 ? l->length -1 : 0; - list_node* current_node = current_index == 0 ? l->head : l->tail; - - while(current_index != index && current_node != NULL) - { - current_node = current_index > index ? current_node->previous : current_node->next; - current_index = current_index > index ? current_index -1 : current_index + 1; - } - if(current_node != NULL) - { - return_value = current_node->value; - } - } - return return_value; -} -void** get_list_values(list* l, unsigned long* num_values) /* returns null terminated array */ -{ - void** values = NULL; - unsigned long value_index = 0; - if(l != NULL) - { - - list_node* current_node = l->head; - values = (void**)malloc((1+l->length)*sizeof(void*)); - - for(value_index = 0; value_index < l->length; value_index++) - { - values[value_index] = current_node->value; - current_node = current_node->next; - } - values[value_index] = NULL; - } - *num_values = value_index; - return values; -} diff --git a/package/jsda/libericstools/src/priority_queue.c b/package/jsda/libericstools/src/priority_queue.c deleted file mode 100644 index 3f1875df85..0000000000 --- a/package/jsda/libericstools/src/priority_queue.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright © 2008 by Eric Bishop - * - * This work ‘as-is’ we provide. - * No warranty, express or implied. - * We’ve done our best, - * to debug and test. - * Liability for damages denied. - * - * Permission is granted hereby, - * to copy, share, and modify. - * Use as is fit, - * free or for profit. - * On this notice these rights rely. - * - * - * - * Note that unlike other portions of Gargoyle this code - * does not fall under the GPL, but the rather whimsical - * 'Poetic License' above. - * - * Basically, this library contains a bunch of utilities - * that I find useful. I'm sure other libraries exist - * that are just as good or better, but I like these tools - * because I personally wrote them, so I know their quirks. - * (i.e. I know where the bodies are buried). I want to - * make sure that I can re-use these utilities for whatever - * code I may want to write in the future be it - * proprietary or open-source, so I've put them under - * a very, very permissive license. - * - * If you find this code useful, use it. If not, don't. - * I really don't care. - * - */ - -#include "erics_tools.h" -#define malloc safe_malloc -#define strdup safe_strdup - -typedef struct id_map_node_struct -{ - list* id_list; - list_node* id_node; -} id_map_node; - - -priority_queue* initialize_priority_queue(void) -{ - priority_queue* pq = (priority_queue*)malloc(sizeof(priority_queue)); - pq->priorities = initialize_long_map(); - pq->ids = initialize_string_map(0); - pq->first = NULL; - pq->length = 0; - return pq; -} - -priority_queue_node* create_priority_node(unsigned long priority, char* id, void* value) -{ - priority_queue_node* pn = (priority_queue_node*)malloc(sizeof(priority_queue_node)); - pn->priority = priority; - pn->id = strdup(id); - pn->value = value; - return pn; -} - -void* free_priority_queue_node(priority_queue_node* pn) -{ - void *return_value = NULL; - if(pn != NULL) - { - return_value = pn->value; - free(pn->id); - free(pn); - } - return return_value; -} - -void push_priority_queue(priority_queue* pq, unsigned long priority, char* id, void * value) -{ - if(pq != NULL && id != NULL) - { - priority_queue_node* pn = create_priority_node(priority, id, value); - push_priority_queue_node(pq, pn); - } -} - -/* note id is ALWAYS dynamically allocated, need to free */ -void* shift_priority_queue(priority_queue* pq, unsigned long* priority, char** id) -{ - void* return_value = NULL; - priority_queue_node* pn = shift_priority_queue_node(pq); - if(pn != NULL) - { - *priority = pn->priority; - *id = strdup(pn->id); - return_value = free_priority_queue_node(pn); - } - return return_value; -} - -/* last param specified whether to dynamicall allocate id (otherwise pointer to id in priority_queue_node) */ -void* peek_priority_queue(priority_queue* pq, unsigned long* priority, char** id, int dynamic_alloc_id) -{ - void* return_value = NULL; - *priority = 0; - *id = NULL; - if(pq != NULL) - { - if(pq->first != NULL) - { - return_value = pq->first->value; - *priority = pq->first->priority; - if(dynamic_alloc_id) - { - *id = strdup(pq->first->id); - } - else - { - *id = pq->first->id; - } - } - } - return return_value; -} - -void* get_priority_queue_element_with_id(priority_queue* pq, char* id, long* priority) -{ - void* return_value = NULL; - priority_queue_node* pn = get_priority_queue_node_with_id(pq, id); - if(pn != NULL) - { - *priority = pn->priority; - return_value = free_priority_queue_node(pn); - } - else - { - *priority = 0; - } - return return_value; -} - -void* remove_priority_queue_element_with_id(priority_queue* pq, char* id, long* priority) -{ - void* return_value = NULL; - priority_queue_node* pn = remove_priority_queue_node_with_id(pq, id); - if(pn != NULL) - { - *priority = pn->priority; - return_value = free_priority_queue_node(pn); - } - else - { - *priority = 0; - } - return return_value; -} - -void push_priority_queue_node(priority_queue* pq, priority_queue_node* pn) -{ - if(pq != NULL && pn != NULL) - { - /* assume that most of the time we won't have collisions */ - list_node* lpn = create_list_node(pn); - list* new_list = initialize_list(); - list* old_list; - id_map_node* idn; - - push_list_node(new_list, lpn); - old_list = (list*)set_long_map_element(pq->priorities, pn->priority, new_list); - if(old_list != NULL) - { - push_list_node(old_list, lpn); - set_long_map_element(pq->priorities, pn->priority, old_list); - free(new_list); - new_list = old_list; - } - - /* update first */ - if(pq->first == NULL) - { - pq->first = pn; - } - else if(pn->priority < pq->first->priority) - { - pq->first = pn; - } - - /* save id */ - idn = (id_map_node*)malloc(sizeof(id_map_node)); - idn->id_list = new_list; - idn->id_node = lpn; - set_string_map_element(pq->ids, pn->id, idn); - - pq->length = pq->length + 1;; - } -} - -priority_queue_node* shift_priority_queue_node(priority_queue* pq) -{ - priority_queue_node* return_node = NULL; - if(pq != NULL) - { - if(pq->first != NULL) - { - list* next_list = (list*)remove_long_map_element(pq->priorities, pq->first->priority); - list* next_first_list = NULL; - list_node* smallest_list_node = shift_list_node(next_list); - id_map_node* idn; - - if(next_list->length == 0) - { - unsigned long tmp; - destroy_list(next_list, DESTROY_MODE_IGNORE_VALUES, &tmp); - next_first_list = (list*)get_smallest_long_map_element(pq->priorities, &tmp); - } - else - { - set_long_map_element(pq->priorities, pq->first->priority, next_list); - next_first_list = next_list; - } - return_node = free_list_node(smallest_list_node); - idn = (id_map_node*)remove_string_map_element(pq->ids, return_node->id); - free(idn); - - if(next_first_list != NULL) - { - list_node* next_first_node = shift_list_node(next_first_list); - pq->first = (priority_queue_node*)next_first_node->value; - unshift_list_node(next_first_list, next_first_node); - } - else - { - pq->first = NULL; - } - - pq->length = pq->length -1; - } - } - return return_node; -} - -priority_queue_node* get_priority_queue_node_with_id(priority_queue* pq, char* id) -{ - priority_queue_node* return_node = NULL; - if(pq != NULL && id != NULL) - { - id_map_node* idn = (id_map_node*)get_string_map_element(pq->ids, id); - if(idn != NULL) - { - return_node = (priority_queue_node*)idn->id_node->value; - } - } - return return_node; -} - -priority_queue_node* remove_priority_queue_node_with_id(priority_queue* pq, char* id) -{ - priority_queue_node* return_node = NULL; - if(pq != NULL && id != NULL) - { - id_map_node* idn = (id_map_node*)remove_string_map_element(pq->ids, id); - if(idn != NULL) - { - /* remove relevant node from list */ - remove_internal_list_node(idn->id_list, idn->id_node); - return_node = free_list_node(idn->id_node); - - /* if list is empty remove it from priority map */ - if(idn->id_list->length == 0) - { - unsigned long tmp; - remove_long_map_element(pq->priorities, return_node->priority); - destroy_list(idn->id_list, DESTROY_MODE_IGNORE_VALUES, &tmp); - } - free(idn); - - /* if we're removing first node, reset it */ - if(return_node == pq->first) - { - unsigned long tmp; - list* next_first_list = (list*)get_smallest_long_map_element(pq->priorities, &tmp); - if(next_first_list != NULL) - { - list_node* next_first_node = shift_list_node(next_first_list); - pq->first = (priority_queue_node*)next_first_node->value; - unshift_list_node(next_first_list, next_first_node); - } - else - { - pq->first = NULL; - } - } - pq->length = pq->length -1; - } - } - return return_node; -} - -void set_priority_for_id_in_priority_queue(priority_queue* pq, char* id, unsigned long priority) -{ - if(pq != NULL && id != NULL) - { - priority_queue_node* id_pq_node = remove_priority_queue_node_with_id(pq, id); - id_pq_node->priority = priority; - push_priority_queue_node(pq, id_pq_node); - } -} - -priority_queue_node* peek_priority_queue_node(priority_queue* pq) -{ - return pq->first; -} - -void** destroy_priority_queue(priority_queue* pq, int destroy_mode, unsigned long* num_elements_destroyed) -{ - void** values = NULL; - unsigned long tmp; - *num_elements_destroyed = 0; - if(pq != NULL) - { - if(destroy_mode == DESTROY_MODE_RETURN_VALUES) - { - values = (void**)malloc((pq->length+1)*sizeof(void*)); - } - while(pq->length > 0) - { - priority_queue_node* pqn = shift_priority_queue_node(pq); - void* next_value = free_priority_queue_node(pqn); - if(destroy_mode == DESTROY_MODE_RETURN_VALUES) - { - values[*num_elements_destroyed] = next_value; - } - else if(destroy_mode == DESTROY_MODE_FREE_VALUES) - { - free(next_value); - } - *num_elements_destroyed = *num_elements_destroyed + 1; - } - if(destroy_mode == DESTROY_MODE_RETURN_VALUES) - { - values[*num_elements_destroyed] = NULL; - } - - destroy_long_map(pq->priorities, DESTROY_MODE_FREE_VALUES, &tmp); - destroy_string_map(pq->ids, DESTROY_MODE_FREE_VALUES, &tmp); - free(pq); - } - return values; -} diff --git a/package/jsda/libericstools/src/safe_malloc.c b/package/jsda/libericstools/src/safe_malloc.c deleted file mode 100644 index 4ab204a217..0000000000 --- a/package/jsda/libericstools/src/safe_malloc.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright © 2008 by Eric Bishop - * - * This work ‘as-is’ we provide. - * No warranty, express or implied. - * We’ve done our best, - * to debug and test. - * Liability for damages denied. - * - * Permission is granted hereby, - * to copy, share, and modify. - * Use as is fit, - * free or for profit. - * On this notice these rights rely. - * - * - * - * Note that unlike other portions of Gargoyle this code - * does not fall under the GPL, but the rather whimsical - * 'Poetic License' above. - * - * Basically, this library contains a bunch of utilities - * that I find useful. I'm sure other libraries exist - * that are just as good or better, but I like these tools - * because I personally wrote them, so I know their quirks. - * (i.e. I know where the bodies are buried). I want to - * make sure that I can re-use these utilities for whatever - * code I may want to write in the future be it - * proprietary or open-source, so I've put them under - * a very, very permissive license. - * - * If you find this code useful, use it. If not, don't. - * I really don't care. - * - */ - -#include "erics_tools.h" - -void *safe_malloc(size_t size) -{ - void* val = malloc(size); - if(val == NULL) - { - fprintf(stderr, "ERROR: MALLOC FAILURE!\n"); - exit(1); - } - return val; -} - -char* safe_strdup(const char* str) -{ - char* new_str = NULL; - if(str != NULL) - { - new_str = strdup(str); - if(new_str == NULL) - { - fprintf(stderr, "ERROR: MALLOC FAILURE!\n"); - exit(1); - } - } - return new_str; -} - -void free_if_not_null(void* p) -{ - if(p != NULL) - { - free(p); - } -} - -void free_and_set_null(void** p) -{ - if(*p != NULL) - { - free(*p); - *p = NULL; - } -} diff --git a/package/jsda/libericstools/src/string_util.c b/package/jsda/libericstools/src/string_util.c deleted file mode 100644 index 8fc2c7d7c2..0000000000 --- a/package/jsda/libericstools/src/string_util.c +++ /dev/null @@ -1,669 +0,0 @@ -/* - * Copyright © 2008 by Eric Bishop - * - * This work ‘as-is’ we provide. - * No warranty, express or implied. - * We’ve done our best, - * to debug and test. - * Liability for damages denied. - * - * Permission is granted hereby, - * to copy, share, and modify. - * Use as is fit, - * free or for profit. - * On this notice these rights rely. - * - * - * - * Note that unlike other portions of Gargoyle this code - * does not fall under the GPL, but the rather whimsical - * 'Poetic License' above. - * - * Basically, this library contains a bunch of utilities - * that I find useful. I'm sure other libraries exist - * that are just as good or better, but I like these tools - * because I personally wrote them, so I know their quirks. - * (i.e. I know where the bodies are buried). I want to - * make sure that I can re-use these utilities for whatever - * code I may want to write in the future be it - * proprietary or open-source, so I've put them under - * a very, very permissive license. - * - * If you find this code useful, use it. If not, don't. - * I really don't care. - * - */ - -#include "erics_tools.h" -#define malloc safe_malloc -#define strdup safe_strdup - -char* replace_prefix(char* original, char* old_prefix, char* new_prefix) -{ - char* replaced = NULL; - if(original != NULL && old_prefix != NULL && new_prefix != NULL && strstr(original, old_prefix) == original) - { - int old_prefix_length = strlen(old_prefix); - int new_prefix_length = strlen(new_prefix); - int remainder_length = strlen(original) - old_prefix_length; - int new_length = new_prefix_length + remainder_length; - /* printf("%d %d %d %d\n", old_prefix_length, new_prefix_length, remainder_length, new_length); */ - - replaced = malloc(new_length+1); - memcpy(replaced, new_prefix, new_prefix_length); - memcpy(replaced+new_prefix_length, original+old_prefix_length, remainder_length); - replaced[new_prefix_length+remainder_length] = '\0'; - } - return replaced; -} - -char* trim_flanking_whitespace(char* str) -{ - int new_start = 0; - int new_length = 0; - - char whitespace[5] = { ' ', '\t', '\n', '\r', '\0' }; - int num_whitespace_chars = 4; - - - int index = 0; - int is_whitespace = 1; - int test; - while( (test = str[index]) != '\0' && is_whitespace == 1) - { - int whitespace_index; - is_whitespace = 0; - for(whitespace_index = 0; whitespace_index < num_whitespace_chars && is_whitespace == 0; whitespace_index++) - { - is_whitespace = test == whitespace[whitespace_index] ? 1 : 0; - } - index = is_whitespace == 1 ? index+1 : index; - } - new_start = index; - - index = strlen(str) - 1; - is_whitespace = 1; - while( index >= new_start && is_whitespace == 1) - { - int whitespace_index; - is_whitespace = 0; - for(whitespace_index = 0; whitespace_index < num_whitespace_chars && is_whitespace == 0; whitespace_index++) - { - is_whitespace = str[index] == whitespace[whitespace_index] ? 1 : 0; - } - index = is_whitespace == 1 ? index-1 : index; - } - new_length = str[new_start] == '\0' ? 0 : index + 1 - new_start; - - - if(new_start > 0) - { - for(index = 0; index < new_length; index++) - { - str[index] = str[index+new_start]; - } - } - str[new_length] = 0; - return str; -} - -int safe_strcmp(const char* str1, const char* str2) -{ - if(str1 == NULL && str2 == NULL) - { - return 0; - } - else if(str1 == NULL && str2 != NULL) - { - return 1; - } - else if(str1 != NULL && str2 == NULL) - { - return -1; - } - return strcmp(str1, str2); -} - -void to_lowercase(char* str) -{ - int i; - for(i = 0; str[i] != '\0'; i++) - { - str[i] = tolower(str[i]); - } -} - -void to_uppercase(char* str) -{ - int i; - for(i = 0; str[i] != '\0'; i++) - { - str[i] = toupper(str[i]); - } -} - -/* returns number freed */ -int free_null_terminated_string_array(char** strs) -{ - unsigned long str_index = 0; - if(strs != NULL) - { - for(str_index=0; strs[str_index] != NULL; str_index++) - { - free(strs[str_index]); - } - free(strs); - } - return str_index; -} - -char** copy_null_terminated_string_array(char** original) -{ - unsigned long size; - char** new; - for(size=0; original[size] != NULL ; size++) ; - new = (char**)malloc( (size+1)*sizeof(char*)); - for(size=0; original[size] != NULL; size++) - { - new[size] = strdup(original[size]); - } - new[size] = NULL; - return new; -} - -char* dynamic_strcat(int num_strs, ...) -{ - - va_list strs; - int new_length = 0; - int i; - int next_start; - char* new_str; - - va_start(strs, num_strs); - for(i=0; i < num_strs; i++) - { - char* next_arg = va_arg(strs, char*); - if(next_arg != NULL) - { - new_length = new_length + strlen(next_arg); - } - } - va_end(strs); - - new_str = malloc((1+new_length)*sizeof(char)); - va_start(strs, num_strs); - next_start = 0; - for(i=0; i < num_strs; i++) - { - char* next_arg = va_arg(strs, char*); - if(next_arg != NULL) - { - int next_length = strlen(next_arg); - memcpy(new_str+next_start,next_arg, next_length); - next_start = next_start+next_length; - } - } - new_str[next_start] = '\0'; - - return new_str; -} - -char* dcat_and_free(char** one, char** two, int free1, int free2) -{ - char* s = NULL; - - if(one != NULL && two != NULL) { s = dynamic_strcat(2, *one, *two); } - else if(one != NULL) { s = strdup(*one); } - else if(two != NULL) { s = strdup(*two); } - else { s= strdup(""); } - - if(free1){ free(*one); *one=s; } - if(free2){ free(*two); *two=s; } - - return s; -} - -/* - * line is the line to be parsed -- it is not modified in any way - * max_pieces indicates number of pieces to return, if negative this is determined dynamically - * include_remainder_at_max indicates whether the last piece, when max pieces are reached, - * should be what it would normally be (0) or the entire remainder of the line (1) - * if max_pieces < 0 this parameter is ignored - * - * - * returns all non-separator pieces in a line - * result is dynamically allocated, MUST be freed after call-- even if - * line is empty (you still get a valid char** pointer to to a NULL char*) - */ -char** split_on_separators(char* line, char* separators, int num_separators, int max_pieces, int include_remainder_at_max, unsigned long *num_pieces) -{ - char** split; - - *num_pieces = 0; - if(line != NULL) - { - int split_index; - int non_separator_found; - char* dup_line; - char* start; - - if(max_pieces < 0) - { - /* count number of separator characters in line -- this count + 1 is an upperbound on number of pieces */ - int separator_count = 0; - int line_index; - for(line_index = 0; line[line_index] != '\0'; line_index++) - { - int sep_index; - int found = 0; - for(sep_index =0; found == 0 && sep_index < num_separators; sep_index++) - { - found = separators[sep_index] == line[line_index] ? 1 : 0; - } - separator_count = separator_count+ found; - } - max_pieces = separator_count + 1; - } - split = (char**)malloc((1+max_pieces)*sizeof(char*)); - split_index = 0; - split[split_index] = NULL; - - - dup_line = strdup(line); - start = dup_line; - non_separator_found = 0; - while(non_separator_found == 0) - { - int matches = 0; - int sep_index; - for(sep_index =0; sep_index < num_separators; sep_index++) - { - matches = matches == 1 || separators[sep_index] == start[0] ? 1 : 0; - } - non_separator_found = matches==0 || start[0] == '\0' ? 1 : 0; - if(non_separator_found == 0) - { - start++; - } - } - - while(start[0] != '\0' && split_index < max_pieces) - { - /* find first separator index */ - int first_separator_index = 0; - int separator_found = 0; - while( separator_found == 0 ) - { - int sep_index; - for(sep_index =0; separator_found == 0 && sep_index < num_separators; sep_index++) - { - separator_found = separators[sep_index] == start[first_separator_index] || start[first_separator_index] == '\0' ? 1 : 0; - } - if(separator_found == 0) - { - first_separator_index++; - } - } - - /* copy next piece to split array */ - if(first_separator_index > 0) - { - char* next_piece = NULL; - if(split_index +1 < max_pieces || include_remainder_at_max <= 0) - { - next_piece = (char*)malloc((first_separator_index+1)*sizeof(char)); - memcpy(next_piece, start, first_separator_index); - next_piece[first_separator_index] = '\0'; - } - else - { - next_piece = strdup(start); - } - split[split_index] = next_piece; - split[split_index+1] = NULL; - split_index++; - } - - - /* find next non-separator index, indicating start of next piece */ - start = start+ first_separator_index; - non_separator_found = 0; - while(non_separator_found == 0) - { - int matches = 0; - int sep_index; - for(sep_index =0; sep_index < num_separators; sep_index++) - { - matches = matches == 1 || separators[sep_index] == start[0] ? 1 : 0; - } - non_separator_found = matches==0 || start[0] == '\0' ? 1 : 0; - if(non_separator_found == 0) - { - start++; - } - } - } - free(dup_line); - *num_pieces = split_index; - } - else - { - split = (char**)malloc((1)*sizeof(char*)); - split[0] = NULL; - } - return split; -} - -char* join_strs(char* separator, char** parts, int max_parts, int free_parts, int free_parts_array) -{ - char* joined = NULL; - int num_parts = 0; - for(num_parts=0; parts[num_parts] != NULL && (max_parts < 0 || num_parts < max_parts); num_parts++){} - if(num_parts > 0) - { - num_parts--; - joined = strdup(parts[num_parts]); - if(free_parts){ free(parts[num_parts]); } - num_parts--; - - while(num_parts >= 0) - { - char* tmp = joined; - joined = dynamic_strcat(3, parts[num_parts], separator, joined); - free(tmp); - if(free_parts){ free(parts[num_parts]); } - num_parts--; - } - } - if(free_parts_array) - { - free(parts); - } - return joined; -} - - -char* dynamic_replace(char* template_str, char* old, char* new) -{ - char *ret; - int i, count = 0; - int newlen = strlen(new); - int oldlen = strlen(old); - - char* dyn_template = strdup(template_str); - char* s = dyn_template; - for (i = 0; s[i] != '\0'; i++) - { - if (strstr(&s[i], old) == &s[i]) - { - count++; - i += oldlen - 1; - } - } - ret = malloc(i + 1 + count * (newlen - oldlen)); - - i = 0; - while (*s) - { - if (strstr(s, old) == s) - { - strcpy(&ret[i], new); - i += newlen; - s += oldlen; - } - else - { - ret[i++] = *s++; - } - } - ret[i] = '\0'; - free(dyn_template); - - return ret; -} - -/* - requires expression to be surrounded by '/' characters, and deals with escape - characters '\/', '\r', '\n', and '\t' when escapes haven't been interpreted - (e.g. after recieving regex string from user) - - returns 1 on good regex, 0 on bad regex -*/ -int convert_to_regex(char* str, regex_t* p) -{ - char* trimmed = trim_flanking_whitespace(strdup(str)); - int trimmed_length = strlen(trimmed); - char* new = NULL; - - int valid = 1; - /* regex must be defined by surrounding '/' characters */ - if(trimmed[0] != '/' || trimmed[trimmed_length-1] != '/') - { - valid = 0; - free(trimmed); - } - - if(valid == 1) - { - char* internal = (char*)malloc(trimmed_length*sizeof(char)); - int internal_length = trimmed_length-2; - - int new_index = 0; - int internal_index = 0; - char previous = '\0'; - - - memcpy(internal, trimmed+1, internal_length); - internal[internal_length] = '\0'; - free(trimmed); - - new = (char*)malloc(trimmed_length*sizeof(char)); - while(internal[internal_index] != '\0' && valid == 1) - { - char next = internal[internal_index]; - if(next == '/' && previous != '\\') - { - valid = 0; - } - else if((next == 'n' || next == 'r' || next == 't' || next == '/') && previous == '\\') - { - char previous2 = '\0'; - if(internal_index >= 2) - { - previous2 = internal[internal_index-2]; - } - - new_index = previous2 == '\\' ? new_index : new_index-1; - switch(next) - { - case 'n': - new[new_index] = previous2 == '\\' ? next : '\n'; - break; - case 'r': - new[new_index] = previous2 == '\\' ? next : '\r'; - break; - case 't': - new[new_index] = previous2 == '\\' ? next : '\t'; - break; - case '/': - new[new_index] = previous2 == '\\' ? next : '/'; - break; - } - previous = '\0'; - internal_index++; - new_index++; - - } - else - { - new[new_index] = next; - previous = next; - internal_index++; - new_index++; - } - } - if(valid == 0 || previous == '\\') - { - valid = 0; - free(new); - new = NULL; - } - else - { - new[new_index] = '\0'; - } - free(internal); - } - if(valid == 1) - { - valid = regcomp(p,new,REG_EXTENDED) == 0 ? 1 : 0; - if(valid == 0) - { - regfree(p); - } - free(new); - } - - return valid; -} - -/* note: str element in return value is dynamically allocated, need to free */ -dyn_read_t dynamic_read(FILE* open_file, char* terminators, int num_terminators, unsigned long* read_length) -{ - fpos_t start_pos; - unsigned long size_to_read = 0; - int terminator_found = 0; - int terminator; - char* str; - dyn_read_t ret_value; - - fgetpos(open_file, &start_pos); - - while(terminator_found == 0) - { - int nextch = fgetc(open_file); - int terminator_index = 0; - for(terminator_index = 0; terminator_index < num_terminators && terminator_found == 0; terminator_index++) - { - terminator_found = nextch == terminators[terminator_index] ? 1 : 0; - terminator = nextch; - } - terminator_found = nextch == EOF ? 1 : terminator_found; - terminator = nextch == EOF ? EOF : nextch; - if(terminator_found == 0) - { - size_to_read++; - } - } - - str = (char*)malloc((size_to_read+1)*sizeof(char)); - if(size_to_read > 0) - { - int i; - fsetpos(open_file, &start_pos); - for(i=0; ilength > 0) - { - printf("%s\n", (char*)pop_list(l)); - } - - unsigned long dl; - destroy_list(l, DESTROY_MODE_IGNORE_VALUES, &dl); - - printf("-------queue test-------------\n"); - unsigned long priority; - char* id; - - priority_queue* pq = initialize_priority_queue(); - push_priority_queue(pq, 30, "id_1", "value_1"); - push_priority_queue(pq, 10, "id_2", "value_2"); - push_priority_queue(pq, 10, "id_3", "value_3"); - push_priority_queue(pq, 40, "id_4", "value_4"); - push_priority_queue(pq, 5, "id_5", "value_5"); - push_priority_queue(pq, 30, "id_6", "value_6"); - push_priority_queue(pq, 30, "id_7", "value_7"); - - printf("queue length = %ld\n", pq->length); - unsigned long num_destroyed; - - char* tmp = peek_priority_queue(pq, &priority, &id, 0); - printf("first is \"%s\"\n", tmp); - - set_priority_for_id_in_priority_queue(pq, "id_5", 35); - - tmp = peek_priority_queue(pq, &priority, &id, 0); - printf("first is \"%s\"\n", tmp); - - set_priority_for_id_in_priority_queue(pq, "id_2", 36); - - tmp = peek_priority_queue(pq, &priority, &id, 0); - printf("first is \"%s\"\n", tmp); - - /* - char** values = (char**)destroy_priority_queue(pq, DESTROY_MODE_RETURN_VALUES, &num_destroyed); - int index = 0; - for(index = 0; values[index] != NULL; index++) - { - printf("%s\n", values[index]); - } - */ - - while(pq->length > 0) - { - char* value = (char*)shift_priority_queue(pq, &priority, &id); - printf("%s\n", value); - free(id); - } - destroy_priority_queue(pq, DESTROY_MODE_FREE_VALUES, &dl); - - return 0; -} diff --git a/package/jsda/libericstools/src/test_map.c b/package/jsda/libericstools/src/test_map.c deleted file mode 100644 index ef5552fc8d..0000000000 --- a/package/jsda/libericstools/src/test_map.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright © 2008 by Eric Bishop - * - * This work 'as-is' we provide. - * No warranty, express or implied. - * We've done our best, - * to debug and test. - * Liability for damages denied. - * - * Permission is granted hereby, - * to copy, share, and modify. - * Use as is fit, - * free or for profit. - * On this notice these rights rely. - * - * - * - * Note that unlike other portions of Gargoyle this code - * does not fall under the GPL, but the rather whimsical - * 'Poetic License' above. - * - * Basically, this library contains a bunch of utilities - * that I find useful. I'm sure other libraries exist - * that are just as good or better, but I like these tools - * because I personally wrote them, so I know their quirks. - * (i.e. I know where the bodies are buried). I want to - * make sure that I can re-use these utilities for whatever - * code I may want to write in the future be it - * proprietary or open-source, so I've put them under - * a very, very permissive license. - * - * If you find this code useful, use it. If not, don't. - * I really don't care. - * - */ - -#include "erics_tools.h" -#include - -void get_max_depth(long_map_node* n, unsigned long* max_depth, unsigned long current_depth); -void get_min_depth(long_map_node* n, unsigned long* min_depth, unsigned long current_depth); -void print_map(long_map_node* n, int depth); - -int main (void) -{ - unsigned long num_insertions = 2500; - unsigned long max_insertion = 5000; - int num_repeats = 3; - - unsigned int seed = (unsigned int)time(NULL); - srand (seed); - - printf("TESTING LONG MAP....\n\n"); - printf("initializing map....\n"); - - long_map* lm = initialize_long_map(); - printf("initialized!\n\n"); - - int repeat = 0; - for(repeat =0; repeat < num_repeats; repeat++) - { - - printf("randomly inserting %ld integers randomly selected (not in order) between 0 and %ld\n", num_insertions, max_insertion); - - unsigned long i; - unsigned long dupes = 0; - for(i=0; iroot->left, &left_depth, 0); - get_max_depth(lm->root->right, &right_depth, 0); - - unsigned long original_size = lm->num_elements; - printf("insertion complete\n"); - printf("after insertion, tree size = %ld \n", original_size); - printf("(note this may be less than %ld because the same numbers can be selected for insertion more than once, replacing the original node)\n", num_insertions); - printf("dupes = %ld\n", dupes); - printf("depth of left branch = %ld, depth of right branch = %ld\n\n", left_depth, right_depth); - - if(repeat+1 < num_repeats) - { - printf("randomly selecting %ld numbers between 0 and %ld to remove from tree.\n", num_insertions, max_insertion); - printf("note that these keys will not necessarily be present in tree -- the selection process is entirely random.\n"); - - int j; - int found = 0; - for(j=0; j < num_insertions; j++) - { - - unsigned long r = (unsigned long)(max_insertion*((double)rand()/(double)RAND_MAX)); - if( remove_long_map_element(lm, r) != NULL) - { - found++; - } - } - right_depth = 0; - left_depth = 0; - get_max_depth(lm->root->left, &left_depth, 0); - get_max_depth(lm->root->right, &right_depth, 0); - - printf("removal complete\n"); - printf("after removal, tree size = %ld \n", lm->num_elements); - printf("depth of left branch = %ld, depth of right branch = %ld\n", left_depth, right_depth); - if(original_size - found == lm->num_elements) - { - printf("size consistent with number of nodes successfully removed\n\n"); - } - else - { - printf("SIZE IS BAD -- IS NOT CONSISTENT WITH NUMBER OF NODES REMOVED !!!!\n\n"); - } - - printf("removing remaining nodes in tree in random order\n"); - unsigned long length; - unsigned long *keys = get_sorted_long_map_keys(lm, &length); - while(lm->root != NULL && lm->num_elements > 0) - { - unsigned long r = (unsigned long)(length*((double)rand()/(double)RAND_MAX)); - if( remove_long_map_element(lm, keys[r]) != NULL) - { - found++; - if(original_size - found != lm->num_elements) - { - printf("SIZE IS BAD!!!!\n"); - } - } - } - printf("done removing remaining nodes\n"); - printf("tree size is now %ld, and root is %s\n\n", lm->num_elements, lm->root == NULL ? "null" : "not null"); - - free(keys); - - printf("repeating insertion/deletion\n\n"); - } - else - { - unsigned long num_destroyed; - printf("destroying map...\n"); - void** values = destroy_long_map(lm, DESTROY_MODE_RETURN_VALUES, &num_destroyed); - printf("map destroyed.\n"); - int v=0; - for(v=0; values[v] != NULL; v++){} - free(values); - printf("number of values returned after map destruction = %d\n", v); - - } - } - - printf("LONG MAP TESTING COMPLETE. TESTING STRING MAP (WITH KEY STORAGE) \n\n"); - - printf("initializing map....\n"); - string_map* sm = initialize_string_map(1); - printf("initialized!\n\n"); - - repeat = 0; - for(repeat =0; repeat < num_repeats; repeat++) - { - - printf("randomly inserting %ld integer strings randomly selected (not in order) between 0 and %ld\n", num_insertions, max_insertion); - - unsigned long i; - unsigned long dupes = 0; - for(i=0; ilm.root->left, &left_depth, 0); - get_max_depth(sm->lm.root->right, &right_depth, 0); - - unsigned long original_size = sm->num_elements; - printf("insertion complete\n"); - printf("after insertion, tree size = %ld \n", original_size); - printf("(note this may be less than %ld because the same numbers can be selected for insertion more than once, replacing the original node)\n", num_insertions); - printf("dupes = %ld\n", dupes); - printf("depth of left branch = %ld, depth of right branch = %ld\n\n", left_depth, right_depth); - - if(repeat+1 < num_repeats) - { - printf("randomly selecting %ld numbers between 0 and %ld to remove from tree.\n", num_insertions, max_insertion); - printf("note that these keys will not necessarily be present in tree -- the selection process is entirely random.\n"); - - int j; - int found = 0; - for(j=0; j < num_insertions; j++) - { - unsigned long r = (unsigned long)(max_insertion*((double)rand()/(double)RAND_MAX)); - char* new_str = (char*)malloc(40*sizeof(char)); - sprintf(new_str, "%ld", r); - void* old; - if( (old = remove_string_map_element(sm, new_str)) != NULL) - { - found++; - } - free(new_str); - } - right_depth = 0; - left_depth = 0; - get_max_depth(sm->lm.root->left, &left_depth, 0); - get_max_depth(sm->lm.root->right, &right_depth, 0); - - printf("removal complete\n"); - printf("after removal, tree size = %ld \n", sm->num_elements); - printf("depth of left branch = %ld, depth of right branch = %ld\n", left_depth, right_depth); - if(original_size - found == sm->num_elements) - { - printf("size consistent with number of nodes successfully removed\n\n"); - } - else - { - printf("SIZE IS BAD -- IS NOT CONSISTENT WITH NUMBER OF NODES REMOVED !!!!\n\n"); - } - - printf("removing remaining nodes in tree in random order\n"); - unsigned long length = sm->num_elements; - char** keys = get_string_map_keys(sm, &length); - while(sm->lm.root != NULL && sm->num_elements > 0) - { - unsigned long r = (unsigned long)(length*((double)rand()/(double)RAND_MAX)); - if( remove_string_map_element(sm, keys[r]) != NULL) - { - found++; - if(original_size - found != sm->num_elements) - { - printf("SIZE IS BAD!!!!\n"); - } - } - } - - int k; - for(k=0; knum_elements, sm->lm.root == NULL ? "null" : "not null"); - - printf("repeating insertion/deletion\n\n"); - } - else - { - unsigned long num_destroyed; - printf("destroying map...\n"); - void** values = destroy_string_map(sm, DESTROY_MODE_RETURN_VALUES, &num_destroyed); - printf("map destroyed.\n"); - int v=0; - for(v=0; values[v] != NULL; v++){ } - free(values); - printf("number of values returned after map destruction = %d\n", v); - } - } - - return(0); -} -void get_max_depth(long_map_node* n, unsigned long* max_depth, unsigned long current_depth) -{ - if(n == NULL) - { - *max_depth = current_depth > *max_depth ? current_depth : *max_depth; - return; - } - else - { - *max_depth = current_depth+1 > *max_depth ? current_depth+1 : *max_depth; - get_max_depth(n->left, max_depth, current_depth+1); - get_max_depth(n->right, max_depth, current_depth+1); - } -} -void get_min_depth(long_map_node* n, unsigned long* min_depth, unsigned long current_depth) -{ - if(n == NULL) - { - return; - } - else if(n->left == NULL && n->right == NULL) - { - *min_depth = current_depth < *min_depth ? current_depth : *min_depth; - } - else - { - get_min_depth(n->left, min_depth, current_depth+1); - get_min_depth(n->right, min_depth, current_depth+1); - } -} - -void print_map(long_map_node* n, int depth) -{ - if(n == NULL) - { - return; - } - int i; - for(i=0; i < depth; i++){ printf("\t");} - printf("%ld (%d)\n", n->key, n->balance); - for(i=0; i < depth; i++){ printf("\t");} - printf("left:\n"); - print_map(n->left, depth+1); - for(i=0; i < depth; i++){ printf("\t");} - printf("right:\n"); - print_map(n->right, depth+1); -} diff --git a/package/jsda/libericstools/src/test_string.c b/package/jsda/libericstools/src/test_string.c deleted file mode 100644 index b752dccefd..0000000000 --- a/package/jsda/libericstools/src/test_string.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "erics_tools.h" - -int main(void) -{ - FILE* f = fopen("tmp", "r"); - char terminators[] = "\n\r"; - - unsigned long length; - char* file_data = (char*)read_entire_file(f, 100, &length); - printf("%s\n", file_data); - fclose(f); - - f = fopen("tmp", "r"); - dyn_read_t next; - next.terminator = '\n'; - while(next.terminator != EOF) - { - next = dynamic_read(f, terminators, 2, &length); - printf("read \"%s\"\n", next.str); - free(next.str); - } - fclose(f); - - return 0; -} diff --git a/package/jsda/libericstools/src/tree_map.c b/package/jsda/libericstools/src/tree_map.c deleted file mode 100644 index 9dd14b5627..0000000000 --- a/package/jsda/libericstools/src/tree_map.c +++ /dev/null @@ -1,884 +0,0 @@ -/* - * Copyright © 2008 by Eric Bishop - * - * This work 'as-is' we provide. - * No warranty, express or implied. - * We've done our best, - * to debug and test. - * Liability for damages denied. - * - * Permission is granted hereby, - * to copy, share, and modify. - * Use as is fit, - * free or for profit. - * On this notice these rights rely. - * - * - * - * Note that unlike other portions of Gargoyle this code - * does not fall under the GPL, but the rather whimsical - * 'Poetic License' above. - * - * Basically, this library contains a bunch of utilities - * that I find useful. I'm sure other libraries exist - * that are just as good or better, but I like these tools - * because I personally wrote them, so I know their quirks. - * (i.e. I know where the bodies are buried). I want to - * make sure that I can re-use these utilities for whatever - * code I may want to write in the future be it - * proprietary or open-source, so I've put them under - * a very, very permissive license. - * - * If you find this code useful, use it. If not, don't. - * I really don't care. - * - */ - -#include "erics_tools.h" -#define malloc safe_malloc -#define strdup safe_strdup - -/* internal utility structures/ functions */ -typedef struct stack_node_struct -{ - long_map_node** node_ptr; - signed char direction; - struct stack_node_struct* previous; -} stack_node; - -static void** destroy_long_map_values(long_map* map, int destruction_type, unsigned long* num_destroyed); - -static void apply_to_every_long_map_node(long_map_node* node, void (*apply_func)(unsigned long key, void* value)); - -static void apply_to_every_string_map_node(long_map_node* node, unsigned char has_key, void (*apply_func)(char* key, void* value)); - -static void get_sorted_node_keys(long_map_node* node, unsigned long* key_list, unsigned long* next_key_index, int depth); - -static void get_sorted_node_values(long_map_node* node, void** value_list, unsigned long* next_value_index, int depth); - -static signed char rebalance (long_map_node** n, signed char direction, signed char update_op); - -static void rotate_right (long_map_node** parent); - -static void rotate_left (long_map_node** parent); - -/* internal for string map */ -typedef struct -{ - char* key; - void* value; -} string_map_key_value; - -static unsigned long sdbm_string_hash(const char *key); - -/*************************************************** - * For testing only - ***************************************************/ -/* -void print_list(stack_node *l); - -void print_list(stack_node *l) -{ - if(l != NULL) - { - printf(" list key = %ld, dir=%d, \n", (*(l->node_ptr))->key, l->direction); - print_list(l->previous); - } -} -*/ -/****************************************************** - * End testing Code - *******************************************************/ - - -/*************************************************** - * string_map function definitions - ***************************************************/ - -string_map* initialize_string_map(unsigned char store_keys) -{ - string_map* map = (string_map*)malloc(sizeof(string_map)); - map->store_keys = store_keys; - map->lm.root = NULL; - map->lm.num_elements = 0; - map->num_elements = map->lm.num_elements; - - return map; -} - -void* get_string_map_element(string_map* map, const char* key) -{ - unsigned long hashed_key = sdbm_string_hash(key); - void* return_value = get_long_map_element( &(map->lm), hashed_key); - if(return_value != NULL && map->store_keys) - { - string_map_key_value* r = (string_map_key_value*)return_value; - return_value = r->value; - } - map->num_elements = map->lm.num_elements; - return return_value; -} - -void* set_string_map_element(string_map* map, const char* key, void* value) -{ - unsigned long hashed_key = sdbm_string_hash(key); - void* return_value = NULL; - if(map->store_keys) - { - string_map_key_value* kv = (string_map_key_value*)malloc(sizeof(string_map_key_value)); - kv->key = strdup(key); - kv->value = value; - return_value = set_long_map_element( &(map->lm), hashed_key, kv); - if(return_value != NULL) - { - string_map_key_value* r = (string_map_key_value*)return_value; - return_value = r->value; - free(r->key); - free(r); - } - } - else - { - return_value = set_long_map_element( &(map->lm), hashed_key, value); - } - map->num_elements = map->lm.num_elements; - return return_value; -} - -void* remove_string_map_element(string_map* map, const char* key) -{ - unsigned long hashed_key = sdbm_string_hash(key); - void* return_value = remove_long_map_element( &(map->lm), hashed_key); - - if(return_value != NULL && map->store_keys) - { - string_map_key_value* r = (string_map_key_value*)return_value; - return_value = r->value; - free(r->key); - free(r); - } - map->num_elements = map->lm.num_elements; - return return_value; -} - -char** get_string_map_keys(string_map* map, unsigned long* num_keys_returned) -{ - char** str_keys; - str_keys = (char**)malloc((map->num_elements+1)*sizeof(char*)); - str_keys[0] = NULL; - *num_keys_returned = 0; - if(map->store_keys && map->num_elements > 0) - { - unsigned long list_length; - void** long_values = get_sorted_long_map_values( &(map->lm), &list_length); - unsigned long key_index; - for(key_index = 0; key_index < list_length; key_index++) - { - str_keys[key_index] = strdup( ((string_map_key_value*)(long_values[key_index]))->key); - *num_keys_returned = *num_keys_returned + 1; - } - str_keys[list_length] = NULL; - free(long_values); - } - return str_keys; -} - -void** get_string_map_values(string_map* map, unsigned long* num_values_returned) -{ - void** values = NULL; - if(map != NULL) - { - values = get_sorted_long_map_values ( &(map->lm), num_values_returned ); - } - return values; -} - - - -void** destroy_string_map(string_map* map, int destruction_type, unsigned long* num_destroyed) -{ - void** return_values = NULL; - if(map != NULL) - { - if(map->store_keys) - { - void** kvs = destroy_long_map_values( &(map->lm), DESTROY_MODE_RETURN_VALUES, num_destroyed ); - unsigned long kv_index = 0; - for(kv_index=0; kv_index < *num_destroyed; kv_index++) - { - string_map_key_value* kv = (string_map_key_value*)kvs[kv_index]; - void* value = kv->value; - - free(kv->key); - free(kv); - if(destruction_type == DESTROY_MODE_FREE_VALUES) - { - free(value); - } - if(destruction_type == DESTROY_MODE_RETURN_VALUES) - { - kvs[kv_index] = value; - } - } - if(destruction_type == DESTROY_MODE_RETURN_VALUES) - { - return_values = kvs; - } - else - { - free(kvs); - } - } - else - { - return_values = destroy_long_map_values( &(map->lm), destruction_type, num_destroyed ); - } - free(map); - } - return return_values; -} - -/*************************************************** - * long_map function definitions - ***************************************************/ - -long_map* initialize_long_map(void) -{ - long_map* map = (long_map*)malloc(sizeof(long_map)); - map->root = NULL; - map->num_elements = 0; - - return map; -} - -void* get_long_map_element(long_map* map, unsigned long key) -{ - void* value = NULL; - - if(map->root != NULL) - { - long_map_node* parent_node = map->root; - long_map_node* next_node; - while( key != parent_node->key && (next_node = (long_map_node *)(key < parent_node->key ? parent_node->left : parent_node->right)) != NULL) - { - parent_node = next_node; - } - if(parent_node->key == key) - { - value = parent_node->value; - } - } - return value; -} - -void* get_smallest_long_map_element(long_map* map, unsigned long* smallest_key) -{ - void* value = NULL; - if(map->root != NULL) - { - long_map_node* next_node = map->root; - while( next_node->left != NULL) - { - next_node = next_node->left; - } - value = next_node->value; - *smallest_key = next_node->key; - } - return value; -} - -void* get_largest_long_map_element(long_map* map, unsigned long* largest_key) -{ - void* value = NULL; - if(map->root != NULL) - { - long_map_node* next_node = map->root; - while( next_node->right != NULL) - { - next_node = next_node->right; - } - value = next_node->value; - *largest_key = next_node->key; - } - return value; -} - -void* remove_smallest_long_map_element(long_map* map, unsigned long* smallest_key) -{ - get_smallest_long_map_element(map, smallest_key); - return remove_long_map_element(map, *smallest_key); -} - -void* remove_largest_long_map_element(long_map* map, unsigned long* largest_key) -{ - get_largest_long_map_element(map, largest_key); - return remove_long_map_element(map, *largest_key); -} - - -/* if replacement performed, returns replaced value, otherwise null */ -void* set_long_map_element(long_map* map, unsigned long key, void* value) -{ - stack_node* parent_list = NULL; - void* old_value = NULL; - int old_value_found = 0; - - long_map_node* parent_node; - long_map_node* next_node; - stack_node* next_parent; - stack_node* previous_parent; - signed char new_balance; - - long_map_node* new_node = (long_map_node*)malloc(sizeof(long_map_node)); - new_node->value = value; - new_node->key = key; - new_node->left = NULL; - new_node->right = NULL; - new_node->balance = 0; - - if(map->root == NULL) - { - map->root = new_node; - } - else - { - parent_node = map->root; - - next_parent = (stack_node*)malloc(sizeof(stack_node)); - next_parent->node_ptr = &(map->root); - next_parent->previous = parent_list; - parent_list = next_parent; - - while( key != parent_node->key && (next_node = (key < parent_node->key ? parent_node->left : parent_node->right) ) != NULL) - { - next_parent = (stack_node*)malloc(sizeof(stack_node)); - next_parent->node_ptr = key < parent_node->key ? &(parent_node->left) : &(parent_node->right); - next_parent->previous = parent_list; - next_parent->previous->direction = key < parent_node->key ? -1 : 1; - parent_list = next_parent; - - parent_node = next_node; - } - - - if(key == parent_node->key) - { - old_value = parent_node->value; - old_value_found = 1; - parent_node->value = value; - free(new_node); - /* we merely replaced a node, no need to rebalance */ - } - else - { - if(key < parent_node->key) - { - parent_node->left = (void*)new_node; - parent_list->direction = -1; - } - else - { - parent_node->right = (void*)new_node; - parent_list->direction = 1; - } - - - /* we inserted a node, rebalance */ - previous_parent = parent_list; - new_balance = 1; /* initial value is not used, but must not be 0 for initial loop condition */ - - - while(previous_parent != NULL && new_balance != 0) - { - new_balance = rebalance(previous_parent->node_ptr, previous_parent->direction, 1); - previous_parent = previous_parent->previous; - } - } - } - - while(parent_list != NULL) - { - previous_parent = parent_list; - parent_list = previous_parent->previous; - free(previous_parent); - } - - if(old_value_found == 0) - { - map->num_elements = map->num_elements + 1; - } - - return old_value; -} - - -void* remove_long_map_element(long_map* map, unsigned long key) -{ - - void* value = NULL; - - long_map_node* root_node = map->root; - stack_node* parent_list = NULL; - - long_map_node* remove_parent; - long_map_node* remove_node; - long_map_node* next_node; - - long_map_node* replacement; - long_map_node* replacement_parent; - long_map_node* replacement_next; - - stack_node* next_parent; - stack_node* previous_parent; - stack_node* replacement_stack_node; - - signed char new_balance; - - if(root_node != NULL) - { - remove_parent = root_node; - remove_node = key < remove_parent->key ? remove_parent->left : remove_parent->right; - - if(remove_node != NULL && key != remove_parent->key) - { - next_parent = (stack_node*)malloc(sizeof(stack_node)); - next_parent->node_ptr = &(map->root); - next_parent->previous = parent_list; - parent_list = next_parent; - while( key != remove_node->key && (next_node = (key < remove_node->key ? remove_node->left : remove_node->right)) != NULL) - { - next_parent = (stack_node*)malloc(sizeof(stack_node)); - next_parent->node_ptr = key < remove_parent->key ? &(remove_parent->left) : &(remove_parent->right); - next_parent->previous = parent_list; - next_parent->previous->direction = key < remove_parent->key ? -1 : 1; - parent_list = next_parent; - - remove_parent = remove_node; - remove_node = next_node; - } - parent_list->direction = key < remove_parent-> key ? -1 : 1; - } - else - { - remove_node = remove_parent; - } - - if(key == remove_node->key) - { - /* find replacement for node we are deleting */ - if( remove_node->right == NULL ) - { - replacement = remove_node->left; - } - else if( remove_node->right->left == NULL) - { - - replacement = remove_node->right; - replacement->left = remove_node->left; - replacement->balance = remove_node->balance; - - /* put pointer to replacement node into list for balance update */ - replacement_stack_node = (stack_node*)malloc(sizeof(stack_node));; - replacement_stack_node->previous = parent_list; - replacement_stack_node->direction = 1; /* replacement is from right */ - if(remove_node == remove_parent) /* special case for root node */ - { - replacement_stack_node->node_ptr = &(map->root); - } - else - { - replacement_stack_node->node_ptr = key < remove_parent-> key ? &(remove_parent->left) : &(remove_parent->right); - } - parent_list = replacement_stack_node; - } - else - { - /* put pointer to replacement node into list for balance update */ - replacement_stack_node = (stack_node*)malloc(sizeof(stack_node)); - replacement_stack_node->previous = parent_list; - replacement_stack_node->direction = 1; /* we always look for replacement on right */ - if(remove_node == remove_parent) /* special case for root node */ - { - replacement_stack_node->node_ptr = &(map->root); - } - else - { - replacement_stack_node->node_ptr = key < remove_parent-> key ? &(remove_parent->left) : &(remove_parent->right); - } - - parent_list = replacement_stack_node; - - /* - * put pointer to replacement node->right into list for balance update - * this node will have to be updated with the proper pointer - * after we have identified the replacement - */ - replacement_stack_node = (stack_node*)malloc(sizeof(stack_node)); - replacement_stack_node->previous = parent_list; - replacement_stack_node->direction = -1; /* we always look for replacement to left of this node */ - parent_list = replacement_stack_node; - - /* find smallest node on right (large) side of tree */ - replacement_parent = remove_node->right; - replacement = replacement_parent->left; - - while((replacement_next = replacement->left) != NULL) - { - next_parent = (stack_node*)malloc(sizeof(stack_node)); - next_parent->node_ptr = &(replacement_parent->left); - next_parent->previous = parent_list; - next_parent->direction = -1; /* we always go left */ - parent_list = next_parent; - - replacement_parent = replacement; - replacement = replacement_next; - } - - replacement_parent->left = replacement->right; - - replacement->left = remove_node->left; - replacement->right = remove_node->right; - replacement->balance = remove_node->balance; - replacement_stack_node->node_ptr = &(replacement->right); - } - - /* insert replacement at proper location in tree */ - if(remove_node == remove_parent) - { - map->root = replacement; - } - else - { - remove_parent->left = remove_node == remove_parent->left ? replacement : remove_parent->left; - remove_parent->right = remove_node == remove_parent->right ? replacement : remove_parent->right; - } - - /* rebalance tree */ - previous_parent = parent_list; - new_balance = 0; - while(previous_parent != NULL && new_balance == 0) - { - new_balance = rebalance(previous_parent->node_ptr, previous_parent->direction, -1); - previous_parent = previous_parent->previous; - } - - /* - * since we found a value to remove, decrease number of elements in map - * set return value to the deleted node's value and free the node - */ - map->num_elements = map->num_elements - 1; - value = remove_node->value; - free(remove_node); - } - } - - while(parent_list != NULL) - { - previous_parent = parent_list; - parent_list = previous_parent->previous; - free(previous_parent); - } - - return value; -} - - -/* note: returned keys are dynamically allocated, you need to free them! */ -unsigned long* get_sorted_long_map_keys(long_map* map, unsigned long* num_keys_returned) -{ - unsigned long* key_list = (unsigned long*)malloc((map->num_elements)*sizeof(unsigned long)); - - unsigned long next_key_index = 0; - get_sorted_node_keys(map->root, key_list, &next_key_index, 0); - - *num_keys_returned = map->num_elements; - - return key_list; -} - -void** get_sorted_long_map_values(long_map* map, unsigned long* num_values_returned) -{ - void** value_list = (void**)malloc((map->num_elements+1)*sizeof(void*)); - - unsigned long next_value_index = 0; - get_sorted_node_values(map->root, value_list, &next_value_index, 0); - value_list[map->num_elements] = NULL; /* since we're dealing with pointers make list null terminated */ - - *num_values_returned = map->num_elements; - return value_list; -} - -void** destroy_long_map(long_map* map, int destruction_type, unsigned long* num_destroyed) -{ - void** return_values = NULL; - unsigned long return_index = 0; - - *num_destroyed = 0; - - if(destruction_type == DESTROY_MODE_RETURN_VALUES) - { - return_values = (void**)malloc((map->num_elements+1)*sizeof(void*)); - return_values[map->num_elements] = NULL; - } - while(map->num_elements > 0) - { - unsigned long smallest_key = 0; - void* removed_value = remove_smallest_long_map_element(map, &smallest_key); - if(destruction_type == DESTROY_MODE_RETURN_VALUES) - { - return_values[return_index] = removed_value; - } - if(destruction_type == DESTROY_MODE_FREE_VALUES) - { - free(removed_value); - } - return_index++; - *num_destroyed = *num_destroyed + 1; - } - free(map); - - return return_values; -} - -void apply_to_every_long_map_value(long_map* map, void (*apply_func)(unsigned long key, void* value)) -{ - apply_to_every_long_map_node(map->root, apply_func); -} -void apply_to_every_string_map_value(string_map* map, void (*apply_func)(char* key, void* value)) -{ - apply_to_every_string_map_node( (map->lm).root, map->store_keys, apply_func); -} - -/*************************************************** - * internal utility function definitions - ***************************************************/ -static void** destroy_long_map_values(long_map* map, int destruction_type, unsigned long* num_destroyed) -{ - void** return_values = NULL; - unsigned long return_index = 0; - - *num_destroyed = 0; - - if(destruction_type == DESTROY_MODE_RETURN_VALUES) - { - return_values = (void**)malloc((map->num_elements+1)*sizeof(void*)); - return_values[map->num_elements] = NULL; - } - while(map->num_elements > 0) - { - unsigned long smallest_key = 0; - void* removed_value = remove_smallest_long_map_element(map, &smallest_key); - if(destruction_type == DESTROY_MODE_RETURN_VALUES) - { - return_values[return_index] = removed_value; - } - if(destruction_type == DESTROY_MODE_FREE_VALUES) - { - free(removed_value); - } - return_index++; - *num_destroyed = *num_destroyed + 1; - } - return return_values; -} - -static void apply_to_every_long_map_node(long_map_node* node, void (*apply_func)(unsigned long key, void* value)) -{ - if(node != NULL) - { - apply_to_every_long_map_node(node->left, apply_func); - - apply_func(node->key, node->value); - - apply_to_every_long_map_node(node->right, apply_func); - } -} -static void apply_to_every_string_map_node(long_map_node* node, unsigned char has_key, void (*apply_func)(char* key, void* value)) -{ - if(node != NULL) - { - apply_to_every_string_map_node(node->left, has_key, apply_func); - - if(has_key) - { - string_map_key_value* kv = (string_map_key_value*)(node->value); - apply_func(kv->key, kv->value); - } - else - { - apply_func(NULL, node->value); - } - apply_to_every_string_map_node(node->right, has_key, apply_func); - } -} - - -static void get_sorted_node_keys(long_map_node* node, unsigned long* key_list, unsigned long* next_key_index, int depth) -{ - if(node != NULL) - { - get_sorted_node_keys(node->left, key_list, next_key_index, depth+1); - - key_list[ *next_key_index ] = node->key; - (*next_key_index)++; - - get_sorted_node_keys(node->right, key_list, next_key_index, depth+1); - } -} - -static void get_sorted_node_values(long_map_node* node, void** value_list, unsigned long* next_value_index, int depth) -{ - if(node != NULL) - { - get_sorted_node_values(node->left, value_list, next_value_index, depth+1); - - value_list[ *next_value_index ] = node->value; - (*next_value_index)++; - - get_sorted_node_values(node->right, value_list, next_value_index, depth+1); - } -} - -/* - * direction = -1 indicates left subtree updated, direction = 1 for right subtree - * update_op = -1 indicates delete node, update_op = 1 for insert node - */ -static signed char rebalance (long_map_node** n, signed char direction, signed char update_op) -{ - /* - printf( "original: key = %ld, balance = %d, update_op=%d, direction=%d\n", (*n)->key, (*n)->balance, update_op, direction); - */ - - (*n)->balance = (*n)->balance + (update_op*direction); - - if( (*n)->balance < -1) - { - if((*n)->left->balance < 0) - { - rotate_right(n); - (*n)->right->balance = 0; - (*n)->balance = 0; - } - else if((*n)->left->balance == 0) - { - rotate_right(n); - (*n)->right->balance = -1; - (*n)->balance = 1; - } - else if((*n)->left->balance > 0) - { - rotate_left( &((*n)->left) ); - rotate_right(n); - /* - if( (*n)->balance < 0 ) - { - (*n)->left->balance = 0; - (*n)->right->balance = 1; - } - else if( (*n)->balance == 0 ) - { - (*n)->left->balance = 0; - (*n)->right->balance = 0; - } - else if( (*n)->balance > 0 ) - { - (*n)->left->balance = -1; - (*n)->right->balance = 0; - } - */ - (*n)->left->balance = (*n)->balance > 0 ? -1 : 0; - (*n)->right->balance = (*n)->balance < 0 ? 1 : 0; - (*n)->balance = 0; - } - } - if( (*n)->balance > 1) - { - if((*n)->right->balance > 0) - { - rotate_left(n); - (*n)->left->balance = 0; - (*n)->balance = 0; - } - else if ((*n)->right->balance == 0) - { - rotate_left(n); - (*n)->left->balance = 1; - (*n)->balance = -1; - } - else if((*n)->right->balance < 0) - { - rotate_right( &((*n)->right) ); - rotate_left(n); - /* - if( (*n)->balance < 0 ) - { - (*n)->left->balance = 0; - (*n)->right->balance = 1; - } - else if( (*n)->balance == 0 ) - { - (*n)->left->balance = 0; - (*n)->right->balance = 0; - } - else if( (*n)->balance > 0 ) - { - (*n)->left->balance = -1; - (*n)->right->balance = 0; - } - */ - (*n)->left->balance = (*n)->balance > 0 ? -1 : 0; - (*n)->right->balance = (*n)->balance < 0 ? 1 : 0; - (*n)->balance = 0; - } - } - - /* - printf( "key = %ld, balance = %d\n", (*n)->key, (*n)->balance); - */ - - return (*n)->balance; -} - -static void rotate_right (long_map_node** parent) -{ - long_map_node* old_parent = *parent; - long_map_node* pivot = old_parent->left; - old_parent->left = pivot->right; - pivot->right = old_parent; - - *parent = pivot; -} - -static void rotate_left (long_map_node** parent) -{ - long_map_node* old_parent = *parent; - long_map_node* pivot = old_parent->right; - old_parent->right = pivot->left; - pivot->left = old_parent; - - *parent = pivot; -} - -/*************************************************************************** - * This algorithm was created for the sdbm database library (a public-domain - * reimplementation of ndbm) and seems to work relatively well in - * scrambling bits - * - * - * This code was derived from code found at: - * http://www.cse.yorku.ca/~oz/hash.html - ***************************************************************************/ -static unsigned long sdbm_string_hash(const char *key) -{ - unsigned long hashed_key = 0; - - int index = 0; - unsigned int nextch; - while(key[index] != '\0') - { - nextch = key[index]; - hashed_key = nextch + (hashed_key << 6) + (hashed_key << 16) - hashed_key; - index++; - } - return hashed_key; -} diff --git a/package/jsda/libiptbwctl/Makefile b/package/jsda/libiptbwctl/Makefile deleted file mode 100644 index 74c80fdf73..0000000000 --- a/package/jsda/libiptbwctl/Makefile +++ /dev/null @@ -1,74 +0,0 @@ -# -# Copyright (C) 2006 OpenWrt.org -# Copyright (C) 2009 Eric Bishop -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=libiptbwctl -PKG_VERSION:=1.0.0 -PKG_RELEASE:=1 - -PKG_BUILD_DIR:=$(BUILD_DIR)/libiptbwctl - -include $(INCLUDE_DIR)/package.mk - -define Package/libiptbwctl - SECTION:=net - CATEGORY:=Gargoyle - SUBMENU:=Network - DEPENDS:=+iptables-mod-bandwidth - TITLE:=IPT bandwidth control library - URL:=http://www.gargoyle-router.com - MAINTAINER:=Eric Bishop -endef - -define Package/libiptbwctl/description - IPT bandwidth control library -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - -define Build/Configure -endef - -define Build/Compile - -$(MAKE) -C $(PKG_BUILD_DIR) clean - $(MAKE) -C $(PKG_BUILD_DIR) \ - $(TARGET_CONFIGURE_OPTS) \ - STAGING_DIR="$(STAGING_DIR)" \ - CFLAGS="$(TARGET_CFLAGS) -I $(STAGING_DIR)/usr/include" \ - LDFLAGS="$(TARGET_LDFLAGS) -L $(STAGING_DIR)/usr/lib" \ - all - - mkdir -p $(STAGING_DIR)/usr/include/ - $(CP) $(PKG_BUILD_DIR)/*.h $(STAGING_DIR)/usr/include/ - - mkdir -p $(STAGING_DIR)/usr/lib - $(CP) $(PKG_BUILD_DIR)/*.so* $(STAGING_DIR)/usr/lib/ - - $(MAKE) -C $(PKG_BUILD_DIR)/utils \ - $(TARGET_CONFIGURE_OPTS) \ - STAGING_DIR="$(STAGING_DIR)" \ - CFLAGS="$(TARGET_CFLAGS) -I $(STAGING_DIR)/usr/include" \ - LDFLAGS="$(TARGET_LDFLAGS) -L $(STAGING_DIR)/usr/lib" \ - all -endef - -define Package/libiptbwctl/install - $(INSTALL_DIR) $(1)/usr/lib - $(INSTALL_DIR) $(1)/usr/bin - $(CP) $(PKG_BUILD_DIR)/*.so* $(1)/usr/lib/ - $(INSTALL_BIN) $(PKG_BUILD_DIR)/utils/bw_get $(1)/usr/bin/bw_get - $(INSTALL_BIN) $(PKG_BUILD_DIR)/utils/bw_set $(1)/usr/bin/bw_set - $(INSTALL_BIN) $(PKG_BUILD_DIR)/utils/bw_print_history_file $(1)/usr/bin/bw_print_history_file - $(INSTALL_BIN) $(PKG_BUILD_DIR)/utils/set_kernel_timezone $(1)/usr/bin/set_kernel_timezone -endef - -$(eval $(call BuildPackage,libiptbwctl)) diff --git a/package/jsda/libiptbwctl/src/Makefile b/package/jsda/libiptbwctl/src/Makefile deleted file mode 100644 index 42c308fc73..0000000000 --- a/package/jsda/libiptbwctl/src/Makefile +++ /dev/null @@ -1,60 +0,0 @@ -VERSION=1 - -ifeq ($(CC),) - CC=gcc -endif - -ifeq ($(LD),) - LD=ld -endif - -ifeq ($(AR),) - AR=ar -endif - -ifeq ($(RANLIB),) - RANLIB=ranlib -endif - -OS=$(shell uname) -ifeq ($(OS),Darwin) - LINK=$(LD) - SHLIB_EXT=dylib - SHLIB_FLAGS=-dylib - SHLIB_FILE=libiptbwctl.$(SHLIB_EXT).$(VERSION) -else - LINK=$(CC) - SHLIB_EXT=so - SHLIB_FILE=libiptbwctl.$(SHLIB_EXT).$(VERSION) - SHLIB_FLAGS=-shared -Wl,-soname,$(SHLIB_FILE) -endif - -CFLAGS:=$(CFLAGS) -Os -WARNING_FLAGS=-Wall -Wstrict-prototypes - -all: libiptbwctl - -libiptbwctl: libiptbwctl.$(SHLIB_EXT) libiptbwctl.a - -libiptbwctl.a: ipt_bwctl_static.o ipt_bwctl_safe_malloc_static.o - if [ -e $@ ] ; then rm $@ ; fi - $(AR) rc $@ $^ - $(RANLIB) $@ - -libiptbwctl.$(SHLIB_EXT) : ipt_bwctl_dyn.o ipt_bwctl_safe_malloc_dyn.o - if [ -e libiptbwctl.$(SHLIB_EXT) ] ; then rm libiptbwctl.$(SHLIB_EXT)* ; fi - $(LINK) $(LDFLAGS) $(SHLIB_FLAGS) -o $(SHLIB_FILE) $^ -lc - ln -s $(SHLIB_FILE) libiptbwctl.$(SHLIB_EXT) - -%_dyn.o: %.c - $(CC) $(CFLAGS) -fPIC $(WARNING_FLAGS) -o $@ -c $^ - -%_static.o: %.c - $(CC) $(CFLAGS) $(WARNING_FLAGS) -o $@ -c $^ - -clean: - cd utils - rm -rf bw_get bw_set *.a *.o *~ .*sw* - cd .. - if [ -n "$(SHLIB_EXT)" ] ; then rm -rf *.$(SHLIB_EXT)* ; fi - rm -rf *.a *.o *~ .*sw* diff --git a/package/jsda/libiptbwctl/src/ipt_bwctl.c b/package/jsda/libiptbwctl/src/ipt_bwctl.c deleted file mode 100644 index c5d669ca72..0000000000 --- a/package/jsda/libiptbwctl/src/ipt_bwctl.c +++ /dev/null @@ -1,1279 +0,0 @@ -/* libiptbwctl -- A userspace library for querying the bandwidth iptables module - * Originally designed for use with Gargoyle router firmware (gargoyle-router.com) - * - * - * Copyright © 2009 by Eric Bishop - * - * This file is free software: you may copy, redistribute 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 file 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 "ipt_bwctl.h" -#define malloc ipt_bwctl_safe_malloc -#define strdup ipt_bwctl_safe_strdup - -static int bandwidth_semaphore = -1; - -union semun -{ - int val; // Value for SETVAL - struct semid_ds *buf; // Buffer for IPC_STAT, IPC_SET - unsigned short *array; // Array for GETALL, SETALL - struct seminfo *__buf; // Buffer for IPC_INFO (Linux specific) -}; - -/* semaphore functions */ -static int get_sem_val(int sid, int member); -static int get_sem(int *sid, key_t key); -static int lock_sem(int sid); -static int unlock_sem(int sid); -static int lock(unsigned long max_wait_milliseconds); -static int unlock(void); - -/* needed to calculate history time intervals */ -static time_t get_next_node_start_time(time_t current_start_time, - time_t reset_interval, - time_t reset_time, - unsigned char is_constant_interval - ); - -/* functions used to get data from kernel module */ -static void parse_returned_ip_data(void *out_data, - uint32_t* out_index, - unsigned char* in_buffer, - uint32_t* in_index, - unsigned char get_history, - time_t reset_interval, - time_t reset_time, - unsigned char is_constant_interval - ); - -static int get_bandwidth_data(char* id, - unsigned char get_history, - char* ip, - unsigned long* num_ips, - void** data, - unsigned long max_wait_milliseconds - ); - -/* functions used to send/restore data to kernel module */ -static int set_ip_block(void* ip_block_data, - unsigned char is_history, - unsigned char* output_buffer, - uint32_t* current_output_index, - uint32_t output_buffer_length - ); - -static int set_bandwidth_data(char* id, - unsigned char zero_unset, - unsigned char set_history, - unsigned long num_ips, - time_t last_backup, - void* data, - unsigned long max_wait_milliseconds - ); - -/* utility i/o functions when saving/restoring data to/from file */ -static unsigned char* read_entire_file(FILE* in, - unsigned long read_block_size, - unsigned long *length - ); - -static char** split_on_separators(char* line, - char* separators, - int num_separators, - int max_pieces, - int include_remainder_at_max, - unsigned long *pieces_read - ); - -static int get_sem_val(int sid, int member) -{ - int semval; - semval = semctl(sid, member, GETVAL, 0); - return(semval); -} - -static int get_sem(int *sid, key_t key) -{ - int cntr; - union semun semopts; - int members = 1; - - int success = ((*sid = semget(key, members, IPC_CREAT|IPC_EXCL|0777))== -1) ? 0 : 1; - if(success) - { - semopts.val = 1; - /* Initialize all members (could be done with SETALL) */ - for(cntr=0; cntr 0) - { - sem_lock.sem_num = member; - if((semop(sid, &sem_lock, 1)) != -1) - { - success = 1; - } - } - - return success; -} - -static int unlock_sem(int sid) -{ - int member = 0; - struct sembuf sem_unlock={ member, 1, IPC_NOWAIT}; - - /* will fail if we can't can't unlock semaphore for some reason, - * will NOT fail if semaphore is already unlocked - */ - int success = 1; - - /* Is the semaphore set locked? */ - int semval = get_sem_val(sid, member); - if(semval == 0) - { - /* it's locked, unlock it */ - sem_unlock.sem_num = member; - success = ((semop(sid, &sem_unlock, 1)) == -1) ? 0 : 1; - } - return success; -} - - - -static int lock(unsigned long max_wait_milliseconds) -{ - int locked = 0; - if(bandwidth_semaphore == -1) - { - get_sem(&bandwidth_semaphore, (key_t)(BANDWIDTH_SEMAPHORE_KEY) ); - } - if(bandwidth_semaphore != -1) - { - do - { - locked = lock_sem(bandwidth_semaphore); - if(locked == 0 && max_wait_milliseconds > 25) - { - usleep(1000*25); - } - max_wait_milliseconds = max_wait_milliseconds > 25 ? max_wait_milliseconds - 25 : 0; - } while(locked == 0 && max_wait_milliseconds > 0); - } - return locked; -} - -static int unlock(void) -{ - int unlocked = 0; - if(bandwidth_semaphore == -1) - { - get_sem(&bandwidth_semaphore, (key_t)(BANDWIDTH_SEMAPHORE_KEY) ); - } - if(bandwidth_semaphore != -1) - { - unlocked = unlock_sem(bandwidth_semaphore); - } - return unlocked; -} - -static time_t get_next_node_start_time(time_t current_start_time, - time_t reset_interval, - time_t reset_time, - unsigned char is_constant_interval - ) -{ - time_t next = current_start_time; - if(is_constant_interval) - { - next = current_start_time + reset_interval; - } - else - { - while(next + reset_time <= current_start_time) - { - struct tm* curr = localtime(¤t_start_time); - curr->tm_isdst = -1; - if(reset_interval == BANDWIDTH_MINUTE) - { - curr->tm_sec = 0; - curr->tm_min = curr->tm_min+1; - next = mktime(curr); - } - else if(reset_interval == BANDWIDTH_HOUR) - { - curr->tm_sec = 0; - curr->tm_min = 0; - curr->tm_hour = curr->tm_hour+1; - next = mktime(curr); - } - else if(reset_interval == BANDWIDTH_DAY) - { - curr->tm_sec = 0; - curr->tm_min = 0; - curr->tm_hour = 0; - curr->tm_mday = curr->tm_mday+1; - next = mktime(curr); - } - else if(reset_interval == BANDWIDTH_WEEK) - { - curr->tm_sec = 0; - curr->tm_min = 0; - curr->tm_hour = 0; - curr->tm_mday = curr->tm_mday+1; - time_t tmp = mktime(curr); - curr = localtime(&tmp); - while(curr->tm_wday != 0) - { - curr->tm_mday=curr->tm_mday+1; - tmp = mktime(curr); - curr = localtime(&tmp); - } - next = mktime(curr); - } - else if(reset_interval == BANDWIDTH_MONTH) - { - curr->tm_sec = 0; - curr->tm_min = 0; - curr->tm_hour = 0; - curr->tm_mday = 1; - curr->tm_mon = curr->tm_mon+1; - next = mktime(curr); - } - } - next = next + reset_time; - } - return next; -} - -static void parse_returned_ip_data(void *out_data, - uint32_t* out_index, - unsigned char* in_buffer, - uint32_t* in_index, - unsigned char get_history, - time_t reset_interval, - time_t reset_time, - unsigned char is_constant_interval - ) -{ - uint32_t ip = *( (uint32_t*)(in_buffer + *in_index) ); - ip_bw_kernel_data_item* ip_bw_data = (ip_bw_kernel_data*)(in_buffer + *in_index); - if(get_history == 0) - { - (((ip_bw*)out_data)[*out_index]).ip = ip; - *in_index = *in_index + 4; - (((ip_bw*)out_data)[*out_index]).bw = *( (uint64_t*)(in_buffer + *in_index) ); - *in_index = *in_index + 8; - } - else - { - ip_bw_history *history = ((ip_bw_history*)out_data) + *out_index; - history->reset_interval = reset_interval; - history->reset_time = reset_time; - history->is_constant_interval = is_constant_interval; - - history->ip = ip_bw_data->ip; - history->num_nodes = ip_bw_data->num_nodes; - history->first_start = ip_bw_data->first_start; - history->first_end = ip_bw_data->first_end; - history->last_end = ip_bw_data->last_end; - - history->history_bws = (uint64_t*)malloc( (history->num_nodes+1)*sizeof(uint64_t) ); - - /* read bws */ - int node_index = 0; - *in_index += 32; - for (node_index = 0; node_index < history->num_nodes; node_index++) - { - *in_index += 8; - (history->history_bws)[node_index] = ip_bw_data->ipbw_data[node_index]; - } - - /* - * We now need to deal with DST - * - * The problem is that the kernel can't tell the difference - * between timezones being switched and entering daylight savings - * time. Whenever the time offset from UTC shifts, the kernel module - * shifts values in the bandwidth history to reflect the time - * as it would be if the current offset from UTC had always been - * in effect. So, we need to go backwards through the history and - * anytime we go from DST to non-DST (or visa-versa) implement a - * shift so that returned times reflect reality. - */ - time_t now; - time(&now); - int current_minutes_west = get_minutes_west(now); - history->first_start = history->first_start + (60*(get_minutes_west(history->first_start)-current_minutes_west)); - history->first_end = history->first_end + (60*(get_minutes_west(history->first_end)-current_minutes_west)); - history->last_end = history->last_end + (60*(get_minutes_west(history->last_end)-current_minutes_west)); - } - *out_index = *out_index + 1; -} - -static int get_bandwidth_data(char* id, unsigned char get_history, char* ip, unsigned long* num_ips, void** data, unsigned long max_wait_milliseconds) -{ - unsigned char buf[BANDWIDTH_QUERY_LENGTH]; - memset(buf, '\0', BANDWIDTH_QUERY_LENGTH); - int done = 0; - ip_bw_kernel_data* ip_bw_data = (ip_bw_kernel_data*)(buf); - - *data = NULL; - *num_ips = 0; - - int got_lock = lock(max_wait_milliseconds); - int sockfd = -1; - if(got_lock) - { - sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); - } - - uint32_t* request_ip = (uint32_t*)buf; - uint32_t* request_index = (uint32_t*)(buf + 4); - unsigned char* request_history =(unsigned char*)(buf + 8); - char* request_id = (char*)(buf+9); - - if(strcmp(ip, "ALL") == 0) - { - *request_ip = 0; - } - else - { - struct in_addr addr; - inet_aton(ip, &addr); - *request_ip = (uint32_t)addr.s_addr; - } - *request_index = 0; - *request_history = get_history; - sprintf(request_id, "%s", id); - - unsigned char error = 0; - unsigned char data_initialized = 0; - uint32_t data_index = 0; - while(!done && sockfd >= 0 && got_lock) - { - uint32_t size = BANDWIDTH_QUERY_LENGTH; - - getsockopt(sockfd, IPPROTO_IP, BANDWIDTH_GET, buf, &size); - - error = (unsigned char)buf[0]; - if(error != 0) - { - done = 1; - } - else - { - uint32_t total_ips = ip_bw_data->ip_total; - /*uint32_t next_ip_index = *( (uint32_t*)(buf+5) ); //unused */ - uint32_t response_ips = ip_bw_data->ip_num; - time_t reset_interval = ip_bw_data->reset_interval; - time_t reset_time = ip_bw_data->reset_time; - unsigned char is_constant_interval = ip_bw_data->reset_is_constant_interval; - - if(!data_initialized) - { - *num_ips = total_ips; - if(get_history) - { - *data = (void*)malloc(sizeof(ip_bw_history)*(total_ips+1)); - memset(*data, 0, sizeof(ip_bw_history)*(total_ips+1)); - } - else - { - *data = (void*)malloc(sizeof(ip_bw)*(total_ips+1)); - memset(*data, 0, sizeof(ip_bw)*(total_ips+1)); - } - } - - int response_index=0; - uint32_t buffer_index = 30; - for(response_index=0; response_index < response_ips; response_index++) - { - parse_returned_ip_data(*data, &data_index, buf, &buffer_index, get_history, reset_interval, reset_time, is_constant_interval); - } - *request_index= *request_index + response_ips; - done = *request_index < total_ips ? 0 : 1; - } - } - if( (error != 0) && data_initialized) - { - if(get_history) - { - free_ip_bw_histories( (ip_bw_history*)(*data), *num_ips ); - } - else - { - free(*data); - } - *data = NULL; - *num_ips = 0; - } - - if(sockfd >= 0) - { - close(sockfd); - } - if(got_lock) - { - unlock(); - } - return got_lock && (error == 0); -} - -static int set_ip_block(void* ip_block_data, unsigned char is_history, unsigned char* output_buffer, uint32_t* current_output_index, uint32_t output_buffer_length) -{ - if(is_history) - { - ip_bw_history* history = (ip_bw_history*)ip_block_data; - uint32_t block_length = (2*4) + (3*8) + (8*history->num_nodes); - if(*current_output_index + block_length > output_buffer_length) - { - return 1; - } - - *( (uint32_t*)(output_buffer + *current_output_index) ) = history->ip; - *current_output_index = *current_output_index + 4; - - *( (uint32_t*)(output_buffer + *current_output_index) ) = history->num_nodes; - *current_output_index = *current_output_index + 4; - - /* - * We now need to deal with DST - * - * The problem is that the kernel module can't tell the difference - * between timezones being switched and entering daylight savings - * time. Whenever the time offset from UTC shifts, the kernel module - * shifts values in the bandwidth history to reflect the time - * as it would be if the current offset from UTC had always been - * in effect. In order to keep all data in the kernel module - * consistent we need to make sure values we send kernel module - * are adjusted for current offset from UTC, not the real one, - * where the offset may be inconsistent because of DST. - * - * Also note we ignore all but the first, second and last values in the - * history time list. These are the only values the kernel needs/uses. - * We have the whole list in the structure so that we don't have to make - * programs that deal with the library worry about the conversion when - * values are returned. However, when setting data, it's perfectly ok - * to just have the three necessary values and set everything else to zero - */ - time_t first_start = history->first_start; - time_t first_end = history->first_end; - time_t last_end = history->last_end; - - time_t now; - time(&now); - int current_minutes_west = get_minutes_west(now); - first_start = first_start + (get_minutes_west(first_start)-current_minutes_west); - first_end = first_end + (get_minutes_west(first_end)-current_minutes_west); - last_end = last_end + (get_minutes_west(last_end)-current_minutes_west); - - *( (uint64_t*)(output_buffer + *current_output_index) ) = (uint64_t)first_start; - *current_output_index = *current_output_index + 8; - - *( (uint64_t*)(output_buffer + *current_output_index) ) = (uint64_t)first_end; - *current_output_index = *current_output_index + 8; - - *( (uint64_t*)(output_buffer + *current_output_index) ) = (uint64_t)last_end; - *current_output_index = *current_output_index + 8; - - uint32_t node_num = 0; - for(node_num=0; node_num < history->num_nodes; node_num++) - { - *( (uint64_t*)(output_buffer + *current_output_index) ) = (history->history_bws)[ node_num ]; - *current_output_index = *current_output_index + 8; - } - } - else - { - if(*current_output_index + 12 > output_buffer_length) - { - return 1; - } - - ip_bw* ib = (ip_bw*)ip_block_data; - *( (uint32_t*)(output_buffer + *current_output_index) ) = ib->ip; - *current_output_index = *current_output_index + 4; - *( (uint64_t*)(output_buffer + *current_output_index) ) = ib->bw; - - /* - struct in_addr addr; - addr.s_addr = ib->ip; - printf("setting ip = %s, ip index = %ld\n", inet_ntoa(addr), (*current_output_index)-4); - printf("setting bw = %lld, bw_index = %ld\n", ib->bw, *current_output_index); - */ - *current_output_index = *current_output_index + 8; - } - return 0; -} - -static int set_bandwidth_data(char* id, unsigned char zero_unset, unsigned char set_history, unsigned long num_ips, time_t last_backup, void* data, unsigned long max_wait_milliseconds) -{ - unsigned char buf[BANDWIDTH_QUERY_LENGTH]; - memset(buf, 0, BANDWIDTH_QUERY_LENGTH); - int done = 0; - - int got_lock = lock(max_wait_milliseconds); - int sockfd = -1; - if(got_lock) - { - sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); - } - - uint32_t* total_ips = (uint32_t*)(buf+0); - uint32_t* next_ip_index = (uint32_t*)(buf+4); - uint32_t* num_ips_in_buffer = (uint32_t*)(buf+8); - unsigned char* history_included = (unsigned char*)(buf+12); - unsigned char* zero_unset_ips = (unsigned char*)(buf+13); - uint64_t* last_backup_time = (uint64_t*)(buf+14); - unsigned char* set_id = (unsigned char*)(buf+22); - - *total_ips = num_ips; - *next_ip_index = 0; - *num_ips_in_buffer = 0; - *history_included = set_history; - *zero_unset_ips = zero_unset; - *last_backup_time = (uint64_t)last_backup; - memcpy(set_id, id, BANDWIDTH_MAX_ID_LENGTH); - set_id[BANDWIDTH_MAX_ID_LENGTH-1] = '\0'; - - while(!done && sockfd >= 0 && got_lock) - { - uint32_t buf_index = (3*4) + (2*1) + 8 + BANDWIDTH_MAX_ID_LENGTH; - uint32_t ip_index = *next_ip_index; - unsigned char buffer_full = 0; - memset( (buf + buf_index), 0, (BANDWIDTH_QUERY_LENGTH-buf_index) ); - *num_ips_in_buffer = 0; - done = (ip_index >= *total_ips); - - while( (!buffer_full) && (!done) ) - { - void *next_data = set_history ? (void*)(((ip_bw_history*)data) + ip_index) : (void*)(((ip_bw*)data) + ip_index); - buffer_full = set_ip_block(next_data , set_history, buf, &buf_index, BANDWIDTH_QUERY_LENGTH); - ip_index = buffer_full ? ip_index : ip_index+1; - *num_ips_in_buffer = buffer_full ? *num_ips_in_buffer : *num_ips_in_buffer + 1; - done = (ip_index >= *total_ips); - } - setsockopt(sockfd, IPPROTO_IP, BANDWIDTH_SET, buf, BANDWIDTH_QUERY_LENGTH); - - *next_ip_index = ip_index; - } - if(sockfd >= 0) - { - close(sockfd); - } - if(got_lock) - { - unlock(); - } - return got_lock; -} - -static unsigned char* read_entire_file(FILE* in, unsigned long read_block_size, unsigned long *length) -{ - int max_read_size = read_block_size; - unsigned char* read_string = (unsigned char*)malloc(max_read_size+1); - unsigned long bytes_read = 0; - int end_found = 0; - while(end_found == 0) - { - int nextch = '?'; - while(nextch != EOF && bytes_read < max_read_size) - { - nextch = fgetc(in); - if(nextch != EOF) - { - read_string[bytes_read] = (unsigned char)nextch; - bytes_read++; - } - } - read_string[bytes_read] = '\0'; - end_found = (nextch == EOF) ? 1 : 0; - if(end_found == 0) - { - unsigned char *new_str; - max_read_size = max_read_size + read_block_size; - new_str = (unsigned char*)malloc(max_read_size+1); - memcpy(new_str, read_string, bytes_read); - free(read_string); - read_string = new_str; - } - } - *length = bytes_read; - return read_string; -} - -/* - * line is the line to be parsed -- it is not modified in any way - * max_pieces indicates number of pieces to return, if negative this is determined dynamically - * include_remainder_at_max indicates whether the last piece, when max pieces are reached, - * should be what it would normally be (0) or the entire remainder of the line (1) - * if max_pieces < 0 this parameter is ignored - * - * - * returns all non-separator pieces in a line - * result is dynamically allocated, MUST be freed after call-- even if - * line is empty (you still get a valid char** pointer to to a NULL char*) - */ -static char** split_on_separators(char* line, char* separators, int num_separators, int max_pieces, int include_remainder_at_max, unsigned long *pieces_read) -{ - char** split; - *pieces_read = 0; - - if(line != NULL) - { - int split_index; - int non_separator_found; - char* dup_line; - char* start; - - if(max_pieces < 0) - { - /* count number of separator characters in line -- this count + 1 is an upperbound on number of pieces */ - int separator_count = 0; - int line_index; - for(line_index = 0; line[line_index] != '\0'; line_index++) - { - int sep_index; - int found = 0; - for(sep_index =0; found == 0 && sep_index < num_separators; sep_index++) - { - found = separators[sep_index] == line[line_index] ? 1 : 0; - } - separator_count = separator_count+ found; - } - max_pieces = separator_count + 1; - } - split = (char**)malloc((1+max_pieces)*sizeof(char*)); - split_index = 0; - split[split_index] = NULL; - - - dup_line = strdup(line); - start = dup_line; - non_separator_found = 0; - while(non_separator_found == 0) - { - int matches = 0; - int sep_index; - for(sep_index =0; sep_index < num_separators; sep_index++) - { - matches = matches == 1 || separators[sep_index] == start[0] ? 1 : 0; - } - non_separator_found = matches==0 || start[0] == '\0' ? 1 : 0; - if(non_separator_found == 0) - { - start++; - } - } - - while(start[0] != '\0' && split_index < max_pieces) - { - /* find first separator index */ - int first_separator_index = 0; - int separator_found = 0; - while( separator_found == 0 ) - { - int sep_index; - for(sep_index =0; separator_found == 0 && sep_index < num_separators; sep_index++) - { - separator_found = separators[sep_index] == start[first_separator_index] || start[first_separator_index] == '\0' ? 1 : 0; - } - if(separator_found == 0) - { - first_separator_index++; - } - } - - /* copy next piece to split array */ - if(first_separator_index > 0) - { - char* next_piece = NULL; - if(split_index +1 < max_pieces || include_remainder_at_max <= 0) - { - next_piece = (char*)malloc((first_separator_index+1)*sizeof(char)); - memcpy(next_piece, start, first_separator_index); - next_piece[first_separator_index] = '\0'; - } - else - { - next_piece = strdup(start); - } - split[split_index] = next_piece; - split[split_index+1] = NULL; - split_index++; - *pieces_read = split_index; - } - - /* find next non-separator index, indicating start of next piece */ - start = start+ first_separator_index; - non_separator_found = 0; - while(non_separator_found == 0) - { - int matches = 0; - int sep_index; - for(sep_index =0; sep_index < num_separators; sep_index++) - { - matches = matches == 1 || separators[sep_index] == start[0] ? 1 : 0; - } - non_separator_found = matches==0 || start[0] == '\0' ? 1 : 0; - if(non_separator_found == 0) - { - start++; - } - } - } - free(dup_line); - - } - else - { - split = (char**)malloc((1)*sizeof(char*)); - split[0] = NULL; - } - return split; -} - -time_t* get_interval_starts_for_history(ip_bw_history history) -{ - time_t *start_times = NULL; - if(history.num_nodes > 0) - { - start_times = (time_t*)malloc(history.num_nodes*sizeof(time_t)); - int node_index =0; - time_t next_start = history.first_start; - time_t next_end = get_next_node_start_time(next_start, history.reset_interval, history.reset_time, history.is_constant_interval); - for(node_index=0; node_index < history.num_nodes; node_index++) - { - start_times[node_index] = next_start; - next_start = next_end; - next_end = get_next_node_start_time(next_start, history.reset_interval, history.reset_time, history.is_constant_interval); - } - } - return start_times; -} - -void free_ip_bw_histories(ip_bw_history* histories, int num_histories) -{ - if(histories == NULL) - { - return; - } - int history_index = 0; - for(history_index=0; history_index < num_histories; history_index++) - { - if((histories[history_index]).history_bws != NULL) - { - free( (histories[history_index]).history_bws ); - } - } - free(histories); -} - -int get_all_bandwidth_history_for_rule_id(char* id, unsigned long* num_ips, ip_bw_history** data, unsigned long max_wait_milliseconds) -{ - return get_bandwidth_data(id, 1, "ALL", num_ips, (void*)data, max_wait_milliseconds); -} - -int get_ip_bandwidth_history_for_rule_id(char* id, char* ip, ip_bw_history** data, unsigned long max_wait_milliseconds) -{ - unsigned long num_ips; - return get_bandwidth_data(id, 1, ip, &num_ips, (void*)data, max_wait_milliseconds); -} - -int get_all_bandwidth_usage_for_rule_id(char* id, unsigned long* num_ips, ip_bw** data, unsigned long max_wait_milliseconds) -{ - return get_bandwidth_data(id, 0, "ALL", num_ips, (void*)data, max_wait_milliseconds); -} - -int get_ip_bandwidth_usage_for_rule_id(char* id, char* ip, ip_bw** data, unsigned long max_wait_milliseconds) -{ - unsigned long num_ips; - return get_bandwidth_data(id, 0, ip, &num_ips, (void*)data, max_wait_milliseconds); -} - -int set_bandwidth_history_for_rule_id(char* id, unsigned char zero_unset, unsigned long num_ips, ip_bw_history* data, unsigned long max_wait_milliseconds) -{ - return set_bandwidth_data(id, zero_unset, 1, num_ips, 0, data, max_wait_milliseconds); -} - -int set_bandwidth_usage_for_rule_id(char* id, unsigned char zero_unset, unsigned long num_ips, time_t last_backup, ip_bw* data, unsigned long max_wait_milliseconds) -{ - return set_bandwidth_data(id, zero_unset, 0, num_ips, last_backup, data, max_wait_milliseconds); -} - -/* save single id in ascii */ -int save_usage_to_file(ip_bw* data, unsigned long num_ips, char* out_file_path) -{ - - int success = 0; - FILE* out_file = fopen(out_file_path, "w"); - if(out_file != NULL) - { - //dump backup time - time_t now; - time(&now); - fprintf(out_file, "%-15ld\n", now); - - //dump ips - int out_index=0; - for(out_index=0; out_index < num_ips; out_index++) - { - struct in_addr ipaddr; - ip_bw next = data[out_index]; - ipaddr.s_addr = next.ip; - fprintf(out_file, "%-15s\t%lld\n", inet_ntoa(ipaddr), (long long int)next.bw); - } - fclose(out_file); - success = 1; - } - return success; -} - -/* save history (must be for one id only) in binary so it takes up less space */ -int save_history_to_file(ip_bw_history* data, unsigned long num_ips, char* out_file_path) -{ - int success = 0; - FILE* out_file = fopen(out_file_path, "wb"); - if(out_file != NULL) - { - //dump number of ips & history interval parameter - //note that we assume interval is same for all histories - //(which will be the case if they all come from the same rule id) - fwrite((uint32_t*)(&num_ips), 4, 1, out_file); - if(num_ips > 0) - { - ip_bw_history first = data[0]; - uint64_t interval = (uint64_t)(first.reset_interval); - uint64_t time = (uint64_t)(first.reset_time); - unsigned char is_constant = first.is_constant_interval; - - fwrite( &interval, 8, 1, out_file); - fwrite( &time, 8, 1, out_file); - fwrite( &is_constant, 1, 1, out_file); - } - - unsigned char bw_fits_in_32bits = 1; - uint32_t out_index=0; - for(out_index=0; out_index < num_ips && bw_fits_in_32bits; out_index++) - { - uint32_t node_index = 0; - ip_bw_history next = data[out_index]; - for(node_index=0; node_index < next.num_nodes && bw_fits_in_32bits; node_index++) - { - uint64_t bw = (next.history_bws)[node_index]; - bw_fits_in_32bits = bw_fits_in_32bits && (bw < INT32_MAX); - } - } - - //dump data for each ip - for(out_index=0; out_index < num_ips; out_index++) - { - ip_bw_history next = data[out_index]; - - fwrite( &(next.ip), 4, 1, out_file); - fwrite( &(next.num_nodes), 4, 1, out_file); - if(next.num_nodes == 0) - { - uint64_t dummy = 0; - unsigned char bw_bits = 32; - fwrite( &dummy, 8, 1, out_file); - fwrite( &dummy, 8, 1, out_file); - fwrite( &dummy, 8, 1, out_file); - fwrite( &bw_bits, 1, 1, out_file); - } - else - { - uint32_t node_index = 0; - uint64_t first_start = (uint64_t)next.first_start; - uint64_t first_end = (uint64_t)next.first_end; - uint64_t last_end = (uint64_t)next.last_end; - unsigned char bw_bits = 32; - for(node_index=0; node_index < next.num_nodes && bw_bits == 32; node_index++) - { - uint64_t bw = (next.history_bws)[node_index]; - bw_bits = bw_bits == 32 && (bw < INT32_MAX) ? 32 : 64; - } - - fwrite( &first_start, 8, 1, out_file); - fwrite( &first_end, 8, 1, out_file); - fwrite( &last_end, 8, 1, out_file); - fwrite( &bw_bits, 1, 1, out_file); - for(node_index=0; node_index < next.num_nodes; node_index++) - { - if(bw_bits == 32) - { - uint32_t bw = (uint32_t)(next.history_bws)[node_index]; - fwrite( &bw, 4, 1, out_file); - - } - else - { - uint64_t bw = (next.history_bws)[node_index]; - fwrite( &bw, 8, 1, out_file); - } - } - } - } - fclose(out_file); - success = 1; - } - return success; -} - - -ip_bw* load_usage_from_file(char* in_file_path, unsigned long* num_ips, time_t* last_backup) -{ - ip_bw* data = NULL; - *num_ips = 0; - *last_backup = 0; - FILE* in_file = fopen(in_file_path, "r"); - if(in_file != NULL) - { - unsigned long num_data_parts = 0; - char* file_data = read_entire_file(in_file, 4086, &num_data_parts); - fclose(in_file); - char whitespace[] = {'\n', '\r', '\t', ' '}; - char** data_parts = split_on_separators(file_data, whitespace, 4, -1, 0, &num_data_parts); - free(file_data); - - *num_ips = (num_data_parts/2) + 1; - data = (ip_bw*)malloc( (*num_ips) * sizeof(ip_bw) ); - *num_ips = 0; - unsigned long data_index = 0; - unsigned long data_part_index = 0; - while(data_part_index < num_data_parts) - { - ip_bw next; - struct in_addr ipaddr; - int valid = inet_aton(data_parts[data_part_index], &ipaddr); - if(!valid) - { - sscanf(data_parts[data_part_index], "%ld", last_backup); - //printf("last_backup = %ld\n", *last_backup); - } - data_part_index++; - - if(valid && data_index < num_data_parts) - { - next.ip = ipaddr.s_addr; - valid = sscanf(data_parts[data_part_index], "%lld", (long long int*)&(next.bw) ); - data_part_index++; - } - else - { - valid = 0; - } - - if(valid) - { - //printf("next.bw = %lld\n", next.bw); - //printf("next.ip = %d\n", next.ip); - data[data_index] = next; - data_index++; - *num_ips = *num_ips + 1; - } - } - - /* cleanup by freeing data_parts */ - for(data_part_index = 0; data_part_index < num_data_parts; data_part_index++) - { - free(data_parts[data_part_index]); - } - - free(data_parts); - } - return data; -} - -ip_bw_history* load_history_from_file(char* in_file_path, unsigned long* num_ips) -{ - ip_bw_history* data = NULL; - *num_ips = 0; - FILE* in_file = fopen(in_file_path, "rb"); - if(in_file != NULL) - { - uint64_t reset_interval; - uint64_t reset_time; - unsigned char is_constant_interval; - - uint32_t nips = 0; - fread(&nips, 4, 1, in_file); - *num_ips = (unsigned long)nips; - - if(*num_ips > 0) - { - fread(&reset_interval, 8, 1, in_file); - fread(&reset_time, 8, 1, in_file); - fread(&is_constant_interval, 1, 1, in_file); - data = (ip_bw_history*)malloc( (*num_ips) * sizeof(ip_bw_history)); - } - - uint32_t ip_index; - for(ip_index=0; ip_index < *num_ips; ip_index++) - { - - uint32_t ip; - uint32_t num_nodes; - uint64_t first_start; - uint64_t first_end; - uint64_t last_end; - unsigned char bw_bits; - - fread(&ip, 4, 1, in_file); - fread(&num_nodes, 4, 1, in_file); - fread(&first_start, 8, 1, in_file); - fread(&first_end, 8, 1, in_file); - fread(&last_end, 8, 1, in_file); - fread(&bw_bits, 1, 1, in_file); - - ip_bw_history next; - next.reset_interval = (time_t)reset_interval; - next.reset_time = (time_t)reset_time; - next.is_constant_interval = is_constant_interval; - next.ip = ip; - next.num_nodes = num_nodes; - next.first_start = (time_t)first_start; - next.first_end = (time_t)first_end; - next.last_end = (time_t)last_end; - next.history_bws = NULL; - if(next.num_nodes > 0) - { - next.history_bws = malloc( next.num_nodes * sizeof(uint64_t) ); - uint32_t node_index = 0; - for(node_index=0; node_index < next.num_nodes; node_index++) - { - if(bw_bits == 32) - { - uint32_t nextbw = 0; - fread(&nextbw, 4, 1, in_file); - (next.history_bws)[node_index] = (uint64_t)nextbw; - - } - else - { - uint64_t nextbw = 0; - fread(&nextbw, 8, 1, in_file); - (next.history_bws)[node_index] = nextbw; - } - } - } - data[ip_index] = next; - } - fclose(in_file); - } - return data; -} - - -void print_usage(FILE* out, ip_bw* usage, unsigned long num_ips) -{ - unsigned long usage_index; - for(usage_index =0; usage_index < num_ips; usage_index++) - { - ip_bw next = usage[usage_index]; - if(next.ip != 0) - { - struct in_addr ipaddr; - ipaddr.s_addr = next.ip; - fprintf(out, "%-15s\t%lld\n", inet_ntoa(ipaddr), (long long int)next.bw); - } - else - { - fprintf(out, "%-15s\t%lld\n", "COMBINED", (long long int)next.bw); - } - } - fprintf(out, "\n"); -} - -void print_histories(FILE* out, char* id, ip_bw_history* histories, unsigned long num_histories, char output_type) -{ - unsigned long history_index = 0; - for(history_index=0; history_index < num_histories; history_index++) - { - ip_bw_history history = histories[history_index]; - - int history_initialized = 1; - if( history.first_start == 0 && history.first_end == 0 && history.last_end == 0) - { - history_initialized = 0; - } - - if(history_initialized) - { - char *ip_str = NULL; - time_t *times = NULL; - - if(history.ip != 0) - { - struct in_addr ipaddr; - ipaddr.s_addr = history.ip; - ip_str = strdup(inet_ntoa(ipaddr)); - } - else - { - ip_str = strdup("COMBINED"); - } - - - if(output_type == 'm' || output_type == 'h') - { - fprintf(out, "%s %-15s\n", id, ip_str); - } - - if(output_type == 'm') - { - printf("%ld\n", history.first_start); - printf("%ld\n", history.first_end); - printf("%ld\n", history.last_end); - } - else - { - times = get_interval_starts_for_history(history); - } - - int hindex = 0; - for(hindex=0; hindex < history.num_nodes; hindex++) - { - uint64_t bw = (history.history_bws)[hindex]; - if(output_type == 'm') - { - if(hindex != 0) { printf(","); }; - printf("%lld", (unsigned long long int)bw); - } - else if(times != NULL) - { - time_t start = times[hindex]; - time_t end = hindex+1 < history.num_nodes ? times[hindex+1] : 0 ; - - char* start_str = strdup(asctime(localtime(&start))); - char* end_str = end == 0 ? strdup("(Now)") : strdup(asctime(localtime(&end))); - char* nl = strchr(start_str, '\n'); - if(nl != NULL) - { - *nl = '\0'; - } - nl = strchr(end_str, '\n'); - if(nl != NULL) - { - *nl = '\0'; - } - - if(output_type == 'h') - { - fprintf(out, "%lld\t%s\t%s\n", (unsigned long long int)bw, start_str, end_str); - } - else - { - fprintf(out, "%s,%s,%ld,%ld,%lld\n", id, ip_str, start, end, (unsigned long long int)bw ); - } - free(start_str); - free(end_str); - } - } - fprintf(out, "\n"); - if(times != NULL) { free(times); }; - if(ip_str != NULL) { free(ip_str); }; - } - } -} - -void unlock_bandwidth_semaphore(void) -{ - unlock(); -} - -void signal_handler(int sig) -{ - if(sig == SIGTERM || sig == SIGINT ) - { - unlock_bandwidth_semaphore(); - exit(0); - } -} - -void unlock_bandwidth_semaphore_on_exit(void) -{ - signal(SIGTERM,signal_handler); - signal(SIGINT, signal_handler); -} - -int get_minutes_west(time_t now) -{ - struct tm* utc_info; - struct tm* tz_info; - int utc_day; - int utc_hour; - int utc_minute; - int tz_day; - int tz_hour; - int tz_minute; - int minuteswest; - - utc_info = gmtime(&now); - utc_day = utc_info->tm_mday; - utc_hour = utc_info->tm_hour; - utc_minute = utc_info->tm_min; - tz_info = localtime(&now); - tz_day = tz_info->tm_mday; - tz_hour = tz_info->tm_hour; - tz_minute = tz_info->tm_min; - - utc_day = utc_day < tz_day - 1 ? tz_day + 1 : utc_day; - tz_day = tz_day < utc_day - 1 ? utc_day + 1 : tz_day; - - minuteswest = (24*60*utc_day + 60*utc_hour + utc_minute) - (24*60*tz_day + 60*tz_hour + tz_minute) ; - - return minuteswest; -} - - -void set_kernel_timezone(void) -{ - time_t now; - struct timeval tv; - struct timezone old_tz; - struct timezone new_tz; - - time(&now); - new_tz.tz_minuteswest = get_minutes_west(now); - new_tz.tz_dsttime = 0; - - /* Get tv to pass to settimeofday(2) to be sure we avoid hour-sized warp */ - /* (see gettimeofday(2) man page, or /usr/src/linux/kernel/time.c) */ - gettimeofday(&tv, &old_tz); - - /* set timezone */ - settimeofday(&tv, &new_tz); -} diff --git a/package/jsda/libiptbwctl/src/ipt_bwctl.h b/package/jsda/libiptbwctl/src/ipt_bwctl.h deleted file mode 100644 index 1ceaf703c0..0000000000 --- a/package/jsda/libiptbwctl/src/ipt_bwctl.h +++ /dev/null @@ -1,147 +0,0 @@ -/* libiptbwctl -- A userspace library for querying the bandwidth iptables module - * Originally designed for use with Gargoyle router firmware (gargoyle-router.com) - * - * - * Copyright © 2009 by Eric Bishop - * - * This file is free software: you may copy, redistribute 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 file 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 -#include -#include -#include -#include -#include -#include -#include -#define BANDWIDTH_QUERY_LENGTH 16384 - -/* socket id parameters (for userspace i/o) */ -#define BANDWIDTH_SET 2048 -#define BANDWIDTH_GET 2049 - -/* max id length */ -#define BANDWIDTH_MAX_ID_LENGTH 50 - -/* pick something rather random... let's make it end in 666 to - * freak out the crazy fundies out there ;-) */ -#define BANDWIDTH_SEMAPHORE_KEY 12699666 - -/* possible reset intervals */ -#define BANDWIDTH_MINUTE 80 -#define BANDWIDTH_HOUR 81 -#define BANDWIDTH_DAY 82 -#define BANDWIDTH_WEEK 83 -#define BANDWIDTH_MONTH 84 -#define BANDWIDTH_NEVER 85 - -#pragma pack(push, 1) -typedef struct ip_bw_struct -{ - uint32_t ip; - uint64_t bw; -} ip_bw; - -/* -* format of response: -* byte 1 : error code (0 for ok) -* bytes 2-5 : total_num_ips found in query (further gets may be necessary to retrieve them) -* bytes 6-9 : start_index, index (in a list of total_num_ips) of first ip in response -* bytes 10-13 : num_ips_in_response, number of ips in this response -* bytes 14-21 : reset_interval (helps deal with DST shifts in userspace) -* bytes 22-29 : reset_time (helps deal with DST shifts in userspace) -* byte 30 : reset_is_constant_interval (helps deal with DST shifts in userspace) -* remaining bytes contain blocks of ip data -* format is dependent on whether history was queried -*/ -typedef struct ip_bw_kernel_data_item_struct -{ - uint32_t ip; - uint32_t num_nodes; - uint64_t first_start; - uint64_t first_end; - uint64_t last_end; - uint64_t ipbw_data[0]; -}ip_bw_kernel_data_item; - -typedef struct -{ - uint8_t error; - uint32_t ip_total; - uint32_t index_start; - uint32_t ip_num; - uint64_t reset_interval; - uint64_t reset_time; - uint8_t reset_is_constant_interval; - /*payload for history ip bw data*/ - ip_bw_kernel_data_item data_item[0]; -} ip_bw_kernel_data; - -typedef struct history_struct -{ - uint32_t ip; - uint32_t num_nodes; - - time_t reset_interval; - time_t reset_time; - unsigned char is_constant_interval; - - time_t first_start; - time_t first_end; - time_t last_end; - - uint64_t* history_bws; -} ip_bw_history; -#pragma pack(pop) - -time_t* get_interval_starts_for_history(ip_bw_history history); - -extern void free_ip_bw_histories(ip_bw_history* histories, int num_histories); - -extern int get_all_bandwidth_history_for_rule_id(char* id, unsigned long* num_ips, ip_bw_history** data, unsigned long max_wait_milliseconds); -extern int get_ip_bandwidth_history_for_rule_id(char* id, char* ip, ip_bw_history** data, unsigned long max_wait_milliseconds); -extern int get_all_bandwidth_usage_for_rule_id(char* id, unsigned long* num_ips, ip_bw** data, unsigned long max_wait_milliseconds); -extern int get_ip_bandwidth_usage_for_rule_id(char* id, char* ip, ip_bw** data, unsigned long max_wait_milliseconds); - -extern int set_bandwidth_history_for_rule_id(char* id, unsigned char zero_unset, unsigned long num_ips, ip_bw_history* data, unsigned long max_wait_milliseconds); -extern int set_bandwidth_usage_for_rule_id(char* id, unsigned char zero_unset, unsigned long num_ips, time_t last_backup, ip_bw* data, unsigned long max_wait_milliseconds); - -extern int save_usage_to_file(ip_bw* data, unsigned long num_ips, char* out_file_path); -extern int save_history_to_file(ip_bw_history* data, unsigned long num_ips, char* out_file_path); - -extern ip_bw* load_usage_from_file(char* in_file_path, unsigned long* num_ips, time_t* last_backup); -extern ip_bw_history* load_history_from_file(char* in_file_path, unsigned long* num_ips); - -extern void print_usage(FILE* out, ip_bw* usage, unsigned long num_ips); -extern void print_histories(FILE* out, char* id, ip_bw_history* histories, unsigned long num_histories, char output_type); - -extern void unlock_bandwidth_semaphore(void); -extern void unlock_bandwidth_semaphore_on_exit(void); - -/* sets kernel timezone minuteswest to match user timezone */ -extern int get_minutes_west(time_t now); -extern void set_kernel_timezone(void); - -/* safe malloc & strdup functions used to handle malloc errors cleanly */ -extern void* ipt_bwctl_safe_malloc(size_t size); -extern char* ipt_bwctl_safe_strdup(const char* str); diff --git a/package/jsda/libiptbwctl/src/ipt_bwctl_safe_malloc.c b/package/jsda/libiptbwctl/src/ipt_bwctl_safe_malloc.c deleted file mode 100644 index 463379acfd..0000000000 --- a/package/jsda/libiptbwctl/src/ipt_bwctl_safe_malloc.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "ipt_bwctl.h" - -void *ipt_bwctl_safe_malloc(size_t size) -{ - void* val = malloc(size); - if(val == NULL) - { - fprintf(stderr, "ERROR: MALLOC FAILURE!\n"); - exit(1); - } - return val; -} - -char* ipt_bwctl_safe_strdup(const char* str) -{ - char* new_str = strdup(str); - if(new_str == NULL) - { - fprintf(stderr, "ERROR: MALLOC FAILURE!\n"); - exit(1); - } - return new_str; -} diff --git a/package/jsda/libiptbwctl/src/utils/Makefile b/package/jsda/libiptbwctl/src/utils/Makefile deleted file mode 100644 index c2bc9f3d2d..0000000000 --- a/package/jsda/libiptbwctl/src/utils/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -all: bw_set bw_get bw_print_history_file set_kernel_timezone -bw_set: bw_set.c - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ -liptbwctl -bw_get: bw_get.c - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ -liptbwctl -bw_print_history_file: bw_print_history_file.c - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ -liptbwctl -set_kernel_timezone: set_kernel_timezone.c - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ -liptbwctl - -clean: - rm -rf bw_set bw_get print_history_file set_kernel_timezone *.o *~ .*sw* diff --git a/package/jsda/libiptbwctl/src/utils/bw_get.c b/package/jsda/libiptbwctl/src/utils/bw_get.c deleted file mode 100644 index 5bf3f90b02..0000000000 --- a/package/jsda/libiptbwctl/src/utils/bw_get.c +++ /dev/null @@ -1,175 +0,0 @@ -/* libiptbwctl -- A userspace library for querying the bandwidth iptables module - * Originally designed for use with Gargoyle router firmware (gargoyle-router.com) - * - * - * Copyright © 2009 by Eric Bishop - * - * This file is free software: you may copy, redistribute 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 file 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 -#define malloc ipt_bwctl_safe_malloc -#define strdup ipt_bwctl_safe_strdup - -int main(int argc, char **argv) -{ - char *id = NULL; - char* out_file_path = NULL;; - char *address = NULL; - - unsigned long num_ips; - void *ip_buf; - unsigned long out_index; - int query_succeeded; - int get_history = 0; - char output_type = 'h'; - - int c; - struct in_addr read_addr; - while((c = getopt(argc, argv, "i:I:a:A:f:F:tThHmMuU")) != -1) - { - switch(c) - { - case 'i': - case 'I': - if(strlen(optarg) < BANDWIDTH_MAX_ID_LENGTH && strlen(optarg) > 0) - { - id = strdup(optarg); - } - else - { - fprintf(stderr, "ERROR: ID length is improper length.\n"); - exit(0); - } - break; - case 'a': - case 'A': - if(strcmp(optarg, "combined") == 0 || strcmp(optarg, "COMBINED") == 0) - { - address = strdup("0.0.0.0"); - } - else if( inet_aton(optarg, &read_addr) ) - { - address = strdup(optarg); - } - else - { - fprintf(stderr, "ERROR: invalid IP address specified\n"); - exit(0); - } - - break; - case 'f': - case 'F': - out_file_path = strdup(optarg); - break; - case 'h': - case 'H': - get_history = 1; - break; - case 'm': - case 'M': - output_type = 'm'; - break; - case 't': - case 'T': - output_type = 't'; - break; - case 'u': - case 'U': - default: - fprintf(stderr, "USAGE:\n\t%s -i [ID] -a [IP ADDRESS] -f [OUT_FILE_NAME]\n", argv[0]); - exit(0); - } - } - - - if(id == NULL) - { - fprintf(stderr, "ERROR: you must specify an id to query\n\n"); - exit(0); - } - - set_kernel_timezone(); - unlock_bandwidth_semaphore_on_exit(); - - if(get_history == 0) - { - if(address == NULL) - { - query_succeeded = get_all_bandwidth_usage_for_rule_id(id, &num_ips, (ip_bw**)&ip_buf, 1000); - } - else - { - num_ips = 1; - query_succeeded = get_ip_bandwidth_usage_for_rule_id(id, address, (ip_bw**)&ip_buf, 1000); - } - } - else - { - if(address == NULL) - { - query_succeeded = get_all_bandwidth_history_for_rule_id(id, &num_ips, (ip_bw_history**)&ip_buf, 1000); - } - else - { - num_ips = 1; - query_succeeded = get_ip_bandwidth_history_for_rule_id(id, address, (ip_bw_history**)&ip_buf, 1000); - } - } - if(!query_succeeded) - { - fprintf(stderr, "ERROR: Bandwidth query failed, make sure rule with specified id exists, and that you are performing only one query at a time.\n\n"); - exit(0); - } - - - if(out_file_path != NULL) - { - if(get_history == 0) - { - save_usage_to_file( (ip_bw*)ip_buf, num_ips, out_file_path); - } - else - { - save_history_to_file( (ip_bw_history*)ip_buf, num_ips, out_file_path); - } - } - else - { - if(get_history == 0) - { - print_usage(stdout, (ip_bw*)ip_buf, num_ips); - } - else - { - print_histories(stdout, id, (ip_bw_history*)ip_buf, num_ips, output_type ); - } - } - if(num_ips == 0) - { - if(output_type != 't' && output_type != 'm') - { - fprintf(stderr, "No data available for id \"%s\"\n", id); - } - } - printf("\n"); - - if(out_file_path != NULL) - { - free(out_file_path); - } - - return 0; -} diff --git a/package/jsda/libiptbwctl/src/utils/bw_print_history_file.c b/package/jsda/libiptbwctl/src/utils/bw_print_history_file.c deleted file mode 100644 index 00f6e26436..0000000000 --- a/package/jsda/libiptbwctl/src/utils/bw_print_history_file.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libiptbwctl -- A userspace library for querying the bandwidth iptables module - * Originally designed for use with Gargoyle router firmware (gargoyle-router.com) - * - * - * Copyright © 2009 by Eric Bishop - * - * This file is free software: you may copy, redistribute 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 file 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 -#define malloc ipt_bwctl_safe_malloc -#define strdup ipt_bwctl_safe_strdup - -int main(int argc, char **argv) -{ - if(argc > 1) - { - unsigned long num_ips; - ip_bw_history* histories = load_history_from_file(argv[1], &num_ips); - if(histories != NULL) - { - print_histories(stdout, argv[1], histories, num_ips, 'h'); - } - } - return 0; -} diff --git a/package/jsda/libiptbwctl/src/utils/bw_set.c b/package/jsda/libiptbwctl/src/utils/bw_set.c deleted file mode 100644 index 28cbee0e20..0000000000 --- a/package/jsda/libiptbwctl/src/utils/bw_set.c +++ /dev/null @@ -1,184 +0,0 @@ -/* libiptbwctl -- A userspace library for querying the bandwidth iptables module - * Originally designed for use with Gargoyle router firmware (gargoyle-router.com) - * - * - * Copyright © 2009 by Eric Bishop - * - * This file is free software: you may copy, redistribute 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 file 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 -#define malloc ipt_bwctl_safe_malloc -#define strdup ipt_bwctl_safe_strdup - -static char* read_entire_file(FILE* in, int read_block_size); -static char** split_on_separators(char* line, char* separators, int num_separators, int max_pieces, int include_remainder_at_max, unsigned long *pieces_read); - -int main(int argc, char **argv) -{ - char *id = NULL; - char* in_file_path = NULL; - FILE* in_file = NULL; - time_t last_backup = 0; - int last_backup_from_cl = 0; - int is_history_file = 0; - - int c; - while((c = getopt(argc, argv, "i:I:b:B:f:F:UuHh")) != -1) - { - switch(c) - { - case 'i': - case 'I': - if(strlen(optarg) < BANDWIDTH_MAX_ID_LENGTH) - { - id = strdup(optarg); - } - else - { - fprintf(stderr, "ERROR: ID length is improper length.\n"); - exit(0); - } - - break; - case 'b': - case 'B': - if(sscanf(optarg, "%ld", &last_backup) == 0) - { - fprintf(stderr, "ERROR: invalid backup time specified. Should be unix epoch seconds -- number of seconds since 1970 (UTC)\n"); - exit(0); - } - last_backup_from_cl = 1; - break; - case 'f': - case 'F': - in_file_path = strdup(optarg); - in_file = fopen(optarg, "rb"); - if(in_file == NULL) - { - fprintf(stderr, "ERROR: cannot open specified file for reading\n"); - exit(0); - } - fclose(in_file); - break; - case 'h': - case 'H': - is_history_file = 1; - break; - case 'u': - case 'U': - default: - fprintf(stderr, "USAGE:\n\t%s -i [ID] -b [LAST_BACKUP_TIME] -f [IN_FILE_NAME] [ IP BANDWIDTH PAIRS, IF -f NOT SPECIFIED ]\n", argv[0]); - exit(0); - - } - } - - if(id == NULL) - { - fprintf(stderr, "ERROR: you must specify an id for which to set data\n\n"); - exit(0); - } - if(in_file_path == NULL && is_history_file) - { - fprintf(stderr, "ERROR: you need to specify file to load history from\n\t\t(history format is too complex to load from command line)\n"); - } - - - set_kernel_timezone(); - unlock_bandwidth_semaphore_on_exit(); - int query_succeeded = 0; - if(in_file_path != NULL) - { - if(is_history_file) - { - unsigned long num_ips; - ip_bw_history* history_data = load_history_from_file(in_file_path, &num_ips); - if(history_data != NULL) - { - query_succeeded = set_bandwidth_history_for_rule_id(id, 1, num_ips, history_data, 1000); - } - } - else - { - unsigned long num_ips; - time_t last_backup; - ip_bw* usage_data = load_usage_from_file(in_file_path, &num_ips, &last_backup); - if(usage_data != NULL) - { - query_succeeded = set_bandwidth_usage_for_rule_id(id, 1, num_ips, last_backup, usage_data, 1000); - } - } - } - else - { - char** data_parts; - unsigned long num_data_parts; - data_parts = argv+optind; - num_data_parts = argc - optind; - - - unsigned long num_ips = num_data_parts/2; - ip_bw* buffer = (ip_bw*)malloc(num_ips*sizeof(ip_bw)); - unsigned long data_index = 0; - unsigned long buffer_index = 0; - while(data_index < num_data_parts) - { - ip_bw next; - struct in_addr ipaddr; - int valid = inet_aton(data_parts[data_index], &ipaddr); - if((!valid) && (!last_backup_from_cl)) - { - sscanf(data_parts[data_index], "%ld", &last_backup); - } - data_index++; - - if(valid && data_index < num_data_parts) - { - next.ip = ipaddr.s_addr; - valid = sscanf(data_parts[data_index], "%lld", (long long int*)&(next.bw) ); - data_index++; - } - else - { - valid = 0; - } - - if(valid) - { - /* printf("ip=%d, bw=%lld\n", next.ip, (long long int)next.bw); */ - buffer[buffer_index] = next; - buffer_index++; - } - } - num_ips = buffer_index; /* number that were successfully read */ - query_succeeded = set_bandwidth_usage_for_rule_id(id, 1, num_ips, last_backup, buffer, 1000); - } - - if(!query_succeeded) - { - fprintf(stderr, "ERROR: Could not set data. Please try again.\n\n"); - } - else - { - fprintf(stderr, "Data set successfully\n\n"); - } - - if(in_file_path != NULL) - { - free(in_file_path); - } - - return 0; -} diff --git a/package/jsda/libiptbwctl/src/utils/set_kernel_timezone.c b/package/jsda/libiptbwctl/src/utils/set_kernel_timezone.c deleted file mode 100644 index 5fd958b3df..0000000000 --- a/package/jsda/libiptbwctl/src/utils/set_kernel_timezone.c +++ /dev/null @@ -1,27 +0,0 @@ -/* libiptbwctl -- A userspace library for querying the bandwidth iptables module - * Originally designed for use with Gargoyle router firmware (gargoyle-router.com) - * - * - * Copyright © 2009 by Eric Bishop - * - * This file is free software: you may copy, redistribute 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 file 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 - -int main(void) -{ - set_kernel_timezone(); - return 0; -} diff --git a/package/jsda/luci-app-qos-gargoyle/LICENSE b/package/jsda/luci-app-qos-gargoyle/LICENSE deleted file mode 100755 index 8dada3edaf..0000000000 --- a/package/jsda/luci-app-qos-gargoyle/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - 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/package/jsda/luci-app-qos-gargoyle/Makefile b/package/jsda/luci-app-qos-gargoyle/Makefile deleted file mode 100755 index 78900c782e..0000000000 --- a/package/jsda/luci-app-qos-gargoyle/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright (C) 2017 Xingwang Liao -# -# This is free software, licensed under the Apache License, Version 2.0 . -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=luci-app-qos-gargoyle -PKG_VERSION:=1.3.8 -PKG_RELEASE:=1 - -PKG_LICENSE:=Apache-2.0 -PKG_MAINTAINER:=Xingwang Liao - -LUCI_TITLE:=LuCI Support for Gargoyle QoS -LUCI_DEPENDS:=+qos-gargoyle -LUCI_PKGARCH:=all - -include $(TOPDIR)/feeds/luci/luci.mk - -define Package/$(PKG_NAME)/config -# shown in make menuconfig -help - $(LUCI_TITLE) - . - Version: $(PKG_VERSION)-$(PKG_RELEASE) - $(PKG_MAINTAINER) -endef - -# call BuildPackage - OpenWrt buildroot signature diff --git a/package/jsda/luci-app-qos-gargoyle/README.md b/package/jsda/luci-app-qos-gargoyle/README.md deleted file mode 100755 index ef52b75360..0000000000 --- a/package/jsda/luci-app-qos-gargoyle/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# luci-app-qos-gargoyle - -This is my own fork of QoS Gargoyle - -QoS Gargoyle: https://github.com/kuoruan/qos-gargoyle diff --git a/package/jsda/luci-app-qos-gargoyle/luasrc/controller/qos_gargoyle.lua b/package/jsda/luci-app-qos-gargoyle/luasrc/controller/qos_gargoyle.lua deleted file mode 100755 index 5b9ca56c5f..0000000000 --- a/package/jsda/luci-app-qos-gargoyle/luasrc/controller/qos_gargoyle.lua +++ /dev/null @@ -1,100 +0,0 @@ --- Copyright 2017 Xingwang Liao --- Licensed to the public under the Apache License 2.0. - -module("luci.controller.qos_gargoyle", package.seeall) - -local util = require "luci.util" -local http = require "luci.http" - -function index() - if not nixio.fs.access("/etc/config/qos_gargoyle") then - return - end - - entry({"admin", "network", "qos_gargoyle"}, - firstchild(), _("Gargoyle QoS"), 60) - - entry({"admin", "network", "qos_gargoyle", "global"}, - cbi("qos_gargoyle/global"), _("Global Settings"), 10) - - entry({"admin", "network", "qos_gargoyle", "upload"}, - cbi("qos_gargoyle/upload"), _("Upload Settings"), 20) - - entry({"admin", "network", "qos_gargoyle", "upload", "class"}, - cbi("qos_gargoyle/upload_class")).leaf = true - - entry({"admin", "network", "qos_gargoyle", "upload", "rule"}, - cbi("qos_gargoyle/upload_rule")).leaf = true - - entry({"admin", "network", "qos_gargoyle", "download"}, - cbi("qos_gargoyle/download"), _("Download Settings"), 30) - - entry({"admin", "network", "qos_gargoyle", "download", "class"}, - cbi("qos_gargoyle/download_class")).leaf = true - - entry({"admin", "network", "qos_gargoyle", "download", "rule"}, - cbi("qos_gargoyle/download_rule")).leaf = true - - entry({"admin", "network", "qos_gargoyle", "troubleshooting"}, - template("qos_gargoyle/troubleshooting"), _("Troubleshooting"), 40) - - entry({"admin", "network", "qos_gargoyle", "troubleshooting", "data"}, - call("action_troubleshooting_data")) - - entry({"admin", "network", "qos_gargoyle", "load_data"}, - call("action_load_data")).leaf = true -end - -function action_troubleshooting_data() - local uci = require "luci.model.uci".cursor() - local i18n = require "luci.i18n" - - local data = {} - - local monenabled = uci:get("qos_gargoyle", "download", "qos_monenabled") or "false" - - local show_data = util.trim(util.exec("/etc/init.d/qos_gargoyle show 2>/dev/null")) - if show_data == "" then - show_data = i18n.translate("No data found") - end - - data.show = show_data - - local mon_data - if monenabled == "true" then - mon_data = util.trim(util.exec("cat /tmp/qosmon.status 2>/dev/null")) - - if mon_data == "" then - mon_data = i18n.translate("No data found") - end - else - mon_data = i18n.translate("\"Active Congestion Control\" not enabled") - end - - data.mon = mon_data - - http.prepare_content("application/json") - http.write_json(data) -end - -function action_load_data(type) - local device - if type == "download" then - device = "imq0" - elseif type == "upload" then - local qos = require "luci.model.qos_gargoyle" - local wan = qos.get_wan() - device = wan and wan:ifname() or "" - end - - if device then - local data - if device ~= "" then - data = util.exec("tc -s class show dev %s 2>/dev/null" % device) - end - http.prepare_content("text/plain") - http.write(data or "") - else - http.status(500, "Bad address") - end -end diff --git a/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/download.lua b/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/download.lua deleted file mode 100755 index a165178874..0000000000 --- a/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/download.lua +++ /dev/null @@ -1,166 +0,0 @@ --- Copyright 2017 Xingwang Liao --- Licensed to the public under the Apache License 2.0. - -local wa = require "luci.tools.webadmin" -local uci = require "luci.model.uci".cursor() -local dsp = require "luci.dispatcher" -local http = require "luci.http" -local qos = require "luci.model.qos_gargoyle" - -local m, class_s, rule_s, o -local download_classes = {} -local qos_gargoyle = "qos_gargoyle" - -uci:foreach(qos_gargoyle, "download_class", function(s) - local class_alias = s.name - if class_alias then - download_classes[#download_classes + 1] = {name = s[".name"], alias = class_alias} - end -end) - -m = Map(qos_gargoyle, translate("Download Settings")) -m.template = "qos_gargoyle/list_view" - -class_s = m:section(TypedSection, "download_class", translate("Service Classes"), - translate("Each service class is specified by four parameters: percent bandwidth at capacity, " - .. "realtime bandwidth and maximum bandwidth and the minimimze round trip time flag.")) -class_s.anonymous = true -class_s.addremove = true -class_s.template = "cbi/tblsection" -class_s.extedit = dsp.build_url("admin/network/qos_gargoyle/download/class/%s") -class_s.create = function(...) - local sid = TypedSection.create(...) - if sid then - m.uci:save(qos_gargoyle) - http.redirect(class_s.extedit % sid) - return - end -end - -o = class_s:option(DummyValue, "name", translate("Class Name")) -o.cfgvalue = function(...) - return Value.cfgvalue(...) or translate("None") -end - -o = class_s:option(DummyValue, "percent_bandwidth", translate("Percent Bandwidth At Capacity")) -o.cfgvalue = function(...) - local v = tonumber(Value.cfgvalue(...)) - if v and v > 0 then - return "%d %%" % v - end - return translate("Not set") -end - -o = class_s:option(DummyValue, "min_bandwidth", "%s (kbps)" % translate("Minimum Bandwidth")) -o.cfgvalue = function(...) - local v = tonumber(Value.cfgvalue(...)) - return v or translate("Zero") -end - -o = class_s:option(DummyValue, "max_bandwidth", "%s (kbps)" % translate("Maximum Bandwidth")) -o.cfgvalue = function(...) - local v = tonumber(Value.cfgvalue(...)) - return v or translate("Unlimited") -end - -o = class_s:option(DummyValue, "minRTT", translate("Minimize RTT")) -o.cfgvalue = function(...) - local v = Value.cfgvalue(...) - return v and translate(v) or translate("No") -end - -o = class_s:option(DummyValue, "_ld", "%s (kbps)" % translate("Load")) -o.rawhtml = true -o.value = "*" - -rule_s = m:section(TypedSection, "download_rule", translate("Classification Rules"), - translate("Packets are tested against the rules in the order specified -- rules toward the top " - .. "have priority. As soon as a packet matches a rule it is classified, and the rest of the rules " - .. "are ignored. The order of the rules can be altered using the arrow controls.") - ) -rule_s.addremove = true -rule_s.sortable = true -rule_s.anonymous = true -rule_s.template = "cbi/tblsection" -rule_s.extedit = dsp.build_url("admin/network/qos_gargoyle/download/rule/%s") -rule_s.create = function(...) - local sid = TypedSection.create(...) - if sid then - m.uci:save(qos_gargoyle) - http.redirect(rule_s.extedit % sid) - return - end -end - -o = rule_s:option(ListValue, "class", translate("Service Class")) -for _, s in ipairs(download_classes) do o:value(s.name, s.alias) end - -o = rule_s:option(Value, "proto", translate("Transport Protocol")) -o:value("", translate("All")) -o:value("tcp", "TCP") -o:value("udp", "UDP") -o:value("icmp", "ICMP") -o:value("gre", "GRE") -o.size = "10" -o.cfgvalue = function(...) - local v = Value.cfgvalue(...) - return v and v:upper() or "" -end -o.write = function(self, section, value) - Value.write(self, section, value:lower()) -end - -o = rule_s:option(Value, "source", translate("Source IP(s)")) -o:value("", translate("All")) -wa.cbi_add_knownips(o) -o.datatype = "ipmask4" - -o = rule_s:option(Value, "srcport", translate("Source Port(s)")) -o:value("", translate("All")) -o.datatype = "or(port, portrange)" - -o = rule_s:option(Value, "destination", translate("Destination IP(s)")) -o:value("", translate("All")) -wa.cbi_add_knownips(o) -o.datatype = "ipmask4" - -o = rule_s:option(Value, "dstport", translate("Destination Port(s)")) -o:value("", translate("All")) -o.datatype = "or(port, portrange)" - -o = rule_s:option(DummyValue, "min_pkt_size", translate("Minimum Packet Length")) -o.cfgvalue = function(...) - local v = tonumber(Value.cfgvalue(...)) - if v and v > 0 then - return wa.byte_format(v) - end - return translate("Not set") -end - -o = rule_s:option(DummyValue, "max_pkt_size", translate("Maximum Packet Length")) -o.cfgvalue = function(...) - local v = tonumber(Value.cfgvalue(...)) - if v and v > 0 then - return wa.byte_format(v) - end - return translate("Not set") -end - -o = rule_s:option(DummyValue, "connbytes_kb", translate("Connection Bytes Reach")) -o.cfgvalue = function(...) - local v = tonumber(Value.cfgvalue(...)) - if v and v > 0 then - return wa.byte_format(v * 1024) - end - return translate("Not set") -end - -if qos.has_ndpi() then - o = rule_s:option(DummyValue, "ndpi", translate("DPI Protocol")) - o.cfgvalue = function(...) - local v = Value.cfgvalue(...) - return v and v:upper() or translate("All") - end -end - -return m diff --git a/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/download_class.lua b/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/download_class.lua deleted file mode 100755 index c26cb78301..0000000000 --- a/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/download_class.lua +++ /dev/null @@ -1,61 +0,0 @@ --- Copyright 2017 Xingwang Liao --- Licensed to the public under the Apache License 2.0. - -local m, s, o -local sid = arg[1] -local qos_gargoyle = "qos_gargoyle" - -m = Map(qos_gargoyle, translate("Edit Download Service Class")) -m.redirect = luci.dispatcher.build_url("admin/network/qos_gargoyle/download") - -if m.uci:get(qos_gargoyle, sid) ~= "download_class" then - luci.http.redirect(m.redirect) - return -end - -s = m:section(NamedSection, sid, "download_class") -s.anonymous = true -s.addremove = false - -o = s:option(Value, "name", translate("Service Class Name")) -o.rmempty = false - -o = s:option(Value, "percent_bandwidth", translate("Percent Bandwidth At Capacity"), - translate("The percentage of the total available bandwidth that should be allocated to this class " - .. "when all available bandwidth is being used. If unused bandwidth is available, more can (and " - .. "will) be allocated. The percentages can be configured to equal more (or less) than 100, but " - .. "when the settings are applied the percentages will be adjusted proportionally so that they " - .. "add to 100. This setting only comes into effect when the WAN link is saturated.")) -o.datatype = "range(1, 100)" -o.rmempty = false - -o = s:option(Value, "min_bandwidth", translate("Minimum Bandwidth"), - translate("The minimum service this class will be allocated when the link is at capacity. Classes " - .. "which specify minimum service are known as realtime classes by the active congestion " - .. "controller. Streaming video, VoIP and interactive online gaming are all examples of " - .. "applications that must have a minimum bandwith to function. To determine what to enter use " - .. "the application on an unloaded LAN and observe how much bandwidth it uses. Then enter a " - .. "number only slightly higher than this into this field. QoS will satisfiy the minimum service " - .. "of all classes first before allocating to other waiting classes so be careful to use minimum " - .. "bandwidths sparingly.")) -o:value("0", translate("Zero")) -o.datatype = "uinteger" -o.default = "0" - -o = s:option(Value, "max_bandwidth", translate("Maximum Bandwidth"), - translate("The maximum amount of bandwidth this class will be allocated in kbit/s. Even if unused " - .. "bandwidth is available, this service class will never be permitted to use more than this " - .. "amount of bandwidth.")) -o:value("", translate("Unlimited")) -o.datatype = "uinteger" - -o = s:option(Flag, "minRTT", translate("Minimize RTT"), - translate("Indicates to the active congestion controller that you wish to minimize round trip " - .. "times (RTT) when this class is active. Use this setting for online gaming or VoIP " - .. "applications that need low round trip times (ping times). Minimizing RTT comes at the expense " - .. "of efficient WAN throughput so while these class are active your WAN throughput will decline " - .. "(usually around 20%).")) -o.enabled = "Yes" -o.disabled = "No" - -return m diff --git a/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/download_rule.lua b/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/download_rule.lua deleted file mode 100755 index cbc970e2f0..0000000000 --- a/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/download_rule.lua +++ /dev/null @@ -1,87 +0,0 @@ --- Copyright 2017 Xingwang Liao --- Licensed to the public under the Apache License 2.0. - -local wa = require "luci.tools.webadmin" -local uci = require "luci.model.uci".cursor() -local qos = require "luci.model.qos_gargoyle" - -local m, s, o -local sid = arg[1] -local download_classes = {} -local qos_gargoyle = "qos_gargoyle" - -uci:foreach(qos_gargoyle, "download_class", function(s) - local class_alias = s.name - if class_alias then - download_classes[#download_classes + 1] = {name = s[".name"], alias = class_alias} - end -end) - -m = Map(qos_gargoyle, translate("Edit Download Classification Rule")) -m.redirect = luci.dispatcher.build_url("admin/network/qos_gargoyle/download") - -if m.uci:get(qos_gargoyle, sid) ~= "download_rule" then - luci.http.redirect(m.redirect) - return -end - -s = m:section(NamedSection, sid, "download_rule") -s.anonymous = true -s.addremove = false - -o = s:option(ListValue, "class", translate("Service Class")) -for _, s in ipairs(download_classes) do o:value(s.name, s.alias) end - -o = s:option(Value, "proto", translate("Transport Protocol")) -o:value("", translate("All")) -o:value("tcp", "TCP") -o:value("udp", "UDP") -o:value("icmp", "ICMP") -o:value("gre", "GRE") -o.write = function(self, section, value) - Value.write(self, section, value:lower()) -end - -o = s:option(Value, "source", translate("Source IP(s)"), - translate("Packet's source ip, can optionally have /[mask] after it (see -s option in iptables " - .. "man page).")) -o:value("", translate("All")) -wa.cbi_add_knownips(o) -o.datatype = "ipmask4" - -o = s:option(Value, "srcport", translate("Source Port(s)"), - translate("Packet's source port, can be a range (eg. 80-90).")) -o:value("", translate("All")) -o.datatype = "or(port, portrange)" - -o = s:option(Value, "destination", translate("Destination IP(s)"), - translate("Packet's destination ip, can optionally have /[mask] after it (see -d option in " - .. "iptables man page).")) -o:value("", translate("All")) -wa.cbi_add_knownips(o) -o.datatype = "ipmask4" - -o = s:option(Value, "dstport", translate("Destination Port(s)"), - translate("Packet's destination port, can be a range (eg. 80-90).")) -o:value("", translate("All")) -o.datatype = "or(port, portrange)" - -o = s:option(Value, "min_pkt_size", translate("Minimum Packet Length"), - translate("Packet's minimum size (in bytes).")) -o.datatype = "range(1, 1500)" - -o = s:option(Value, "max_pkt_size", translate("Maximum Packet Length"), - translate("Packet's maximum size (in bytes).")) -o.datatype = "range(1, 1500)" - -o = s:option(Value, "connbytes_kb", translate("Connection Bytes Reach"), - translate("The total size of data transmitted since the establishment of the link (in kBytes).")) -o.datatype = "range(0, 4194303)" - -if qos.has_ndpi() then - o = s:option(ListValue, "ndpi", translate("DPI Protocol")) - o:value("", translate("All")) - qos.cbi_add_dpi_protocols(o) -end - -return m diff --git a/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/global.lua b/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/global.lua deleted file mode 100755 index dcc8f2e4a0..0000000000 --- a/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/global.lua +++ /dev/null @@ -1,123 +0,0 @@ --- Copyright 2017 Xingwang Liao --- Licensed to the public under the Apache License 2.0. - -local sys = require "luci.sys" -local uci = require "luci.model.uci".cursor() -local net = require "luci.model.network".init() -local qos = require "luci.model.qos_gargoyle" - -local m, s, o -local upload_classes = {} -local download_classes = {} -local qos_gargoyle = "qos_gargoyle" - -local function qos_enabled() - return sys.init.enabled(qos_gargoyle) -end - -uci:foreach(qos_gargoyle, "upload_class", function(s) - local class_alias = s.name - if class_alias then - upload_classes[#upload_classes + 1] = {name = s[".name"], alias = class_alias} - end -end) - -uci:foreach(qos_gargoyle, "download_class", function(s) - local class_alias = s.name - if class_alias then - download_classes[#download_classes + 1] = {name = s[".name"], alias = class_alias} - end -end) - -m = Map(qos_gargoyle, translate("Gargoyle QoS"), - translate("Quality of Service (QoS) provides a way to control how available bandwidth is " - .. "allocated.")) - -s = m:section(NamedSection, "global", "global", translate("Global Settings")) -s.anonymous = true - -o = s:option(Button, "_switch", nil, translate("QoS Switch")) -o.render = function(self, section, scope) - if qos_enabled() then - self.title = translate("Disable QoS") - self.inputstyle = "reset" - else - self.title = translate("Enable QoS") - self.inputstyle = "apply" - end - Button.render(self, section, scope) -end -o.write = function(...) - if qos_enabled() then - sys.init.stop(qos_gargoyle) - sys.init.disable(qos_gargoyle) - else - sys.init.enable(qos_gargoyle) - sys.init.start(qos_gargoyle) - end -end - -s = m:section(NamedSection, "upload", "upload", translate("Upload Settings")) -s.anonymous = true - -o = s:option(ListValue, "default_class", translate("Default Service Class"), - translate("Specifie how packets that do not match any rule should be classified.")) -for _, s in ipairs(upload_classes) do o:value(s.name, s.alias) end - -o = s:option(Value, "total_bandwidth", translate("Total Upload Bandwidth"), - translate("Should be set to around 98% of your available upload bandwidth. Entering a number " - .. "which is too high will result in QoS not meeting its class requirements. Entering a number " - .. "which is too low will needlessly penalize your upload speed. You should use a speed test " - .. "program (with QoS off) to determine available upload bandwidth. Note that bandwidth is " - .. "specified in kbps, leave blank to disable update QoS. There are 8 kilobits per kilobyte.")) -o.datatype = "uinteger" - -s = m:section(NamedSection, "download", "download", translate("Download Settings")) -s.anonymous = true - -o = s:option(ListValue, "default_class", translate("Default Service Class"), - translate("Specifie how packets that do not match any rule should be classified.")) -for _, s in ipairs(download_classes) do o:value(s.name, s.alias) end - -o = s:option(Value, "total_bandwidth", translate("Total Download Bandwidth"), - translate("Specifying correctly is crucial to making QoS work. Note that bandwidth is specified " - .. "in kbps, leave blank to disable download QoS. There are 8 kilobits per kilobyte.")) -o.datatype = "uinteger" - -o = s:option(Flag, "qos_monenabled", translate("Enable Active Congestion Control"), - translate("

The active congestion control (ACC) observes your download activity and " - .. "automatically adjusts your download link limit to maintain proper QoS performance. ACC " - .. "automatically compensates for changes in your ISP's download speed and the demand from your " - .. "network adjusting the link speed to the highest speed possible which will maintain proper QoS " - .. "function. The effective range of this control is between 15% and 100% of the total download " - .. "bandwidth you entered above.

") .. - translate("

While ACC does not adjust your upload link speed you must enable and properly " - .. "configure your upload QoS for it to function properly.

") - ) -o.enabled = "true" -o.disabled = "false" - -o = s:option(Value, "ptarget_ip", translate("Use Non-standard Ping Target"), - translate("The segment of network between your router and the ping target is where congestion is " - .. "controlled. By monitoring the round trip ping times to the target congestion is detected. By " - .. "default ACC uses your WAN gateway as the ping target. If you know that congestion on your " - .. "link will occur in a different segment then you can enter an alternate ping target. Leave " - .. "empty to use the default settings.")) -o:depends("qos_monenabled", "true") -local wan = qos.get_wan() -if wan then o:value(wan:gwaddr()) end -o.datatype = "ipaddr" - -o = s:option(Value, "pinglimit", translate("Manual Ping Limit"), - translate("Round trip ping times are compared against the ping limits. ACC controls the link " - .. "limit to maintain ping times under the appropriate limit. By default ACC attempts to " - .. "automatically select appropriate target ping limits for you based on the link speeds you " - .. "entered and the performance of your link it measures during initialization. You cannot change " - .. "the target ping time for the minRTT mode but by entering a manual time you can control the " - .. "target ping time of the active mode. The time you enter becomes the increase in the target " - .. "ping time between minRTT and active mode. Leave empty to use the default settings.")) -o:depends("qos_monenabled", "true") -o:value("Auto", translate("Auto")) -o.datatype = "or('Auto', range(10, 250))" - -return m diff --git a/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/upload.lua b/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/upload.lua deleted file mode 100755 index a5f86927ef..0000000000 --- a/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/upload.lua +++ /dev/null @@ -1,160 +0,0 @@ --- Copyright 2017 Xingwang Liao --- Licensed to the public under the Apache License 2.0. - -local wa = require "luci.tools.webadmin" -local uci = require "luci.model.uci".cursor() -local dsp = require "luci.dispatcher" -local http = require "luci.http" -local qos = require "luci.model.qos_gargoyle" - -local m, class_s, rule_s, o -local upload_classes = {} -local qos_gargoyle = "qos_gargoyle" - -uci:foreach(qos_gargoyle, "upload_class", function(s) - local class_alias = s.name - if class_alias then - upload_classes[#upload_classes + 1] = {name = s[".name"], alias = class_alias} - end -end) - -m = Map(qos_gargoyle, translate("Upload Settings")) -m.template = "qos_gargoyle/list_view" - -class_s = m:section(TypedSection, "upload_class", translate("Service Classes"), - translate("Each upload service class is specified by three parameters: percent bandwidth at " - .. "capacity, minimum bandwidth and maximum bandwidth.")) -class_s.anonymous = true -class_s.addremove = true -class_s.template = "cbi/tblsection" -class_s.extedit = dsp.build_url("admin/network/qos_gargoyle/upload/class/%s") -class_s.create = function(...) - local sid = TypedSection.create(...) - if sid then - m.uci:save(qos_gargoyle) - http.redirect(class_s.extedit % sid) - return - end -end - -o = class_s:option(DummyValue, "name", translate("Class Name")) -o.cfgvalue = function(...) - return Value.cfgvalue(...) or translate("None") -end - -o = class_s:option(DummyValue, "percent_bandwidth", translate("Percent Bandwidth At Capacity")) -o.cfgvalue = function(...) - local v = tonumber(Value.cfgvalue(...)) - if v and v > 0 then - return "%d %%" % v - end - return translate("Not set") -end - -o = class_s:option(DummyValue, "min_bandwidth", "%s (kbps)" % translate("Minimum Bandwidth")) -o.cfgvalue = function(...) - local v = tonumber(Value.cfgvalue(...)) - return v or translate("Zero") -end - -o = class_s:option(DummyValue, "max_bandwidth", "%s (kbps)" % translate("Maximum Bandwidth")) -o.cfgvalue = function(...) - local v = tonumber(Value.cfgvalue(...)) - return v or translate("Unlimited") -end - -o = class_s:option(DummyValue, "_ld", "%s (kbps)" % translate("Load")) -o.rawhtml = true -o.value = "*" - -rule_s = m:section(TypedSection, "upload_rule",translate("Classification Rules"), - translate("Packets are tested against the rules in the order specified -- rules toward the top " - .. "have priority. As soon as a packet matches a rule it is classified, and the rest of the rules " - .. "are ignored. The order of the rules can be altered using the arrow controls.") -) -rule_s.addremove = true -rule_s.sortable = true -rule_s.anonymous = true -rule_s.template = "cbi/tblsection" -rule_s.extedit = dsp.build_url("admin/network/qos_gargoyle/upload/rule/%s") -rule_s.create = function(...) - local sid = TypedSection.create(...) - if sid then - m.uci:save(qos_gargoyle) - http.redirect(rule_s.extedit % sid) - return - end -end - -o = rule_s:option(ListValue, "class", translate("Service Class")) -for _, s in ipairs(upload_classes) do o:value(s.name, s.alias) end - -o = rule_s:option(Value, "proto", translate("Transport Protocol")) -o:value("", translate("All")) -o:value("tcp", "TCP") -o:value("udp", "UDP") -o:value("icmp", "ICMP") -o:value("gre", "GRE") -o.size = "10" -o.cfgvalue = function(...) - local v = Value.cfgvalue(...) - return v and v:upper() or "" -end -o.write = function(self, section, value) - Value.write(self, section, value:lower()) -end - -o = rule_s:option(Value, "source", translate("Source IP(s)")) -o:value("", translate("All")) -wa.cbi_add_knownips(o) -o.datatype = "ipmask4" - -o = rule_s:option(Value, "srcport", translate("Source Port(s)")) -o:value("", translate("All")) -o.datatype = "or(port, portrange)" - -o = rule_s:option(Value, "destination", translate("Destination IP(s)")) -o:value("", translate("All")) -wa.cbi_add_knownips(o) -o.datatype = "ipmask4" - -o = rule_s:option(Value, "dstport", translate("Destination Port(s)")) -o:value("", translate("All")) -o.datatype = "or(port, portrange)" - -o = rule_s:option(DummyValue, "min_pkt_size", translate("Minimum Packet Length")) -o.cfgvalue = function(...) - local v = tonumber(Value.cfgvalue(...)) - if v and v > 0 then - return wa.byte_format(v) - end - return translate("Not set") -end - -o = rule_s:option(DummyValue, "max_pkt_size", translate("Maximum Packet Length")) -o.cfgvalue = function(...) - local v = tonumber(Value.cfgvalue(...)) - if v and v > 0 then - return wa.byte_format(v) - end - return translate("Not set") -end - -o = rule_s:option(DummyValue, "connbytes_kb", translate("Connection Bytes Reach")) -o.cfgvalue = function(...) - local v = tonumber(Value.cfgvalue(...)) - if v and v > 0 then - return wa.byte_format(v * 1024) - end - return translate("Not set") -end - -if qos.has_ndpi() then - o = rule_s:option(DummyValue, "ndpi", translate("DPI Protocol")) - o.cfgvalue = function(...) - local v = Value.cfgvalue(...) - return v and v:upper() or translate("All") - end -end - -return m diff --git a/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/upload_class.lua b/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/upload_class.lua deleted file mode 100755 index 9739b9794b..0000000000 --- a/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/upload_class.lua +++ /dev/null @@ -1,52 +0,0 @@ --- Copyright 2017 Xingwang Liao --- Licensed to the public under the Apache License 2.0. - -local m, s, o -local sid = arg[1] -local qos_gargoyle = "qos_gargoyle" - -m = Map(qos_gargoyle, translate("Edit Upload Service Class")) -m.redirect = luci.dispatcher.build_url("admin/network/qos_gargoyle/upload") - -if m.uci:get(qos_gargoyle, sid) ~= "upload_class" then - luci.http.redirect(m.redirect) - return -end - -s = m:section(NamedSection, sid, "upload_class") -s.anonymous = true -s.addremove = false - -o = s:option(Value, "name", translate("Service Class Name")) -o.rmempty = false - -o = s:option(Value, "percent_bandwidth", translate("Percent Bandwidth At Capacity"), - translate("The percentage of the total available bandwidth that should be allocated to this class " - .. "when all available bandwidth is being used. If unused bandwidth is available, more can (and " - .. "will) be allocated. The percentages can be configured to equal more (or less) than 100, but " - .. "when the settings are applied the percentages will be adjusted proportionally so that they " - .. "add to 100. This setting only comes into effect when the WAN link is saturated.")) -o.datatype = "range(1, 100)" -o.rmempty = false - -o = s:option(Value, "min_bandwidth", translate("Minimum Bandwidth"), - translate("The minimum service this class will be allocated when the link is at capacity. Classes " - .. "which specify minimum service are known as realtime classes by the active congestion " - .. "controller. Streaming video, VoIP and interactive online gaming are all examples of " - .. "applications that must have a minimum bandwith to function. To determine what to enter use " - .. "the application on an unloaded LAN and observe how much bandwidth it uses. Then enter a " - .. "number only slightly higher than this into this field. QoS will satisfiy the minimum service " - .. "of all classes first before allocating to other waiting classes so be careful to use minimum " - .. "bandwidths sparingly.")) -o:value("0", translate("Zero")) -o.datatype = "uinteger" -o.default = "0" - -o = s:option(Value, "max_bandwidth", translate("Maximum Bandwidth"), - translate("The maximum amount of bandwidth this class will be allocated in kbit/s. Even if unused " - .. "bandwidth is available, this service class will never be permitted to use more than this " - .. "amount of bandwidth.")) -o:value("", translate("Unlimited")) -o.datatype = "uinteger" - -return m diff --git a/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/upload_rule.lua b/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/upload_rule.lua deleted file mode 100755 index 8abcac35d9..0000000000 --- a/package/jsda/luci-app-qos-gargoyle/luasrc/model/cbi/qos_gargoyle/upload_rule.lua +++ /dev/null @@ -1,87 +0,0 @@ --- Copyright 2017 Xingwang Liao --- Licensed to the public under the Apache License 2.0. - -local wa = require "luci.tools.webadmin" -local uci = require "luci.model.uci".cursor() -local qos = require "luci.model.qos_gargoyle" - -local m, s, o -local sid = arg[1] -local upload_classes = {} -local qos_gargoyle = "qos_gargoyle" - -uci:foreach(qos_gargoyle, "upload_class", function(s) - local class_alias = s.name - if class_alias then - upload_classes[#upload_classes + 1] = {name = s[".name"], alias = class_alias} - end -end) - -m = Map(qos_gargoyle, translate("Edit Upload Classification Rule")) -m.redirect = luci.dispatcher.build_url("admin/network/qos_gargoyle/upload") - -if m.uci:get(qos_gargoyle, sid) ~= "upload_rule" then - luci.http.redirect(m.redirect) - return -end - -s = m:section(NamedSection, sid, "upload_rule") -s.anonymous = true -s.addremove = false - -o = s:option(ListValue, "class", translate("Service Class")) -for _, s in ipairs(upload_classes) do o:value(s.name, s.alias) end - -o = s:option(Value, "proto", translate("Transport Protocol")) -o:value("", translate("All")) -o:value("tcp", "TCP") -o:value("udp", "UDP") -o:value("icmp", "ICMP") -o:value("gre", "GRE") -o.write = function(self, section, value) - Value.write(self, section, value:lower()) -end - -o = s:option(Value, "source", translate("Source IP(s)"), - translate("Packet's source ip, can optionally have /[mask] after it (see -s option in iptables " - .. "man page).")) -o:value("", translate("All")) -wa.cbi_add_knownips(o) -o.datatype = "ipmask4" - -o = s:option(Value, "srcport", translate("Source Port(s)"), - translate("Packet's source port, can be a range (eg. 80-90).")) -o:value("", translate("All")) -o.datatype = "or(port, portrange)" - -o = s:option(Value, "destination", translate("Destination IP(s)"), - translate("Packet's destination ip, can optionally have /[mask] after it (see -d option in " - .. "iptables man page).")) -o:value("", translate("All")) -wa.cbi_add_knownips(o) -o.datatype = "ipmask4" - -o = s:option(Value, "dstport", translate("Destination Port(s)"), - translate("Packet's destination port, can be a range (eg. 80-90).")) -o:value("", translate("All")) -o.datatype = "or(port, portrange)" - -o = s:option(Value, "min_pkt_size", translate("Minimum Packet Length"), - translate("Packet's minimum size (in bytes).")) -o.datatype = "range(1, 1500)" - -o = s:option(Value, "max_pkt_size", translate("Maximum Packet Length"), - translate("Packet's maximum size (in bytes).")) -o.datatype = "range(1, 1500)" - -o = s:option(Value, "connbytes_kb", translate("Connection Bytes Reach"), - translate("The total size of data transmitted since the establishment of the link (in kBytes).")) -o.datatype = "range(0, 4194303)" - -if qos.has_ndpi() then - o = s:option(ListValue, "ndpi", translate("DPI Protocol")) - o:value("", translate("All")) - qos.cbi_add_dpi_protocols(o) -end - -return m diff --git a/package/jsda/luci-app-qos-gargoyle/luasrc/model/qos_gargoyle.lua b/package/jsda/luci-app-qos-gargoyle/luasrc/model/qos_gargoyle.lua deleted file mode 100755 index b0113f1872..0000000000 --- a/package/jsda/luci-app-qos-gargoyle/luasrc/model/qos_gargoyle.lua +++ /dev/null @@ -1,31 +0,0 @@ --- Copyright 2017 Xingwang Liao --- Licensed to the public under the Apache License 2.0. - -module("luci.model.qos_gargoyle", package.seeall) - -function has_ndpi() - return luci.sys.call("lsmod | cut -d ' ' -f1 | grep -q 'xt_ndpi'") == 0 -end - -function cbi_add_dpi_protocols(field) - local util = require "luci.util" - - local dpi_protocols = {} - - for line in util.execi("iptables -m ndpi --help 2>/dev/null | grep '^--'") do - local _, _, protocol, name = line:find("%-%-([^%s]+) Match for ([^%s]+)") - - if protocol and name then - dpi_protocols[protocol] = name - end - end - - for p, n in util.kspairs(dpi_protocols) do - field:value(p, n) - end -end - -function get_wan() - local net = require "luci.model.network".init() - return net:get_wannet() -end diff --git a/package/jsda/luci-app-qos-gargoyle/luasrc/view/qos_gargoyle/list_view.htm b/package/jsda/luci-app-qos-gargoyle/luasrc/view/qos_gargoyle/list_view.htm deleted file mode 100755 index 87d3994de2..0000000000 --- a/package/jsda/luci-app-qos-gargoyle/luasrc/view/qos_gargoyle/list_view.htm +++ /dev/null @@ -1,97 +0,0 @@ -<%# - Copyright 2017 Xingwang Liao - Licensed to the public under the Apache License 2.0. --%> - -<% - local dsp = require "luci.dispatcher" - local request = dsp.context.path - local leaf = request[#request] --%> - - - -<%+cbi/map%> - - diff --git a/package/jsda/luci-app-qos-gargoyle/luasrc/view/qos_gargoyle/troubleshooting.htm b/package/jsda/luci-app-qos-gargoyle/luasrc/view/qos_gargoyle/troubleshooting.htm deleted file mode 100755 index 17197850e8..0000000000 --- a/package/jsda/luci-app-qos-gargoyle/luasrc/view/qos_gargoyle/troubleshooting.htm +++ /dev/null @@ -1,52 +0,0 @@ -<%# - Copyright 2017 Xingwang Liao - Licensed to the public under the Apache License 2.0. --%> - -<% css = [[ - - #troubleshoot_text { - padding: 20px; - text-align: left; - } - #troubleshoot_text pre { - word-break: break-all; - margin: 0; - } - .description { - background-color: #33CCFF; - } - -]] --%> - -<%+header%> - - - - -
-
- <%:Troubleshooting Data%> -
<%:Loading%><%:Collecting data...%>
-
-
- -<%+footer%> diff --git a/package/jsda/luci-app-qos-gargoyle/po/templates/qos-gargoyle.pot b/package/jsda/luci-app-qos-gargoyle/po/templates/qos-gargoyle.pot deleted file mode 100755 index 9e194d7bc2..0000000000 --- a/package/jsda/luci-app-qos-gargoyle/po/templates/qos-gargoyle.pot +++ /dev/null @@ -1,292 +0,0 @@ -msgid "" -msgstr "Content-Type: text/plain; charset=UTF-8" - -msgid "\"Active Congestion Control\" not enabled" -msgstr "" - -msgid "" -"

The active congestion control (ACC) observes your download activity and " -"automatically adjusts your download link limit to maintain proper QoS " -"performance. ACC automatically compensates for changes in your ISP's " -"download speed and the demand from your network adjusting the link speed to " -"the highest speed possible which will maintain proper QoS function. The " -"effective range of this control is between 15% and 100% of the total " -"download bandwidth you entered above.

" -msgstr "" - -msgid "" -"

While ACC does not adjust your upload link speed you must enable and " -"properly configure your upload QoS for it to function properly.

" -msgstr "" - -msgid "All" -msgstr "" - -msgid "Auto" -msgstr "" - -msgid "Class Name" -msgstr "" - -msgid "Classification Rules" -msgstr "" - -msgid "Collecting data..." -msgstr "" - -msgid "Connection Bytes Reach" -msgstr "" - -msgid "DPI Protocol" -msgstr "" - -msgid "Default Service Class" -msgstr "" - -msgid "Destination IP(s)" -msgstr "" - -msgid "Destination Port(s)" -msgstr "" - -msgid "Disable QoS" -msgstr "" - -msgid "Download Settings" -msgstr "" - -msgid "" -"Each service class is specified by four parameters: percent bandwidth at " -"capacity, realtime bandwidth and maximum bandwidth and the minimimze round " -"trip time flag." -msgstr "" - -msgid "" -"Each upload service class is specified by three parameters: percent " -"bandwidth at capacity, minimum bandwidth and maximum bandwidth." -msgstr "" - -msgid "Edit Download Classification Rule" -msgstr "" - -msgid "Edit Download Service Class" -msgstr "" - -msgid "Edit Upload Classification Rule" -msgstr "" - -msgid "Edit Upload Service Class" -msgstr "" - -msgid "Enable Active Congestion Control" -msgstr "" - -msgid "Enable QoS" -msgstr "" - -msgid "Error collecting troubleshooting information" -msgstr "" - -msgid "Gargoyle QoS" -msgstr "" - -msgid "Global Settings" -msgstr "" - -msgid "" -"Indicates to the active congestion controller that you wish to minimize " -"round trip times (RTT) when this class is active. Use this setting for " -"online gaming or VoIP applications that need low round trip times (ping " -"times). Minimizing RTT comes at the expense of efficient WAN throughput so " -"while these class are active your WAN throughput will decline (usually " -"around 20%)." -msgstr "" - -msgid "Load" -msgstr "" - -msgid "Loading" -msgstr "" - -msgid "Manual Ping Limit" -msgstr "" - -msgid "Maximum Bandwidth" -msgstr "" - -msgid "Maximum Packet Length" -msgstr "" - -msgid "Minimize RTT" -msgstr "" - -msgid "Minimum Bandwidth" -msgstr "" - -msgid "Minimum Packet Length" -msgstr "" - -msgid "No" -msgstr "" - -msgid "No data found" -msgstr "" - -msgid "None" -msgstr "" - -msgid "Not set" -msgstr "" - -msgid "" -"Packet's destination ip, can optionally have /[mask] after it (see -d option " -"in iptables man page)." -msgstr "" - -msgid "Packet's destination port, can be a range (eg. 80-90)." -msgstr "" - -msgid "Packet's maximum size (in bytes)." -msgstr "" - -msgid "Packet's minimum size (in bytes)." -msgstr "" - -msgid "" -"Packet's source ip, can optionally have /[mask] after it (see -s option in " -"iptables man page)." -msgstr "" - -msgid "Packet's source port, can be a range (eg. 80-90)." -msgstr "" - -msgid "" -"Packets are tested against the rules in the order specified -- rules toward " -"the top have priority. As soon as a packet matches a rule it is classified, " -"and the rest of the rules are ignored. The order of the rules can be altered " -"using the arrow controls." -msgstr "" - -msgid "Percent Bandwidth At Capacity" -msgstr "" - -msgid "QoS Switch" -msgstr "" - -msgid "" -"Quality of Service (QoS) provides a way to control how available bandwidth " -"is allocated." -msgstr "" - -msgid "" -"Round trip ping times are compared against the ping limits. ACC controls the " -"link limit to maintain ping times under the appropriate limit. By default " -"ACC attempts to automatically select appropriate target ping limits for you " -"based on the link speeds you entered and the performance of your link it " -"measures during initialization. You cannot change the target ping time for " -"the minRTT mode but by entering a manual time you can control the target " -"ping time of the active mode. The time you enter becomes the increase in the " -"target ping time between minRTT and active mode. Leave empty to use the " -"default settings." -msgstr "" - -msgid "Service Class" -msgstr "" - -msgid "Service Class Name" -msgstr "" - -msgid "Service Classes" -msgstr "" - -msgid "" -"Should be set to around 98% of your available upload bandwidth. Entering a " -"number which is too high will result in QoS not meeting its class " -"requirements. Entering a number which is too low will needlessly penalize " -"your upload speed. You should use a speed test program (with QoS off) to " -"determine available upload bandwidth. Note that bandwidth is specified in " -"kbps, leave blank to disable update QoS. There are 8 kilobits per kilobyte." -msgstr "" - -msgid "Source IP(s)" -msgstr "" - -msgid "Source Port(s)" -msgstr "" - -msgid "Specifie how packets that do not match any rule should be classified." -msgstr "" - -msgid "" -"Specifying correctly is crucial to making QoS work. Note that bandwidth is " -"specified in kbps, leave blank to disable download QoS. There are 8 kilobits " -"per kilobyte." -msgstr "" - -msgid "" -"The maximum amount of bandwidth this class will be allocated in kbit/s. Even " -"if unused bandwidth is available, this service class will never be permitted " -"to use more than this amount of bandwidth." -msgstr "" - -msgid "" -"The minimum service this class will be allocated when the link is at " -"capacity. Classes which specify minimum service are known as realtime " -"classes by the active congestion controller. Streaming video, VoIP and " -"interactive online gaming are all examples of applications that must have a " -"minimum bandwith to function. To determine what to enter use the application " -"on an unloaded LAN and observe how much bandwidth it uses. Then enter a " -"number only slightly higher than this into this field. QoS will satisfiy the " -"minimum service of all classes first before allocating to other waiting " -"classes so be careful to use minimum bandwidths sparingly." -msgstr "" - -msgid "" -"The percentage of the total available bandwidth that should be allocated to " -"this class when all available bandwidth is being used. If unused bandwidth " -"is available, more can (and will) be allocated. The percentages can be " -"configured to equal more (or less) than 100, but when the settings are " -"applied the percentages will be adjusted proportionally so that they add to " -"100. This setting only comes into effect when the WAN link is saturated." -msgstr "" - -msgid "" -"The segment of network between your router and the ping target is where " -"congestion is controlled. By monitoring the round trip ping times to the " -"target congestion is detected. By default ACC uses your WAN gateway as the " -"ping target. If you know that congestion on your link will occur in a " -"different segment then you can enter an alternate ping target. Leave empty " -"to use the default settings." -msgstr "" - -msgid "" -"The total size of data transmitted since the establishment of the link (in " -"kBytes)." -msgstr "" - -msgid "Total Download Bandwidth" -msgstr "" - -msgid "Total Upload Bandwidth" -msgstr "" - -msgid "Transport Protocol" -msgstr "" - -msgid "Troubleshooting" -msgstr "" - -msgid "Troubleshooting Data" -msgstr "" - -msgid "Unlimited" -msgstr "" - -msgid "Upload Settings" -msgstr "" - -msgid "Use Non-standard Ping Target" -msgstr "" - -msgid "Zero" -msgstr "" diff --git a/package/jsda/luci-app-qos-gargoyle/po/zh-cn/qos-gargoyle.po b/package/jsda/luci-app-qos-gargoyle/po/zh-cn/qos-gargoyle.po deleted file mode 100755 index 4b1d10624a..0000000000 --- a/package/jsda/luci-app-qos-gargoyle/po/zh-cn/qos-gargoyle.po +++ /dev/null @@ -1,334 +0,0 @@ -msgid "" -msgstr "Content-Type: text/plain; charset=UTF-8\n" - -msgid "\"Active Congestion Control\" not enabled" -msgstr "“主动拥塞控制”未启用" - -msgid "" -"

The active congestion control (ACC) observes your download activity and " -"automatically adjusts your download link limit to maintain proper QoS " -"performance. ACC automatically compensates for changes in your ISP's " -"download speed and the demand from your network adjusting the link speed to " -"the highest speed possible which will maintain proper QoS function. The " -"effective range of this control is between 15% and 100% of the total " -"download bandwidth you entered above.

" -msgstr "" -"

主动拥塞控制系统(ACC)观察你的下载活动并自动调整你的下载链接限制以保持适" -"当的 QoS 性能。ACC 自动调整 QoS 功能以补偿来自你 ISP 的下载速度变化及来自你网" -"络链接速度的调整需求,使速度最大化。这个控制的有效范围在你上面输入的下载总带" -"宽的 15% 至 100% 之间。

" - -msgid "" -"

While ACC does not adjust your upload link speed you must enable and " -"properly configure your upload QoS for it to function properly.

" -msgstr "" -"

虽然 ACC 不调整你的上传链路速度,但你必须启用并正确配置你的上传 QoS 带宽以" -"使该功能正常工作。

" - -msgid "All" -msgstr "全部" - -msgid "Auto" -msgstr "自动" - -msgid "Class Name" -msgstr "类型名称" - -msgid "Classification Rules" -msgstr "分类规则" - -msgid "Collecting data..." -msgstr "正在收集数据..." - -msgid "Connection Bytes Reach" -msgstr "连接流量达到" - -msgid "DPI Protocol" -msgstr "DPI 协议" - -msgid "Default Service Class" -msgstr "默认服务类型" - -msgid "Destination IP(s)" -msgstr "目标 IP" - -msgid "Destination Port(s)" -msgstr "目标端口" - -msgid "Disable QoS" -msgstr "禁用 QoS" - -msgid "Download Settings" -msgstr "下载设置" - -msgid "" -"Each service class is specified by four parameters: percent bandwidth at " -"capacity, realtime bandwidth and maximum bandwidth and the minimimze round " -"trip time flag." -msgstr "" -"每个下载服务类型由四个参数指定:带宽占用百分比、最小保证带宽、最大带宽和最小" -"往返延时标志。" - -msgid "" -"Each upload service class is specified by three parameters: percent " -"bandwidth at capacity, minimum bandwidth and maximum bandwidth." -msgstr "每个上传服务类型由三个参数指定:带宽占用百分比、最小带宽和最大带宽。" - -msgid "Edit Download Classification Rule" -msgstr "编辑下载分类规则" - -msgid "Edit Download Service Class" -msgstr "编辑下载服务类型" - -msgid "Edit Upload Classification Rule" -msgstr "编辑上传分类规则" - -msgid "Edit Upload Service Class" -msgstr "编辑上传服务类型" - -msgid "Enable Active Congestion Control" -msgstr "启用主动拥塞控制" - -msgid "Enable QoS" -msgstr "启用 QoS" - -msgid "Error collecting troubleshooting information" -msgstr "收集故障排查信息失败" - -msgid "Gargoyle QoS" -msgstr "石像鬼 QoS" - -msgid "Global Settings" -msgstr "全局设置" - -msgid "" -"Indicates to the active congestion controller that you wish to minimize " -"round trip times (RTT) when this class is active. Use this setting for " -"online gaming or VoIP applications that need low round trip times (ping " -"times). Minimizing RTT comes at the expense of efficient WAN throughput so " -"while these class are active your WAN throughput will decline (usually " -"around 20%)." -msgstr "" -"告诉主动拥塞控制器你希望该服务类型启用时尽量减少往返延时(RTT)。该设置一般用" -"在 VoIP 或在线游戏这类需要低延时(Ping 值)的应用上。减小往返延时(RTT)会带" -"来WAN有效吞吐量的额外花销,所以当这些服务类型启用时你的 WAN 吞吐量将下降(通" -"常在20%左右)" - -msgid "Load" -msgstr "负载" - -msgid "Loading" -msgstr "正在加载" - -msgid "Manual Ping Limit" -msgstr "手动 Ping 限制" - -msgid "Maximum Bandwidth" -msgstr "最大带宽" - -msgid "Maximum Packet Length" -msgstr "最大数据包长度" - -msgid "Minimize RTT" -msgstr "最小往返延时" - -msgid "Minimum Bandwidth" -msgstr "最小带宽" - -msgid "Minimum Packet Length" -msgstr "最小数据包长度" - -msgid "No" -msgstr "否" - -msgid "No data found" -msgstr "无数据" - -msgid "None" -msgstr "无" - -msgid "Not set" -msgstr "未设置" - -msgid "" -"Packet's destination ip, can optionally have /[mask] after it (see -d option " -"in iptables man page)." -msgstr "" -"数据包的目标 IP,可以在后面加子网掩码(/[mask],请看 iptables 的 -d 参数说" -"明)" - -msgid "Packet's destination port, can be a range (eg. 80-90)." -msgstr "数据包的目标端口,可以是一个范围(例如:80-90)" - -msgid "Packet's maximum size (in bytes)." -msgstr "数据包的最大大小(单位:bytes)" - -msgid "Packet's minimum size (in bytes)." -msgstr "数据包的最小大小(单位:bytes)" - -msgid "" -"Packet's source ip, can optionally have /[mask] after it (see -s option in " -"iptables man page)." -msgstr "" -"数据包的源 IP,可以在后面加子网掩码(/[mask],请看 iptables 的 -s 参数说明)" - -msgid "Packet's source port, can be a range (eg. 80-90)." -msgstr "数据包的源端口,可以是一个范围(例如:80-90)" - -msgid "" -"Packets are tested against the rules in the order specified -- rules toward " -"the top have priority. As soon as a packet matches a rule it is classified, " -"and the rest of the rules are ignored. The order of the rules can be altered " -"using the arrow controls." -msgstr "" -"数据包将按规则中指定的顺序进行匹配 —— 靠上的规则优先进行匹配。一旦数据包匹配" -"一条规则那它将被归类,并且其余的规则将被忽略。使用上下箭头可调整规则的顺序。" - -msgid "Percent Bandwidth At Capacity" -msgstr "带宽占用百分比" - -msgid "QoS Switch" -msgstr "QoS 开关" - -msgid "" -"Quality of Service (QoS) provides a way to control how available bandwidth " -"is allocated." -msgstr "QoS 可以用来分配和控制可用带宽。" - -msgid "" -"Round trip ping times are compared against the ping limits. ACC controls the " -"link limit to maintain ping times under the appropriate limit. By default " -"ACC attempts to automatically select appropriate target ping limits for you " -"based on the link speeds you entered and the performance of your link it " -"measures during initialization. You cannot change the target ping time for " -"the minRTT mode but by entering a manual time you can control the target " -"ping time of the active mode. The time you enter becomes the increase in the " -"target ping time between minRTT and active mode. Leave empty to use the " -"default settings." -msgstr "" -"Ping 延时会与 Ping 限制进行比较。ACC 控制链路限制以保持 Ping 延时在适当范围。" -"默认情况下,ACC 会自动根据你输入的链接适当为你选择适当的 Ping 限制。如果你想" -"尝试不同的 Ping 限制,你可以在这里输入一个时间值。输入高的时间值将导致更高的 " -"Ping 限制,低的时间值会有更低的限制。留空则将由 ACC 自动控制。" - -msgid "Service Class" -msgstr "服务类型" - -msgid "Service Class Name" -msgstr "服务类型名称" - -msgid "Service Classes" -msgstr "服务类型" - -msgid "" -"Should be set to around 98% of your available upload bandwidth. Entering a " -"number which is too high will result in QoS not meeting its class " -"requirements. Entering a number which is too low will needlessly penalize " -"your upload speed. You should use a speed test program (with QoS off) to " -"determine available upload bandwidth. Note that bandwidth is specified in " -"kbps, leave blank to disable update QoS. There are 8 kilobits per kilobyte." -msgstr "" -"应被设置为你可用上传带宽的 98% 左右。输入数值太高将导致 QoS 不能匹配服务类型" -"的要求。输入数值太低将造成不必要的上传速度限制。你应当在 QoS 关闭的情况下使用" -"测速程序以确定可用的上传带宽。带宽以 kbps 为单位,留空以禁用上传 QoS。" -"(1KByte/s=8Kbps)" - -msgid "Source IP(s)" -msgstr "源 IP" - -msgid "Source Port(s)" -msgstr "源端口" - -msgid "Specifie how packets that do not match any rule should be classified." -msgstr "指定当数据包不匹配任何规则时将被如何归类。" - -msgid "" -"Specifying correctly is crucial to making QoS work. Note that bandwidth is " -"specified in kbps, leave blank to disable download QoS. There are 8 kilobits " -"per kilobyte." -msgstr "" -"正确设置对于 QoS 的工作至关重要。带宽以 kbps 为单位,留空以禁用下载 QoS。" -"(1KByte/s=8Kbps)" - -msgid "" -"The maximum amount of bandwidth this class will be allocated in kbit/s. Even " -"if unused bandwidth is available, this service class will never be permitted " -"to use more than this amount of bandwidth." -msgstr "" -"该服务类型可被分配的带宽最大值(以 kbit/s 为单位)。即使存在未使用带宽,该服" -"务类型也将永远不被允许使用超过此量的带宽。" - -msgid "" -"The minimum service this class will be allocated when the link is at " -"capacity. Classes which specify minimum service are known as realtime " -"classes by the active congestion controller. Streaming video, VoIP and " -"interactive online gaming are all examples of applications that must have a " -"minimum bandwith to function. To determine what to enter use the application " -"on an unloaded LAN and observe how much bandwidth it uses. Then enter a " -"number only slightly higher than this into this field. QoS will satisfiy the " -"minimum service of all classes first before allocating to other waiting " -"classes so be careful to use minimum bandwidths sparingly." -msgstr "" -"将被分配用于该服务类型的最低链路带宽容量。指定了最小带宽的服务类型会被主动拥" -"塞控制器看作实时类应用。例如视频流、VoIP 和在线互动游戏都应该设置最小带宽。要" -"确定需要多少最小带宽,可以在一个没有负载的局域网中使用应用程序并观察它使用了" -"多少带宽。然后输入一个略高于这个值的数字到字段中。在分配剩余带宽到其它服务类" -"型前,QoS 将优先满足所有服务类型的最小带宽要求,所以要谨慎地使用最小带宽。" - -msgid "" -"The percentage of the total available bandwidth that should be allocated to " -"this class when all available bandwidth is being used. If unused bandwidth " -"is available, more can (and will) be allocated. The percentages can be " -"configured to equal more (or less) than 100, but when the settings are " -"applied the percentages will be adjusted proportionally so that they add to " -"100. This setting only comes into effect when the WAN link is saturated." -msgstr "" -"当所有可用带宽被占满后该服务类型占据总带宽的百分比。如果带宽未用完,该服务类" -"型会被分配更多带宽。该百分比值可被设置为等于、大于或小于 100,但当设置被应用" -"时,百分比值将会被按比例调整以便使它们加起来等于 100。该设置只在 WAN 端链路饱" -"和时才生效。(PS:WAN 端链路饱和即带宽被占用完)" - -msgid "" -"The segment of network between your router and the ping target is where " -"congestion is controlled. By monitoring the round trip ping times to the " -"target congestion is detected. By default ACC uses your WAN gateway as the " -"ping target. If you know that congestion on your link will occur in a " -"different segment then you can enter an alternate ping target. Leave empty " -"to use the default settings." -msgstr "" -"在路由器和 Ping 目标之间的网络部分是拥塞控制的地方。拥塞通过监视和目标间的 " -"Ping 延时来检测。默认情况下 ACC 使用你的 WAN 网关作为 Ping 的目标。假如你知道" -"拥塞会在你链路的不同段发生,你可用输入一个备用的 Ping 目标。留空则将由ACC 自" -"动控制。" - -msgid "" -"The total size of data transmitted since the establishment of the link (in " -"kBytes)." -msgstr "自连接建立以来,传输的数据总量(单位:kBytes)" - -msgid "Total Download Bandwidth" -msgstr "下载总带宽" - -msgid "Total Upload Bandwidth" -msgstr "上传总带宽" - -msgid "Transport Protocol" -msgstr "协议" - -msgid "Troubleshooting" -msgstr "故障排除" - -msgid "Troubleshooting Data" -msgstr "故障排除数据" - -msgid "Unlimited" -msgstr "不限制" - -msgid "Upload Settings" -msgstr "上传设置" - -msgid "Use Non-standard Ping Target" -msgstr "使用自定义 Ping 目标" - -msgid "Zero" -msgstr "零" diff --git a/package/jsda/luci-app-qos-gargoyle/po/zh-cn/qos_gargoyle.po b/package/jsda/luci-app-qos-gargoyle/po/zh-cn/qos_gargoyle.po deleted file mode 100755 index 4b1d10624a..0000000000 --- a/package/jsda/luci-app-qos-gargoyle/po/zh-cn/qos_gargoyle.po +++ /dev/null @@ -1,334 +0,0 @@ -msgid "" -msgstr "Content-Type: text/plain; charset=UTF-8\n" - -msgid "\"Active Congestion Control\" not enabled" -msgstr "“主动拥塞控制”未启用" - -msgid "" -"

The active congestion control (ACC) observes your download activity and " -"automatically adjusts your download link limit to maintain proper QoS " -"performance. ACC automatically compensates for changes in your ISP's " -"download speed and the demand from your network adjusting the link speed to " -"the highest speed possible which will maintain proper QoS function. The " -"effective range of this control is between 15% and 100% of the total " -"download bandwidth you entered above.

" -msgstr "" -"

主动拥塞控制系统(ACC)观察你的下载活动并自动调整你的下载链接限制以保持适" -"当的 QoS 性能。ACC 自动调整 QoS 功能以补偿来自你 ISP 的下载速度变化及来自你网" -"络链接速度的调整需求,使速度最大化。这个控制的有效范围在你上面输入的下载总带" -"宽的 15% 至 100% 之间。

" - -msgid "" -"

While ACC does not adjust your upload link speed you must enable and " -"properly configure your upload QoS for it to function properly.

" -msgstr "" -"

虽然 ACC 不调整你的上传链路速度,但你必须启用并正确配置你的上传 QoS 带宽以" -"使该功能正常工作。

" - -msgid "All" -msgstr "全部" - -msgid "Auto" -msgstr "自动" - -msgid "Class Name" -msgstr "类型名称" - -msgid "Classification Rules" -msgstr "分类规则" - -msgid "Collecting data..." -msgstr "正在收集数据..." - -msgid "Connection Bytes Reach" -msgstr "连接流量达到" - -msgid "DPI Protocol" -msgstr "DPI 协议" - -msgid "Default Service Class" -msgstr "默认服务类型" - -msgid "Destination IP(s)" -msgstr "目标 IP" - -msgid "Destination Port(s)" -msgstr "目标端口" - -msgid "Disable QoS" -msgstr "禁用 QoS" - -msgid "Download Settings" -msgstr "下载设置" - -msgid "" -"Each service class is specified by four parameters: percent bandwidth at " -"capacity, realtime bandwidth and maximum bandwidth and the minimimze round " -"trip time flag." -msgstr "" -"每个下载服务类型由四个参数指定:带宽占用百分比、最小保证带宽、最大带宽和最小" -"往返延时标志。" - -msgid "" -"Each upload service class is specified by three parameters: percent " -"bandwidth at capacity, minimum bandwidth and maximum bandwidth." -msgstr "每个上传服务类型由三个参数指定:带宽占用百分比、最小带宽和最大带宽。" - -msgid "Edit Download Classification Rule" -msgstr "编辑下载分类规则" - -msgid "Edit Download Service Class" -msgstr "编辑下载服务类型" - -msgid "Edit Upload Classification Rule" -msgstr "编辑上传分类规则" - -msgid "Edit Upload Service Class" -msgstr "编辑上传服务类型" - -msgid "Enable Active Congestion Control" -msgstr "启用主动拥塞控制" - -msgid "Enable QoS" -msgstr "启用 QoS" - -msgid "Error collecting troubleshooting information" -msgstr "收集故障排查信息失败" - -msgid "Gargoyle QoS" -msgstr "石像鬼 QoS" - -msgid "Global Settings" -msgstr "全局设置" - -msgid "" -"Indicates to the active congestion controller that you wish to minimize " -"round trip times (RTT) when this class is active. Use this setting for " -"online gaming or VoIP applications that need low round trip times (ping " -"times). Minimizing RTT comes at the expense of efficient WAN throughput so " -"while these class are active your WAN throughput will decline (usually " -"around 20%)." -msgstr "" -"告诉主动拥塞控制器你希望该服务类型启用时尽量减少往返延时(RTT)。该设置一般用" -"在 VoIP 或在线游戏这类需要低延时(Ping 值)的应用上。减小往返延时(RTT)会带" -"来WAN有效吞吐量的额外花销,所以当这些服务类型启用时你的 WAN 吞吐量将下降(通" -"常在20%左右)" - -msgid "Load" -msgstr "负载" - -msgid "Loading" -msgstr "正在加载" - -msgid "Manual Ping Limit" -msgstr "手动 Ping 限制" - -msgid "Maximum Bandwidth" -msgstr "最大带宽" - -msgid "Maximum Packet Length" -msgstr "最大数据包长度" - -msgid "Minimize RTT" -msgstr "最小往返延时" - -msgid "Minimum Bandwidth" -msgstr "最小带宽" - -msgid "Minimum Packet Length" -msgstr "最小数据包长度" - -msgid "No" -msgstr "否" - -msgid "No data found" -msgstr "无数据" - -msgid "None" -msgstr "无" - -msgid "Not set" -msgstr "未设置" - -msgid "" -"Packet's destination ip, can optionally have /[mask] after it (see -d option " -"in iptables man page)." -msgstr "" -"数据包的目标 IP,可以在后面加子网掩码(/[mask],请看 iptables 的 -d 参数说" -"明)" - -msgid "Packet's destination port, can be a range (eg. 80-90)." -msgstr "数据包的目标端口,可以是一个范围(例如:80-90)" - -msgid "Packet's maximum size (in bytes)." -msgstr "数据包的最大大小(单位:bytes)" - -msgid "Packet's minimum size (in bytes)." -msgstr "数据包的最小大小(单位:bytes)" - -msgid "" -"Packet's source ip, can optionally have /[mask] after it (see -s option in " -"iptables man page)." -msgstr "" -"数据包的源 IP,可以在后面加子网掩码(/[mask],请看 iptables 的 -s 参数说明)" - -msgid "Packet's source port, can be a range (eg. 80-90)." -msgstr "数据包的源端口,可以是一个范围(例如:80-90)" - -msgid "" -"Packets are tested against the rules in the order specified -- rules toward " -"the top have priority. As soon as a packet matches a rule it is classified, " -"and the rest of the rules are ignored. The order of the rules can be altered " -"using the arrow controls." -msgstr "" -"数据包将按规则中指定的顺序进行匹配 —— 靠上的规则优先进行匹配。一旦数据包匹配" -"一条规则那它将被归类,并且其余的规则将被忽略。使用上下箭头可调整规则的顺序。" - -msgid "Percent Bandwidth At Capacity" -msgstr "带宽占用百分比" - -msgid "QoS Switch" -msgstr "QoS 开关" - -msgid "" -"Quality of Service (QoS) provides a way to control how available bandwidth " -"is allocated." -msgstr "QoS 可以用来分配和控制可用带宽。" - -msgid "" -"Round trip ping times are compared against the ping limits. ACC controls the " -"link limit to maintain ping times under the appropriate limit. By default " -"ACC attempts to automatically select appropriate target ping limits for you " -"based on the link speeds you entered and the performance of your link it " -"measures during initialization. You cannot change the target ping time for " -"the minRTT mode but by entering a manual time you can control the target " -"ping time of the active mode. The time you enter becomes the increase in the " -"target ping time between minRTT and active mode. Leave empty to use the " -"default settings." -msgstr "" -"Ping 延时会与 Ping 限制进行比较。ACC 控制链路限制以保持 Ping 延时在适当范围。" -"默认情况下,ACC 会自动根据你输入的链接适当为你选择适当的 Ping 限制。如果你想" -"尝试不同的 Ping 限制,你可以在这里输入一个时间值。输入高的时间值将导致更高的 " -"Ping 限制,低的时间值会有更低的限制。留空则将由 ACC 自动控制。" - -msgid "Service Class" -msgstr "服务类型" - -msgid "Service Class Name" -msgstr "服务类型名称" - -msgid "Service Classes" -msgstr "服务类型" - -msgid "" -"Should be set to around 98% of your available upload bandwidth. Entering a " -"number which is too high will result in QoS not meeting its class " -"requirements. Entering a number which is too low will needlessly penalize " -"your upload speed. You should use a speed test program (with QoS off) to " -"determine available upload bandwidth. Note that bandwidth is specified in " -"kbps, leave blank to disable update QoS. There are 8 kilobits per kilobyte." -msgstr "" -"应被设置为你可用上传带宽的 98% 左右。输入数值太高将导致 QoS 不能匹配服务类型" -"的要求。输入数值太低将造成不必要的上传速度限制。你应当在 QoS 关闭的情况下使用" -"测速程序以确定可用的上传带宽。带宽以 kbps 为单位,留空以禁用上传 QoS。" -"(1KByte/s=8Kbps)" - -msgid "Source IP(s)" -msgstr "源 IP" - -msgid "Source Port(s)" -msgstr "源端口" - -msgid "Specifie how packets that do not match any rule should be classified." -msgstr "指定当数据包不匹配任何规则时将被如何归类。" - -msgid "" -"Specifying correctly is crucial to making QoS work. Note that bandwidth is " -"specified in kbps, leave blank to disable download QoS. There are 8 kilobits " -"per kilobyte." -msgstr "" -"正确设置对于 QoS 的工作至关重要。带宽以 kbps 为单位,留空以禁用下载 QoS。" -"(1KByte/s=8Kbps)" - -msgid "" -"The maximum amount of bandwidth this class will be allocated in kbit/s. Even " -"if unused bandwidth is available, this service class will never be permitted " -"to use more than this amount of bandwidth." -msgstr "" -"该服务类型可被分配的带宽最大值(以 kbit/s 为单位)。即使存在未使用带宽,该服" -"务类型也将永远不被允许使用超过此量的带宽。" - -msgid "" -"The minimum service this class will be allocated when the link is at " -"capacity. Classes which specify minimum service are known as realtime " -"classes by the active congestion controller. Streaming video, VoIP and " -"interactive online gaming are all examples of applications that must have a " -"minimum bandwith to function. To determine what to enter use the application " -"on an unloaded LAN and observe how much bandwidth it uses. Then enter a " -"number only slightly higher than this into this field. QoS will satisfiy the " -"minimum service of all classes first before allocating to other waiting " -"classes so be careful to use minimum bandwidths sparingly." -msgstr "" -"将被分配用于该服务类型的最低链路带宽容量。指定了最小带宽的服务类型会被主动拥" -"塞控制器看作实时类应用。例如视频流、VoIP 和在线互动游戏都应该设置最小带宽。要" -"确定需要多少最小带宽,可以在一个没有负载的局域网中使用应用程序并观察它使用了" -"多少带宽。然后输入一个略高于这个值的数字到字段中。在分配剩余带宽到其它服务类" -"型前,QoS 将优先满足所有服务类型的最小带宽要求,所以要谨慎地使用最小带宽。" - -msgid "" -"The percentage of the total available bandwidth that should be allocated to " -"this class when all available bandwidth is being used. If unused bandwidth " -"is available, more can (and will) be allocated. The percentages can be " -"configured to equal more (or less) than 100, but when the settings are " -"applied the percentages will be adjusted proportionally so that they add to " -"100. This setting only comes into effect when the WAN link is saturated." -msgstr "" -"当所有可用带宽被占满后该服务类型占据总带宽的百分比。如果带宽未用完,该服务类" -"型会被分配更多带宽。该百分比值可被设置为等于、大于或小于 100,但当设置被应用" -"时,百分比值将会被按比例调整以便使它们加起来等于 100。该设置只在 WAN 端链路饱" -"和时才生效。(PS:WAN 端链路饱和即带宽被占用完)" - -msgid "" -"The segment of network between your router and the ping target is where " -"congestion is controlled. By monitoring the round trip ping times to the " -"target congestion is detected. By default ACC uses your WAN gateway as the " -"ping target. If you know that congestion on your link will occur in a " -"different segment then you can enter an alternate ping target. Leave empty " -"to use the default settings." -msgstr "" -"在路由器和 Ping 目标之间的网络部分是拥塞控制的地方。拥塞通过监视和目标间的 " -"Ping 延时来检测。默认情况下 ACC 使用你的 WAN 网关作为 Ping 的目标。假如你知道" -"拥塞会在你链路的不同段发生,你可用输入一个备用的 Ping 目标。留空则将由ACC 自" -"动控制。" - -msgid "" -"The total size of data transmitted since the establishment of the link (in " -"kBytes)." -msgstr "自连接建立以来,传输的数据总量(单位:kBytes)" - -msgid "Total Download Bandwidth" -msgstr "下载总带宽" - -msgid "Total Upload Bandwidth" -msgstr "上传总带宽" - -msgid "Transport Protocol" -msgstr "协议" - -msgid "Troubleshooting" -msgstr "故障排除" - -msgid "Troubleshooting Data" -msgstr "故障排除数据" - -msgid "Unlimited" -msgstr "不限制" - -msgid "Upload Settings" -msgstr "上传设置" - -msgid "Use Non-standard Ping Target" -msgstr "使用自定义 Ping 目标" - -msgid "Zero" -msgstr "零" diff --git a/package/jsda/luci-app-qos-gargoyle/root/etc/uci-defaults/40_luci-qos-gargoyle b/package/jsda/luci-app-qos-gargoyle/root/etc/uci-defaults/40_luci-qos-gargoyle deleted file mode 100755 index 4f6cc1b41c..0000000000 --- a/package/jsda/luci-app-qos-gargoyle/root/etc/uci-defaults/40_luci-qos-gargoyle +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@qos_gargoyle[-1] - add ucitrack qos_gargoyle - set ucitrack.@qos_gargoyle[-1].init=qos_gargoyle - commit ucitrack -EOF - -/etc/init.d/qos_gargoyle stop -/etc/init.d/qos_gargoyle disable - -rm -rf /tmp/luci-modulecache /tmp/luci-indexcache -exit 0 diff --git a/package/jsda/openwrt-dnsforwarder/Makefile b/package/jsda/openwrt-dnsforwarder/Makefile index 92a12f44bc..25d31fafb3 100755 --- a/package/jsda/openwrt-dnsforwarder/Makefile +++ b/package/jsda/openwrt-dnsforwarder/Makefile @@ -1,6 +1,6 @@ include $(TOPDIR)/rules.mk -PKG_NAME:=openwrt-dnsforwarder +PKG_NAME:=dnsforwarder PKG_VERSION:=6 PKG_RELEASE:=3 @@ -15,7 +15,7 @@ PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz include $(INCLUDE_DIR)/package.mk -define Package/dnsforwarder +define Package/openwrt-dnsforwarder SECTION:=net CATEGORY:=Network TITLE:=A simple DNS forwarder diff --git a/package/jsda/qos-gargoyle/Makefile b/package/jsda/qos-gargoyle/Makefile deleted file mode 100644 index 5ac73beb96..0000000000 --- a/package/jsda/qos-gargoyle/Makefile +++ /dev/null @@ -1,66 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=qos-gargoyle -PKG_VERSION:=1.0.1 -PKG_RELEASE:=1 -PKG_LICENSE:=GPL-3.0+ -PKG_MAINTAINER:=Xingwang Liao - -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(INCLUDE_DIR)/package.mk - -define Package/qos-gargoyle - SECTION:=net - CATEGORY:=Gargoyle - SUBMENU:=Network - TITLE:=A set of QoS scripts - DEPENDS:=+tc +ip +kmod-sched +iptables-mod-filter +iptables-mod-ipopt +iptables-mod-imq - MAINTAINER:=Xingwang Liao - PKGARCH:=all -endef - -define Package/qos-gargoyle/description - A set of QoS scripts from Gargoyle -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ - $(call Build/Prepare/Default) -endef - -define Build/Configure -endef - -define Build/Compile - -$(MAKE) -C $(PKG_BUILD_DIR) clean - $(MAKE) -C $(PKG_BUILD_DIR) \ - $(TARGET_CONFIGURE_OPTS) \ - CFLAGS="$(TARGET_CFLAGS) -I $(STAGING_DIR)/usr/include" \ - LDFLAGS="$(TARGET_LDFLAGS) -L $(STAGING_DIR)/usr/lib" \ - BUILD_DIR="$(BUILD_DIR)" \ - all -endef - -define Package/qos-gargoyle/install - $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_DIR) $(1)/etc/hotplug.d/iface - $(INSTALL_DIR) $(1)/etc/config - - $(INSTALL_BIN) ./files/qos_gargoyle.init $(1)/etc/init.d/qos_gargoyle - $(INSTALL_BIN) ./files/qos_gargoyle.hotplug $(1)/etc/hotplug.d/iface/23-qos_gargoyle - $(INSTALL_DATA) ./files/qos_gargoyle.conf $(1)/etc/config/qos_gargoyle - - $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/qosmon $(1)/usr/sbin/qosmon -endef - -define Package/qos-gargoyle/prerm - #!/bin/sh - $${IPKG_INSTROOT}/etc/init.d/qos_gargoyle stop 2>/dev/null - $${IPKG_INSTROOT}/etc/init.d/qos_gargoyle disable 2>/dev/null - exit 0 -endef - -$(eval $(call BuildPackage,qos-gargoyle)) diff --git a/package/jsda/qos-gargoyle/files/example-qos-config2.conf b/package/jsda/qos-gargoyle/files/example-qos-config2.conf deleted file mode 100644 index e248b6b255..0000000000 --- a/package/jsda/qos-gargoyle/files/example-qos-config2.conf +++ /dev/null @@ -1,119 +0,0 @@ - -config global global - option mtu "1500" # the maximum allowed packet size (in bytes) on the interface being shaped - option network "wan" # the name of the network whose interface should have its outgoing traffic shaped - #option interface "eth1" # the name of the network interface which should have its outgoing traffic shaped - - -config upload upload - option total_bandwidth "600" # 600kbit/s - option default_class "uclass_2" # default traffic class, must be a section of type upload_class - - -config download download - option total_bandwidth "4000" # 4000kbit/s (500Kbyte/s) - option default_class "dclass_1" # default traffic class, must be a section of type download_class - - - - - - -#upload classes -config upload_class uclass_1 - option percent_bandwidth "40" # percent of total bandwidth to use - -config upload_class uclass_2 - option percent_bandwidth "20" # percent of total bandwidth to use - option max_bandwidth "30" # max bandwidth useage in absolute speed (kbit/s) - -config upload_class uclass_3 - option percent_bandwidth "30" # percent of total bandwidth to use - option min_bandwidth "160" # min bandwidth to allocate to this class - -config upload_class uclass_4 - option percent_bandwidth "10" # percent of total bandwidth to use - - - -#download classes -config download_class dclass_1 - option percent_bandwidth "30" # percent of total bandwidth to use - option min_bandwidth "80" # min bandwidth to allocate to this class - -config download_class dclass_2 - option percent_bandwidth "60" # percent of total bandwidth to use - -config download_class dclass_3 - option percent_bandwidth "10" # percent of total bandwidth to use - option min_bandwidth "80" # min bandwidth to allocate to this class - - -# classification rules -# -# POSSIBLE OPTIONS: -# class name of bandwidth class to use if rule matches, this is required in each rule section -# test_order an integer that specifies the order in which the rule should be checked for a match (lower numbers are checked first) -# proto check that packet has this protocol (tcp, udp, both), if port is specified default is both -# source check that packet has this source ip, can optionally have /[mask] after it (see -s option in iptables man page) -# destination check that packet has this destination ip, can optionally have /[mask] after it (see -d option in iptables man page) -# dport check that packet has this destination port -# sport check that packet has this source port -# min_pkt_size check that packet is at least this size (in bytes) -# max_pkt_size check that packet is no larger than this size (in bytes) -# layer7 check whether packet matches layer7 specification -# ipp2p check wither packet matches ipp2p specification (used to recognize p2p protocols) -# "ipp2p" or "all" will match any of the specified p2p protocols, you can -# also specifically match any protocol listed in the documentation here: -# http://ipp2p.org/docu_en.html -# -# sytnax for upload rules and download rules is identical -config upload_rule - option class "uclass_4" - option test_order "1" - option destination "195.56.146.238" - -config upload_rule - option class "uclass_3" - option test_order "2" - option proto "both" - option dstport "80-90" - -config upload_rule - option class "uclass_1" - option test_order "3" - option dstport "22" - -config upload_rule - option class "uclass_3" - option test_order "44" - option proto "udp" - option max_pkt_size "250" - -config upload_rule - option class "uclass_3" - option test_order "5" - option proto "udp" - option max_pkt_size "250" - -config upload_rule - option class "uclass_4" - option test_order "6" - option ipp2p "all" - -config upload_rule - option class "uclass_3" - option test_order "7" - option layer7 "pop3" - -#download rules -config download_rule - option class "dclass_2" - option test_order "1" - option dstport "80-90" - -config download_rule - option class "dclass_3" - option test_order "2" - option ipp2p "all" - diff --git a/package/jsda/qos-gargoyle/files/qos_gargoyle.conf b/package/jsda/qos-gargoyle/files/qos_gargoyle.conf deleted file mode 100644 index 9c281d0b07..0000000000 --- a/package/jsda/qos-gargoyle/files/qos_gargoyle.conf +++ /dev/null @@ -1,26 +0,0 @@ - -config upload 'upload' - option default_class 'uclass_2' - option total_bandwidth '1000' - -config download 'download' - option qos_monenabled 'true' - option total_bandwidth '10000' - option default_class 'dclass_1' - -config download_class 'dclass_1' - option name 'Normal' - option percent_bandwidth '100' - -config upload_class 'uclass_1' - option name 'Fast' - option percent_bandwidth '90' - -config upload_class 'uclass_2' - option name 'Normal' - option percent_bandwidth '10' - -config upload_rule 'upload_rule_100' - option class 'uclass_1' - option max_pkt_size '128' - diff --git a/package/jsda/qos-gargoyle/files/qos_gargoyle.hotplug b/package/jsda/qos-gargoyle/files/qos_gargoyle.hotplug deleted file mode 100644 index d36b15f870..0000000000 --- a/package/jsda/qos-gargoyle/files/qos_gargoyle.hotplug +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh - -[ "$ACTION" = "ifup" ] || [ "$ACTION" = "ifdown" ] || exit 0 - -. /lib/functions/network.sh - -wan_net_name= -network_find_wan wan_net_name - -if [ "$INTERFACE" = "$wan_net_name" ]; then - if [ -h /etc/rc.d/S50qos_gargoyle ]; then - if [ "$ACTION" = "ifup" ]; then - /etc/init.d/qos_gargoyle start $DEVICE - fi - fi - - if [ "$ACTION" = "ifdown" ]; then - /etc/init.d/qos_gargoyle stop - fi -fi diff --git a/package/jsda/qos-gargoyle/files/qos_gargoyle.init b/package/jsda/qos-gargoyle/files/qos_gargoyle.init deleted file mode 100644 index 2dc6055d33..0000000000 --- a/package/jsda/qos-gargoyle/files/qos_gargoyle.init +++ /dev/null @@ -1,771 +0,0 @@ -#!/bin/sh /etc/rc.common -# -# Copyright (c) 2008 Eric Bishop -# Copyright (c) 2016 GuoGuo -# Copyright (c) 2017 Xingwang Liao -# This is free software licensed under the terms of the GNU GPL v2.0 -# - -START=50 - -EXTRA_COMMANDS=show -EXTRA_HELP=" show Show current Qos configuration (if active)" - -config_file_name="qos_gargoyle" -upload_mask="0x007F" -download_mask="0x7F00" -qos_mark_file="/etc/qos_class_marks" - -# created while qos is being initialized so hotplug and init script don't -# both try to initialize qos at the same time -lock_file="/var/run/qos_updating" - -load_all_config_options() -{ - local config_name="$1" - local section_id="$2" - - ALL_OPTION_VARIABLES="" - # this callback loads all the variables - # in the section_id section when we do - # config_load. We need to redefine - # the option_cb for different sections - # so that the active one isn't still active - # after we're done with it. For reference - # the $1 variable is the name of the option - # and $2 is the name of the section - config_cb() - { - if [ ."$2" = ."$section_id" ]; then - option_cb() - { - ALL_OPTION_VARIABLES="$ALL_OPTION_VARIABLES $1" - } - else - option_cb() { return 0; } - fi - } - - config_load "$config_name" - - for var in $ALL_OPTION_VARIABLES - do - config_get "$var" "$section_id" "$var" - done -} - -load_all_config_sections() -{ - local config_name="$1" - local section_type="$2" - - all_config_sections="" - - get_section_names() - { - all_config_sections="$all_config_sections $1" - } - - config_load "$config_name" - config_foreach get_section_names "$section_type" - echo "$all_config_sections" -} - -get_classname_mark() -{ - local class="$1" - local class_mark_list="$2" - echo "$class_mark_list" | awk -v class="$class" '{ for (i = 1; i <= NF; i++){ if($i~class":"){ gsub(class":",""); print $i } }}' -} - -apply_all_rules() -{ - local rule_type="$1" - local class_mark_list="$2" - local chain="$3" - local table="$4" - - local need_proto - local tmp_proto - - # add filter rules - rule_list=$(load_all_config_sections "$config_file_name" "$rule_type") - for rule in $rule_list ; do - class="" - proto="" - min_pkt_size="" - max_pkt_size="" - match_str="" - need_proto="" - - load_all_config_options "$config_file_name" "$rule" - - for option in $ALL_OPTION_VARIABLES ; do - - option_value=$(eval echo \$$option) - case "$option" in - source) - if [ "$3" = "qos_egress" ] ; then - if [ "$option_value" = "$local_ip" ] || [ "$option_value" = "$wan_ip" ]; then - option_value="$wan_ip" - fi - fi - match_str="$match_str -s $option_value" - ;; - destination) - if [ "$3" = "qos_ingress" ] ; then - if [ "$option_value" = "$local_ip" ] || [ "$option_value" = "$wan_ip" ]; then - option_value="$wan_ip" - fi - fi - match_str="$match_str -d $option_value" - ;; - srcport) - if [ -n "$(echo $option_value | grep '-')" ] ; then option_value="$(echo "$option_value" | sed -e 's,-,:,g')" ; fi - match_str="$match_str --sport $option_value" - need_proto="1" - ;; - dstport) - if [ -n "$(echo $option_value | grep '-')" ] ; then option_value="$(echo "$option_value" | sed -e 's,-,:,g')" ; fi - match_str="$match_str --dport $option_value" - need_proto="1" - ;; - ndpi) - match_str="$match_str -m ndpi --$option_value" - ;; - connbytes_kb) - match_str="$match_str -m connbytes --connbytes $(($option_value*1024)): --connbytes-dir both --connbytes-mode bytes" - ;; - esac - done - - if [ -n "$min_pkt_size" ] || [ -n "$max_pkt_size" ] ; then - if [ -z "$min_pkt_size" ] ; then min_pkt_size=0 ; fi - if [ -z "$max_pkt_size" ] ; then max_pkt_size=1500 ; fi - match_str="$match_str -m length --length $min_pkt_size:$max_pkt_size" - fi - - if [ -n "$class" ] ; then - if [ -n "$proto" ] || [ -n "$match_str" ] ; then - next_mark=$(get_classname_mark "$class" "$class_mark_list" ) - - # We need to specify both udp and tcp if the user indicated a port - # and he did not indiate a protocal. - if [ -z "$proto" ] && [ -n "$need_proto" ] ; then - - $echo_on - iptables -t $table -I $chain -p tcp $match_str -j MARK --set-mark $next_mark - iptables -t $table -I $chain -p udp $match_str -j MARK --set-mark $next_mark - $echo_off - - else - - # Otherwise just specify what the user requested (or nothing) - - if [ -n "$proto" ] ; then - tmp_proto="-p $proto" - else - tmp_proto="" - fi - - $echo_on - iptables -t $table -I $chain $tmp_proto $match_str -j MARK --set-mark $next_mark - $echo_off - fi - - fi - fi - done -} - -update_markfile() -{ - - # initialize mark file in /tmp first, and test md5sum - # this should speed things up and prevent writing to flash unnecessarily (since /tmp is ramdisk) - - tmp_qos_mark_file="/tmp/qos_marks.tmp.tmp" - rm -rf "$tmp_qos_mark_file" - - # re-populate per the QoS setup. - if [ $total_upload_bandwidth -ge 0 ] ; then - - upload_class_list=$(load_all_config_sections "$config_file_name" "upload_class") - - next_class_index=2 - for uclass_name in $upload_class_list ; do - printf "upload $uclass_name %d $upload_mask\n" $next_class_index >> "$tmp_qos_mark_file" - next_class_index=$(($next_class_index+1)) - done - fi - - if [ $total_download_bandwidth -ge 0 ] ; then - - download_class_list=$(load_all_config_sections "$config_file_name" "download_class") - - next_class_index=2 - for dclass_name in $download_class_list ; do - printf "download $dclass_name %d $download_mask\n" $(($next_class_index << 8)) >> "$tmp_qos_mark_file" - next_class_index=$(($next_class_index+1)) - done - fi - - mark_files_match="0" - if [ -e "$qos_mark_file" ] ; then - new_md5=$(md5sum "$tmp_qos_mark_file" | awk '{ print $1 ; } ') - old_md5=$(md5sum "$qos_mark_file" | awk '{ print $1 ; } ') - if [ "$new_md5" = "$old_md5" ] ; then - mark_files_match="1" - fi - fi - - if [ "$mark_files_match" = "0" ] ; then - mv "$tmp_qos_mark_file" "$qos_mark_file" - else - rm -rf "$tmp_qos_mark_file" - fi -} - -module_installed() -{ - lsmod | grep -wq "$1" -} - -install_modules() -{ - for m in "$@"; do - module_installed $m || insmod $m >&- 2>&- - done -} - -initialize_qos() -{ - # Now, load/insert necessary kernel modules - # The following packages are required for the modules: - module_installed imq && rmmod imq >&- 2>&- - insmod imq numdevs=1 hook_chains="INPUT,FORWARD" hook_tables="mangle,mangle" >&- 2>&- - ip link set dev imq0 mtu 1500 - - install_modules cls_fw cls_flow sch_hfsc sch_sfq - - # Set the atm parameters if pppoe is being used. - wan_proto= - network_get_protocol wan_proto $wan_net_name - if [ "$wan_proto" = "pppoe" ] ; then - # On my PPPoE WAN link I see the following overhead - # MAC Header=14 & PPPoE=8 plus I read that an addition ATM=8 is added by the modem" - overhead="stab linklayer atm overhead 30 mtu 1492 tsize 128 " - # else - # Even for the ethernet cases I do not think the qdisc sees the MAC Header - # but for now leave this out. - # overhead="stab linklayer ethernet overhead 14 mpu 64" - fi - - # On low memory routers we need to take it easy on how big the queues can get. - # When depth is limited to 32 maximum bandwidth through any class will be around 11Mbps. - # Otherwise it will be around 350Mbps. - total_mem="$(sed -e '/^MemTotal: /!d; s#MemTotal: *##; s# kB##g' /proc/meminfo)" - if [ "$total_mem" -lt 16000 ] ; then - sfq_depth="depth 32" - else - sfq_depth="" - fi - - # load upload variables - load_all_config_options "$config_file_name" "upload" - if [ -n "$total_bandwidth" ] ; then - total_upload_bandwidth="$total_bandwidth" - else - total_upload_bandwidth=-1 - fi - - upload_default_class="$default_class" - - if [ $total_upload_bandwidth -ge 0 ] ; then - - # load upload classes - upload_class_list=$(load_all_config_sections "$config_file_name" "upload_class") - for uclass_name in $upload_class_list ; do - percent_bandwidth="" - min_bandwidth="" - max_bandwidth="" - load_all_config_options "$config_file_name" "$uclass_name" - if [ -z "$percent_bandwidth" ] ; then - percent_bandwidth="0" - fi - if [ -z "$min_bandwidth" ] ; then - min_bandwidth="-1" - fi - if [ -z "$max_bandwidth" ] ; then - max_bandwidth="-1" - fi - classdef="$percent_bandwidth $max_bandwidth $min_bandwidth" - eval $uclass_name=\"\$classdef\" #"#comment quote here so formatting in editor isn't FUBAR - done - - # Attach egress queuing discipline to QoS interface, now with temperary default - $echo_on - tc qdisc add dev $qos_interface root handle 1:0 hfsc default 1 - - # For the root qdisc, only ul is relevant, since there is no link sharing, and rt only applies to leaf qdiscs - # - # A detailed explanation of how/why ls is being set is warranted here... - # This is being set to max bandwidth possible on a connection (right now that's about 1Gbit, we can increase later if necessary) - # Only ratio of child ls rates is important -- bounding is done by the ul parameter, since hfsc takes min of ls and ul - # This means we can just multiply percents by 10 in child nodes to get what ls curves for each should be - # Again, for ls the ratios matter, but the absolute values do not, provided that they are all < than the ul for either the - # child or any of the parent nodes - # - tc class add dev $qos_interface parent 1:0 classid 1:1 hfsc ls rate 1000Mbit ul rate ${total_upload_bandwidth}kbit - $echo_off - - class_mark_list="" - upload_shift=0 - next_class_index=2 - next_classid=$(printf "0x%X" $(($next_class_index << $upload_shift)) ) - def_upload_idx=$next_class_index - def_upload_class=$next_classid - - for uclass_name in $upload_class_list ; do - - class_mark_list="$class_mark_list$uclass_name:$next_classid " - - uclass_def=$(eval echo "\$$uclass_name") - - # % bandwidth at capacity for this class - m2=$(( 10 * $(echo $uclass_def | awk ' {print $1}' ) )) - - # is there a minimum bandwidth specified in kbps? - min_bandwidth=$( echo $uclass_def | awk ' {print $3}' ) - ll_str="" - if [ "$min_bandwidth" -gt 0 ] ; then - ll_str=" rt m1 $((2*$min_bandwidth))kbit d 20ms m2 ${min_bandwidth}kbit" - fi - - # is there an upper limit specified in kbps? - max_bandwidth=$( echo $uclass_def | awk ' {print $2}' ) - ul_str="" - if [ "$max_bandwidth" -ge 0 ] ; then - ul_str=" ul m2 ${max_bandwidth}kbit" - else - max_bandwidth="$total_upload_bandwidth" - fi - - # tbw is the Delay x Bandwidth product in bytes per second. We do not actually know the packet - # delay so we make an estimate of 150ms here and hope for the best. max_bandwidth is in kbps - # we multiply 150ms by 1000 below so the units work out. - tbw=$(($max_bandwidth*150/8)); - if [ "$tbw" -lt 3000 ] ; then - tbw=3000 - fi - - # We will use the SFQ qdisc with flow classifier. The limit on the depth of our qdisc depends on the upper limit - # of the bandwidth allocated to this class. To impliment per IP sharing of the class we use the flow classifier - # and the 'nfct-src' on the upload side and 'dst' on the download side. I found a nice man page here - # https://arndtroide.homelinux.org/cgi-bin/man/man2html?tc-sfq+8 - $echo_on - - # Add the leaf class - tc class add dev $qos_interface parent 1:1 classid 1:$next_class_index hfsc ls m2 ${m2}Mbit $ll_str $ul_str - # Add the qdisc to the leaf class, assuming average packet at 500 bytes. - tc qdisc add dev $qos_interface parent 1:$next_class_index handle $next_class_index:1 sfq headdrop limit $(($tbw/500)) $sfq_depth divisor 256 - # Add a filter to the root class to direct packets to this leaf class according to the conntrack mark - tc filter add dev $qos_interface parent 1:0 protocol ip handle $next_classid fw flowid 1:$next_class_index - # Add a filter to the leaf class to define flows as being the source IP address. - tc filter add dev $qos_interface parent $next_class_index: handle 1 flow divisor 256 map key nfct-src and 0xff - $echo_off - - if [ "$upload_default_class" = "$uclass_name" ] ; then - def_upload_idx=$next_class_index - def_upload_class=$next_classid - fi - - next_class_index=$(($next_class_index+1)) - next_classid=$(printf "0x%X" $(($next_class_index << $upload_shift)) ) - done - - $echo_on - - # Go back and touch up the root qdisc to have the proper default class - tc qdisc change dev $qos_interface $overhead root handle 1:0 hfsc default $def_upload_idx - - # Set up egress chain - iptables -t mangle -N qos_egress - iptables -t mangle -A POSTROUTING -o $qos_interface -j qos_egress - - # Next the user entered rules. - $echo_off - apply_all_rules "upload_rule" "$class_mark_list" "qos_egress" "mangle" - $echo_on - - # set default class mark first in case we don't match anything - iptables -t mangle -I qos_egress -j MARK --set-mark $def_upload_class - - # if we already set a mark in quota chain, we need to save that mark to the connmark, then return so it doesn't get over-written - iptables -t mangle -I qos_egress -m mark ! --mark 0x0 -j RETURN - iptables -t mangle -I qos_egress -m mark ! --mark 0x0 -j CONNMARK --save-mark --mask $upload_mask - - # save current mark to connmark at end of chain - iptables -t mangle -A qos_egress -j CONNMARK --save-mark --mask $upload_mask - - $echo_off - - fi - - # load download variables - total_bandwidth="" - default_class="" - load_all_config_options "$config_file_name" "download" - if [ -n "$total_bandwidth" ] ; then - total_download_bandwidth="$total_bandwidth" - else - total_download_bandwidth=-1 - fi - download_default_class="$default_class" - - # Only if both upload and download QoS are enabled can we enable Gargoyle active QoS monitor - if [ $total_download_bandwidth -eq 0 ] || [ $total_upload_bandwidth -eq 0 ] ; then - qos_monenabled="false" ; - fi - - if [ $total_download_bandwidth -ge 0 ] ; then - # Set up the InterMediate Queuing device (IMQ) - ip link set imq0 up - - # Attach ingress queuing discipline to IMQ interface - tc qdisc add dev imq0 root handle 1:0 hfsc default 1 - - tc class add dev imq0 parent 1:0 classid 1:1 hfsc ls rate 1000Mbit ul rate ${total_download_bandwidth}kbit - - # load download classes - download_class_list=$(load_all_config_sections "$config_file_name" "download_class") - for dclass_name in $download_class_list ; do - percent_bandwidth="" - min_bandwidth="" - max_bandwidth="" - minRTT="" - - load_all_config_options "$config_file_name" "$dclass_name" - if [ -z "$percent_bandwidth" ] ; then - percent_bandwidth="0" - fi - if [ -z "$min_bandwidth" ] ; then - min_bandwidth="-1" - fi - if [ -z "$max_bandwidth" ] ; then - max_bandwidth="-1" - fi - - classdef="$percent_bandwidth $max_bandwidth $min_bandwidth $minRTT" - eval $dclass_name=\"\$classdef\" #"#comment quote here so formatting in editor isn't FUBAR - done - - class_mark_list="" - download_shift=8 - next_class_index=2 - next_classid=$(printf "0x%X" $(($next_class_index << $download_shift)) ) - def_download_idx=$next_class_index - def_download_class=$next_classid - - for dclass_name in $download_class_list ; do - - class_mark_list="$class_mark_list$dclass_name:$next_classid " - dclass_def=$(eval echo "\$$dclass_name") - - # bandwidth for this class - m2=$(( 10 * $(echo $dclass_def | awk ' {print $1}' ) )) - - # The Gargoyle ACC switches from optimum WAN utilization mode to minimum RTT mode - # when it detects a class has become active that includes a two part service curve. - # So to trigger this behaviour we create two parts curves when minRTT is set. - - minRTT=$( echo $dclass_def | awk ' {print $4}' ) - if [ "$minRTT" = "Yes" ] ; then - ll_str=" ls m1 ${m2}Mbit d 20ms m2 ${m2}Mbit" - else - ll_str=" ls m2 ${m2}Mbit" - fi - - # is there a minimum bandwidth specified? - min_bandwidth=$( echo $dclass_def | awk ' {print $3}' ) - rt_str="" - if [ "$min_bandwidth" -gt 0 ] ; then - if [ "$minRTT" = "Yes" ] ; then - rt_str=" rt m1 $((2*$min_bandwidth))kbit d 20ms m2 ${min_bandwidth}kbit" - else - rt_str=" rt m2 ${min_bandwidth}kbit" - fi - fi - - # is there an upper limit specified? - max_bandwidth=$( echo $dclass_def | awk ' {print $2}' ) - ul_str="" - if [ "$max_bandwidth" -ge 0 ] ; then - ul_str=" ul m2 ${max_bandwidth}kbit" - else - max_bandwidth="$total_download_bandwidth" - fi - - tbw=$(($max_bandwidth*150/8)); - if [ "$tbw" -lt 5000 ] ; then - tbw=5000 - fi - - $echo_on - tc class add dev imq0 parent 1:1 classid 1:$next_class_index hfsc $rt_str $ll_str $ul_str - # Assume average download packet size is 1000 bytes. - tc qdisc add dev imq0 parent 1:$next_class_index handle $next_class_index:1 sfq headdrop limit $(($tbw/1000)) $sfq_depth divisor 256 - tc filter add dev imq0 parent 1:0 prio $next_class_index protocol ip handle $next_classid fw flowid 1:$next_class_index - tc filter add dev imq0 parent $next_class_index: handle 1 flow divisor 256 map key dst and 0xff - $echo_off - - if [ "$download_default_class" = "$dclass_name" ] ; then - def_download_idx=$next_class_index - def_download_class=$next_classid - fi - - next_class_index=$(($next_class_index+1)) - next_classid=$(printf "0x%X" $(($next_class_index << $download_shift)) ) - done - - $echo_on - - # Go back and touch up the root qdisc to have the proper default class - tc qdisc change dev imq0 $overhead root handle 1:0 hfsc default $def_download_idx - - # Create ingress chain - iptables -t mangle -N qos_ingress - - # Mark ingress in FORWARD and INPUT chains to make sure any DNAT (virt. server) is taken into account - iptables -t mangle -A FORWARD -i $qos_interface -j qos_ingress - iptables -t mangle -A INPUT -i $qos_interface -j qos_ingress - - # Now the rest of the user entered rules. - $echo_off - apply_all_rules "download_rule" "$class_mark_list" "qos_ingress" "mangle" "$download_mask" - $echo_on - - # set default class mark first in case we don't match anything - iptables -t mangle -I qos_ingress -j MARK --set-mark $def_download_class - - # if we already set a mark in quota chain, we need to save that mark to the connmark, then return so it doesn't get over-written - iptables -t mangle -I qos_ingress -m mark ! --mark 0x0 -j RETURN - iptables -t mangle -I qos_ingress -m mark ! --mark 0x0 -j CONNMARK --save-mark --mask $download_mask - - # make sure all packets get sent through IMQ - iptables -t mangle -I qos_ingress -j IMQ --todev 0 - - # save current mark to connmark at end of chain - iptables -t mangle -A qos_ingress -j CONNMARK --save-mark --mask $download_mask - - $echo_off - - fi - - # Enable Gargoyle active QoS monitor - if [ $total_upload_bandwidth -ge 0 ] && [ $total_download_bandwidth -ge 0 ] && [ "$qos_monenabled" = "true" ] ; then - - $echo_on - - # if the user specified a ping target then use that otherwise use the gateway. - if [ -z "$ptarget_ip" ] ; then - old_ifs="$IFS" - IFS=$(printf "\n\r") - targets=$(traceroute -n -I -w 1 -q 2 -m6 100.100.100.100 | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}.*ms' | grep -v '8.8.8.8' | sed 's/ms//g') - ptarget_ip="" - for t in $targets ; do - if [ -z "$ptarget_ip" ] ; then - # ip of potential gateway - target=$(echo "$t" | awk '{ print $1 ; }') - target_is_local=$(echo "$target" | grep -E '^(192\.168|10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.|0\.0\.0\.0|127\.|255\.)') - - - # round or rather ceil() time up to nearest millisecond since bash doesn't like working with decimals - time=$(echo "$t" | awk ' { print $3 ; }' | sed 's/\..*$//g') - time=$(( $time + 1 )) - - if [ -z "$target_is_local" ] || [ "$time" -gt 5 ] ; then - ptarget_ip="$target" - fi - fi - done - IFS="$old_ifs" - - # in case ping target is still not defined use default gateway - if [ -z "$ptarget_ip" ] ; then - network_get_gateway ptarget_ip $wan_net_name - fi - fi - - # Ping responses for the ping target never go to the IMQ device. - iptables -t mangle -I qos_ingress -p icmp --icmp-type 0 -d $wan_ip -s $ptarget_ip -j RETURN - - # Make a class to handle the outgoing ping requests from the router. - # These pings 84 bytes each for ethernet plus 22 more for PPPoE connections, allowing a maximum rate of 200ms we get 2.6kbps - tc class add dev $qos_interface parent 1:1 classid 1:127 hfsc rt umax 106 dmax 10ms rate 4kbit - tc qdisc add dev $qos_interface parent 1:127 pfifo - tc filter add dev $qos_interface parent 1:0 prio 1 protocol ip handle 127 fw flowid 1:127 - - # Mark all ping requests from the router to the ptarget to the above special class overriding any other mark. - iptables -t mangle -I qos_egress -p icmp --icmp-type 8 -s $wan_ip -d $ptarget_ip -j MARK --set-mark 127 - - # Start the monitor - if [ -n "$pinglimit" ] ; then - # In manual mode the user selects the active mode pinglimit indirectly. qosmon always measures the RTT of a ping on an unloaded link. - # This is called the ping entitlement. With a manual entry the minRTT ping limit is 110% of this measured ping entitlement - # and the active mode ping limit is the minRTT limit plus the user entered value. See the qosmon source code for more details. - # In summary manaully entered ping times only affect the active mode, not the minRTT mode ping time limits. - qosmon -a -b 800 $ptarget_ip $total_download_bandwidth $pinglimit - else - # In auto mode we calculate transmission delay based on our bandwidth and then ask qosmon - # to add this value to its measured ping entitlement to form the final ping limit. - pinglimit=$((1500*10*2/3/$total_download_bandwidth+1500*10/$total_upload_bandwidth+2)) - qosmon -a -b 800 $ptarget_ip $total_download_bandwidth $pinglimit - fi - - $echo_off - fi - - update_markfile -} - -define_interface() -{ - . /lib/functions/network.sh - - # Wait for up to 15 seconds for the wan interface to indicate it is up. - wan_net_name="" - network_find_wan wan_net_name - wait_sec=15 - while [ -z "$wan_net_name" ] && [ $wait_sec -gt 0 ] ; do - sleep 1 - wait_sec=$(($wait_sec - 1)) - network_find_wan wan_net_name - done - - if [ -z "$wan_net_name" ] ; then - echo "Network is not available." - exit 1 - fi - - qos_interface="" - wan_ip="" - local_ip="" - network_get_device qos_interface $wan_net_name - network_get_ipaddr wan_ip $wan_net_name - network_get_ipaddr local_ip lan -} - -ipt_delete_rule() -{ - local table=$1 - local delete_chain=$2 - local lines - lines=$(iptables -t $table -nL $delete_chain --line-numbers | grep $3 | awk '{print $1}') - for n in $lines ; do - iptables -t $table -D $delete_chain $n 2>/dev/null - done -} - -stop() -{ - # if already in process of being initialized, do not continue - # until that is finished, and then exit cleanly, without - # doing anything further - if [ -e "$lock_file" ] ; then - while [ -e "$lock_file" ] ; do - sleep 1 - done - exit - fi - - # Kill the qos monitor in case it is running - killall qosmon 2>/dev/null - - $echo_on - for iface in $(tc qdisc show | grep hfsc | awk '{print $5}'); do - tc qdisc del dev "$iface" root - done - - # eliminate existing rules in mangle table - ipt_delete_rule "mangle" "POSTROUTING" "qos_egress" - ipt_delete_rule "mangle" "FORWARD" "qos_ingress" - ipt_delete_rule "mangle" "INPUT" "qos_ingress" - iptables -t mangle -F qos_ingress 2>/dev/null - iptables -t mangle -F qos_egress 2>/dev/null - iptables -t mangle -X qos_ingress 2>/dev/null - iptables -t mangle -X qos_egress 2>/dev/null - $echo_off -} - -start() -{ - test_total_up=$(uci -q get qos_gargoyle.upload.total_bandwidth) - test_total_down=$(uci -q get qos_gargoyle.download.total_bandwidth) - if [ -z "$test_total_up" ] && [ -z "$test_total_down" ] ;then - disable - exit 0 - fi - - # This script is called by a hotplug event. If the WAN comes - # up fast we could end up trying to run qos_gargoyle while the - # boot is still in progress which causes issues in low memory - # routers. To avoid this we check to see if rcS is still running - # or not. If it is we wait until it completes or 60 seconds. - cnt=0 - while ps | grep '[//]rcS S boot' >/dev/null - do - sleep 4 - cnt=`expr $cnt + 1` - if [ $cnt -ge 15 ] ; then - break; - fi - done - - stop - touch "$lock_file" - - # load qos_interface from global variables - define_interface - if [ -n "$qos_interface" ] ; then - load_all_config_options "$config_file_name" "global" - initialize_qos - fi - - rm -rf "$lock_file" -} - -restart() -{ - echo_on="set -x" - echo_off="set +x" - start -} - -show() -{ - # load global variables - load_all_config_options "$config_file_name" "global" - - # load qos_interface from global variables - define_interface - - echo "Egress configuration on $qos_interface" - iptables -t mangle -vnL qos_egress 2>/dev/null - tc -s qdisc show dev $qos_interface - tc -s class show dev $qos_interface - tc -s filter show dev $qos_interface - - echo "Ingress configuration in imq0" - iptables -t mangle -vnL qos_ingress 2>/dev/null - tc -s qdisc show dev imq0 - tc -s class show dev imq0 - tc -s filter show dev imq0 - tc -s filter show dev imq0 parent 2: -} - -boot() -{ - # Do nothing during init. Start is called by hotplug. - return 0 -} diff --git a/package/jsda/qos-gargoyle/patches/001-musl-fixes.patch b/package/jsda/qos-gargoyle/patches/001-musl-fixes.patch deleted file mode 100644 index 1aac736677..0000000000 --- a/package/jsda/qos-gargoyle/patches/001-musl-fixes.patch +++ /dev/null @@ -1,47 +0,0 @@ ---- a/Makefile -+++ b/Makefile -@@ -21,7 +21,7 @@ qosmon: qosmon.o - $(CC) $(LDFLAGS) $^ $(TCOBJS) -o $@ $(LDLIBS) - - qosmon.o: qosmon.c -- $(CC) -D ONLYBG $(CFLAGS) -I $(TCDIR)/include -I $(TCDIR)/tc -c $^ -o $@ -+ $(CC) -D ONLYBG -D_GNU_SOURCE $(CFLAGS) -I $(TCDIR)/include -I $(TCDIR)/tc -c $^ -o $@ - - install: all uninstall - -mkdir -p $(BINDIR) ---- a/qosmon.c -+++ b/qosmon.c -@@ -34,6 +34,8 @@ - #include - #include - #include -+#include -+#include - - #include "utils.h" - #include "tc_util.h" -@@ -62,12 +64,13 @@ - //after then and define dump_filter and talk accordingly. - #ifdef RTNL_FAMILY_MAX - #define dump_filter(a,b,c) rtnl_dump_filter(a,b,c) --#define talk(a,b,c,d,e) rtnl_talk(a,b,c,d,e) -+#define talk(a,b,c) rtnl_talk(a,b,c) - #else - #define dump_filter(a,b,c) rtnl_dump_filter(a,b,c,NULL,NULL) --#define talk(a,b,c,d,e) rtnl_talk(a,b,c,d,e,NULL,NULL) -+#define talk(a,b,c) rtnl_talk(a,b,c,NULL,NULL) - #endif - -+#define __sighandler_t sighandler_t - - /* use_names is required when linking to tc_util.o */ - bool use_names = false; -@@ -630,7 +633,7 @@ int tc_class_modify(__u32 rate) - } - - -- if (talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (talk(&rth, &req.n, NULL) < 0) - return 2; - - return 0; diff --git a/package/jsda/qos-gargoyle/src/Makefile b/package/jsda/qos-gargoyle/src/Makefile deleted file mode 100644 index d69b576521..0000000000 --- a/package/jsda/qos-gargoyle/src/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -BINDIR = /usr/sbin -#TCDIR:=$(BUILD_DIR)/iproute2-full/ip* -TCDIR:=$(shell if [ -e "${BUILD_DIR}/iproute2-full" ] ; then echo "${BUILD_DIR}/iproute2-full"/ip* ; else echo "${BUILD_DIR}/iproute2-tiny"/ip* ; fi ; ) - -#The ncurses library only needed if we remove the ONLYBG switch -#below. Mostly for debug -#LDLIBS += -lncurses - -LDLIBS += -lm - -TCOBJS := $(TCDIR)/tc/tc_util.o -TCOBJS += $(TCDIR)/tc/tc_core.o -TCOBJS += $(TCDIR)/tc/q_hfsc.o -TCOBJS += $(TCDIR)/lib/libnetlink.a -TCOBJS += $(TCDIR)/lib/libutil.a -LDFLAGS += -Wl,-export-dynamic - -all: qosmon - -qosmon: qosmon.o - $(CC) $(LDFLAGS) $^ $(TCOBJS) -o $@ $(LDLIBS) - -qosmon.o: qosmon.c - $(CC) -D ONLYBG $(CFLAGS) -I $(TCDIR)/include -I $(TCDIR)/tc -c $^ -o $@ - -install: all uninstall - -mkdir -p $(BINDIR) - cp qosmon $(BINDIR) - -uninstall: - rm -f $(BINDIR)/qosmon - -clean: - rm -rf *.o *~ .*sw* qosmon - diff --git a/package/jsda/qos-gargoyle/src/qosmon.c b/package/jsda/qos-gargoyle/src/qosmon.c deleted file mode 100644 index 38a6131e68..0000000000 --- a/package/jsda/qos-gargoyle/src/qosmon.c +++ /dev/null @@ -1,1246 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ -/* qosmon - An active QoS monitor for gargoyle routers. - * Created By Paul Bixel - * http://www.gargoyle-router.com - * - * Copyright © 2010 by Paul Bixel - * - * This file is free software: you may copy, redistribute 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 file 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 -#include -#include -#include -#include -#include - -#include "utils.h" -#include "tc_util.h" -#include "tc_common.h" - -#include -#include -#include - -#ifndef ONLYBG -#include -#endif - - -#define MAXPACKET 100 /* max packet size */ -#define BACKGROUND 3 /* Detact and run in the background */ -#define ADDENTITLEMENT 4 - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -//The number of arguments needed for two of our kernel calls changed -//in iproute2 after v2.6.29 (not sure when). We will use the new define -//RTNL_FAMILY_MAX to tell us that we are linking against a version of iproute2 -//after then and define dump_filter and talk accordingly. -#ifdef RTNL_FAMILY_MAX -#define dump_filter(a,b,c) rtnl_dump_filter(a,b,c) -#define talk(a,b,c,d,e) rtnl_talk(a,b,c,d,e) -#else -#define dump_filter(a,b,c) rtnl_dump_filter(a,b,c,NULL,NULL) -#define talk(a,b,c,d,e) rtnl_talk(a,b,c,d,e,NULL,NULL) -#endif - - -/* use_names is required when linking to tc_util.o */ -bool use_names = false; - - -u_char packet[MAXPACKET]; -int pingflags, options; - -#define DEAMON (pingflags & BACKGROUND) - -struct rtnl_handle rth; - -int s; /* Socket file descriptor */ -struct hostent *hp; /* Pointer to host info */ -struct timezone tz; /* leftover */ - -struct sockaddr_in whereto;/* Who to ping */ -int datalen=64-8; /* How much data */ - -const char usage[] = -"Gargoyle active congestion controller version 2.3\n\n" -"Usage: qosmon [options] pingtime pingtarget bandwidth [pinglimit]\n" -" pingtime - The ping interval the monitor will use when active in ms.\n" -" pingtarget - The URL or IP address of the target host for the monitor.\n" -" bandwidth - The maximum download speed the WAN link will support in kbps.\n" -" pinglimit - Optional pinglimit to use for control, otherwise measured.\n" -" Options:\n" -" -b - Run in the background\n" -" -a - Add entitlement to pinglimt, enable auto ACTIVE/MINRTT mode switching.\n\n" -" SIGUSR1 can be used to reset the link bandwidth at anytime.\n"; - -char *hostname; -char hnamebuf[MAXHOSTNAMELEN]; - -uint16_t ntransmitted = 0; /* sequence # for outbound packets = #sent */ -uint16_t ident; -uint16_t nreceived = 0; /* # of packets we got back */ - -// For our digital filters we use Y = Y(-1) + alpha * (X - Y(-1)) -// where alpha = Sample_Period / (TC + Sample_Period) - -int fil_triptime; //Filter ping times in uS -int alpha; //Actually alpha * 1000 -int period; //PING period In milliseconds -int rawfltime; //Trip time in milliseconds -int rawfltime_max; //The maximum measured ping time we have seen in uS. -char nopingresponse; //Set to true when ping response is dropped. - - -// Struct of data we keep on our classes -struct CLASS_STATS { - int ID; //Class leaf ID - __u64 bytes; //Work bytes last query - u_char rtclass; //True if class is realtime. - u_char backlog; //Number of packets waiting - u_char actflg; //True if class is active. - long int cbw_flt; //Class bandwidth subject to filter. (bps) - long int cbw_flt_rt; //Class realtime bandwidth subject to filter. (bps) - long bwtime; //Timestamp of last byte reading. -}; - -#define STATCNT 30 -struct CLASS_STATS dnstats[STATCNT]; -struct CLASS_STATS *classptr; -u_char classcnt; -u_char errorflg; -u_char firstflg=1; //First pass flag - -u_char DCA; //Number of download classes active -u_char RTDCA; //Number of realtime download classes active -u_char pingon=0; //Set to one when pinger becomes active. -int pinglimit=0; //MinRTT mode ping time. -int pinglimit_cl=0; //Ping limit entered on the commandline. -int plimit; //Currently enforce ping limit - -float BWTC; //Time constant of the bandwidth filter -int DBW_UL; //This the absolute limit of the link passed in as a parameter. -int dbw_ul; //This is the last value of the limit sent to the kernel. -int new_dbw_ul; //The new link limit proposed by the state machine. -int saved_active_limit; //The new link limit last known to work with active mode. -int saved_realtime_limit;//The new link limit last known to work with realtime mode. -long int dbw_fil; //Filtered total download load (bps). - -#define QMON_CHK 0 -#define QMON_INIT 1 -#define QMON_ACTIVE 2 -#define QMON_REALTIME 3 -#define QMON_IDLE 4 -#define QMON_EXIT 5 -char *statename[]= {"CHECK","INIT","ACTIVE","MINRTT","IDLE","DISABLED"}; -unsigned char qstate=QMON_CHK; - -u_short cnt_mismatch=0; -u_short cnt_errorflg=0; -u_short last_errorflg=0; - -FILE *statusfd; //Filestream for updating our status to. -char sigterm=0; //Set when we get a signal to terminal -int sel_err=0; //Last error code returned by select - -#define DAEMON_NAME "qosmon" - -#ifndef DEVICE -#define DEVICE "imq0" -#endif - -#define EXIT_SUCCESS 0 -#define EXIT_FAILURE 1 - -/* In a world were size is everything we can avoid linking to libm - if we can come up with replacements for rint() and ceil(). This will - save around 64k of RAM. - - rint() is used in tc_util.c in five places. By code inspection I can see that - the parameter x will always be less than or equal to LONG_MAX so the following - simplified rint() will work for us. -*/ -double rint(double x) -{ - long i; - if (x > LONG_MAX) i = LONG_MAX; else i = x+.5; - return i; -} - -/* ceil() is used in q_hfsc.c in three places. There I can see that x is always - positive and less than LONG_MAX. This leads to a much simplified routine. -*/ -double ceil(double x) -{ - long i; - - if (x > LONG_MAX) x = LONG_MAX; - i = x; - if ((double)i != x) i++; - return i; -} - - - -/* - * F I N I S H - * - * Sets a global to cause the main loop to terminate. - */ -void finish(int parm) -{ - sigterm=parm; -} - -/* - * I N _ C K S U M - * - * Checksum routine for Internet Protocol family headers (C Version) - * - */ -int in_cksum(u_short *addr, int len) -{ - int nleft = len; - u_short *w = addr; - u_short answer; - int sum = 0; - - /* - * Our algorithm is simple, using a 32 bit accumulator (sum), - * we add sequential 16 bit words to it, and at the end, fold - * back all the carry bits from the top 16 bits into the lower - * 16 bits. - */ - while( nleft > 1 ) { - sum += *w++; - nleft -= 2; - } - - /* mop up an odd byte, if necessary */ - if( nleft == 1 ) { - u_short u = 0; - - *(u_char *)(&u) = *(u_char *)w ; - sum += u; - } - - /* - * add back carry outs from top 16 bits to low 16 bits - */ - sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ - sum += (sum >> 16); /* add carry */ - answer = ~sum; /* truncate to 16 bits */ - return (answer); -} - -/* - * P I N G E R - * - * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet - * will be added on by the kernel. The ID field is our UNIX process ID, - * and the sequence number is an ascending integer. The first 8 bytes - * of the data portion are used to hold a UNIX "timeval" struct in VAX - * byte-order, to compute the round-trip time. - */ -void pinger(void) -{ - static u_char outpack[MAXPACKET]; - struct icmp *icp = (struct icmp *) outpack; - int i, cc; - struct timeval *tp = (struct timeval *) &outpack[8]; - u_char *datap = &outpack[8+sizeof(struct timeval)]; - - icp->icmp_type = ICMP_ECHO; - icp->icmp_code = 0; - icp->icmp_cksum = 0; - icp->icmp_seq = ++ntransmitted; - icp->icmp_id = ident; /* ID */ - - cc = datalen+8; /* skips ICMP portion */ - - gettimeofday( tp, &tz ); - - for( i=8; iicmp_cksum = in_cksum( (u_short *) icp, cc ); - - /* cc = sendto(s, msg, len, flags, to, tolen) */ - i = sendto( s, outpack, cc, 0, (const struct sockaddr *) &whereto, sizeof(whereto) ); - -} - - -/* - * T V S U B - * - * Subtract 2 timeval structs: out = out - in. - * - * Out is assumed to be >= in. - */ -void tvsub(register struct timeval *out, register struct timeval *in) -{ - if( (out->tv_usec -= in->tv_usec) < 0 ) { - out->tv_sec--; - out->tv_usec += 1000000; - } - out->tv_sec -= in->tv_sec; -} - -/* - * P R _ P A C K - * - * Print out the packet, if it came from us. This logic is necessary - * because ALL readers of the ICMP socket get a copy of ALL ICMP packets - * which arrive ('tis only fair). This permits multiple copies of this - * program to be run without having intermingled output (or statistics!). - */ -char pr_pack( void *buf, int cc, struct sockaddr_in *from ) -{ - struct ip *ip; - struct icmp *icp; - struct timeval tv; - struct timeval *tp; - int hlen,triptime; - struct in_addr tip; - - from->sin_addr.s_addr = ntohl( from->sin_addr.s_addr ); - gettimeofday( &tv, &tz ); - - ip = (struct ip *) buf; - hlen = ip->ip_hl << 2; - if (cc < hlen + ICMP_MINLEN) { - tip.s_addr = ntohl(*(uint32_t *) &from->sin_addr); - return 0; - } - - icp = (struct icmp *)(buf + hlen); - if( icp->icmp_type != ICMP_ECHOREPLY ) { - tip.s_addr = ntohl(*(uint32_t *) &from->sin_addr); - return 0; - } - - if( icp->icmp_id != ident ) - return 0; /* 'Twas not our ECHO */ - - nreceived++; - - //If it was not the packet we are looking for return now. - if (icp->icmp_seq != ntransmitted) return 0; - - tp = (struct timeval *)&icp->icmp_data[0]; - tvsub( &tv, tp ); - triptime = tv.tv_sec*1000+(tv.tv_usec/1000); - - //We are now ready to update the filtered round trip time. - //Check for some possible errors first. - if (triptime > period) triptime = period; - - //If this was the most recent one we sent then update the rawfltime. - rawfltime=triptime; - - //Is this a new maximum? - if (rawfltime > rawfltime_max/1000) rawfltime_max = rawfltime*1000; - - //return 1 if we got a valid time. - return 1; - -} - -//These variables referenced but not used by the tc code we link to. -int filter_ifindex; -int use_iec = 0; -int resolve_hosts = 0; - - -int print_class(const struct sockaddr_nl *who, - struct nlmsghdr *n, void *arg) -{ - struct tcmsg *t = NLMSG_DATA(n); - int len = n->nlmsg_len; - struct rtattr * tb[TCA_MAX+1]; - int leafid; - u_char actflg=0; - unsigned long long work=0; - struct timespec newtime; - - if (n->nlmsg_type != RTM_NEWTCLASS && n->nlmsg_type != RTM_DELTCLASS) { - fprintf(stderr, "Not a class\n"); - return 0; - } - len -= NLMSG_LENGTH(sizeof(*t)); - if (len < 0) { - fprintf(stderr, "Wrong len %d\n", len); - return -1; - } - - memset(tb, 0, sizeof(tb)); - parse_rtattr(tb, TCA_MAX, TCA_RTA(t), len); - clock_gettime(CLOCK_MONOTONIC,&newtime); - - if (tb[TCA_KIND] == NULL) { - fprintf(stderr, "print_class: NULL kind\n"); - return -1; - } - - if (n->nlmsg_type == RTM_DELTCLASS) return 0; - - //We only deal with hfsc classes. - if (strcmp((char*)RTA_DATA(tb[TCA_KIND]),"hfsc")) return 0; - - //Reject the root node - if (t->tcm_parent == TC_H_ROOT) return 0; - - //A previous error backs us out. - if (errorflg) return 0; - - //If something has changed about the class structure or we reached the - //end of the array we need to reset and back out. - if (classcnt >= STATCNT) { - errorflg=1; - return 0; - } - - //Get the leafid or set to -1 if parent. - if (t->tcm_info) leafid = t->tcm_info>>16; - else leafid = -1; - - //If this is not the first pass and the leafid does not - //match then the class list changed so backout. - if ((!firstflg) && (leafid != classptr->ID) ) { - errorflg=1; - return 0; - } - - //First time through so record the ID. - if (firstflg) { - classptr->ID = leafid; - } - - //Pickup some hfsc basic stats - if (tb[TCA_STATS2]) { - - struct tc_stats st; - - /* handle case where kernel returns more/less than we know about */ - memset(&st, 0, sizeof(st)); - memcpy(&st, RTA_DATA(tb[TCA_STATS]), MIN(RTA_PAYLOAD(tb[TCA_STATS]), sizeof(st))); - work = st.bytes; - classptr->backlog = st.qlen; - - /*Checkout if this class will trigger realtime mode by looking to see if either - the realtime or fair service curves are two part. */ - if (firstflg) { - - struct tc_service_curve *sc = NULL; - struct rtattr *tbs[TCA_STATS_MAX + 1]; - - classptr->rtclass=0; - parse_rtattr_nested(tbs, TCA_HFSC_MAX, tb[TCA_OPTIONS]); - if (tbs[TCA_HFSC_RSC] && (RTA_PAYLOAD(tbs[TCA_HFSC_RSC]) >= sizeof(*sc))) { - sc = RTA_DATA(tbs[TCA_HFSC_RSC]); - classptr->rtclass |= (sc && sc->m1); - } - - if (tbs[TCA_HFSC_FSC] && (RTA_PAYLOAD(tbs[TCA_HFSC_FSC]) >= sizeof(*sc))) { - sc = RTA_DATA(tbs[TCA_HFSC_FSC]); - classptr->rtclass |= (sc && sc->m1); - } - - } - - } else { - errorflg=1; - return 0; - } - - - //Avoid a big jolt on the first pass. - if (firstflg) { - classptr->bytes = work; - } - - //Update the filtered bandwidth based on what happened unless a rollover occured. - if (work >= classptr->bytes) { - long int bw; - long bperiod; - - //Calculate an accurate time period for the bps calculation. - bperiod=(newtime.tv_nsec-classptr->bwtime)/1000000; - if (bperiodbytes)*8000/bperiod; //bps per second x 1000 here - - //Convert back to bps as part of the filter calculation - classptr->cbw_flt=(bw-classptr->cbw_flt)*BWTC/1000+classptr->cbw_flt; - - //A class is considered active if its BW exceeds 4000bps - if ((leafid != -1) && (classptr->cbw_flt > 4000)) { - DCA++;actflg=1; - if (classptr->rtclass) RTDCA++; - } - - //Calculate the total link load by adding up all the classes. - if (leafid == -1) { - dbw_fil = 0; - } else { - dbw_fil += classptr->cbw_flt; - } - - } - - classptr->bwtime=newtime.tv_nsec; - classptr->bytes = work; - classptr->actflg = actflg; - - classptr++; - classcnt++; - return 0; -} - -/*Gather stats for classes attached to device d */ -int class_list(char *d) -{ - struct tcmsg t; - - RTDCA=DCA =0; - memset(&t, 0, sizeof(t)); - t.tcm_family = AF_UNSPEC; - - ll_init_map(&rth); - - if (d[0]) { - if ((t.tcm_ifindex = ll_name_to_index(d)) == 0) { - fprintf(stderr, "Cannot find device \"%s\"\n", d); - return 1; - } - filter_ifindex = t.tcm_ifindex; - } - - if (rtnl_dump_request(&rth, RTM_GETTCLASS, &t, sizeof(t)) < 0) { - perror("Cannot send dump request"); - return 1; - } - - if (dump_filter(&rth, print_class, stdout) < 0) { - fprintf(stderr, "Dump terminated\n"); - return 1; - } - - return 0; -} - - -/* - * tc_class_modify - * - * This function changes the upper limit rate of the 'DEVICE' class to match - * the rate passed in as the sole parameter. This is the throttle means - * we will use to maintian the QoS performance as the link becomes saturated. - * - * The structure of this code is gleaned from the source code of 'tc' and is - * specific the the gargoyle QoS design. - */ -int tc_class_modify(__u32 rate) -{ - struct { - struct nlmsghdr n; - struct tcmsg t; - char buf[4096]; - } req; - - char k[16]; - __u32 handle; - - if (dbw_ul == rate) return 0; - dbw_ul=rate; - - memset(&req, 0, sizeof(req)); - memset(k, 0, sizeof(k)); - - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)); - req.n.nlmsg_flags = NLM_F_REQUEST; - req.n.nlmsg_type = RTM_NEWTCLASS; - req.t.tcm_family = AF_UNSPEC; - - //We are only going to modify the upper limit rate of the parent class. - if (get_tc_classid(&handle, "1:1")) { - fprintf(stderr,"invalid class ID"); - return 1; - } - req.t.tcm_handle = handle; - - if (get_tc_classid(&handle, "1:0")) { - fprintf(stderr,"invalid parent ID"); - return 1; - } - req.t.tcm_parent = handle; - - strcpy(k,"hsfc"); - addattr_l(&req.n, sizeof(req), TCA_KIND, k, strlen(k)+1); - - { - struct tc_service_curve usc; - struct rtattr *tail; - - memset(&usc, 0, sizeof(usc)); - - usc.m2 = rate/8; - - tail = NLMSG_TAIL(&req.n); - - addattr_l(&req.n, 1024, TCA_OPTIONS, NULL, 0); - addattr_l(&req.n, 1024, TCA_HFSC_USC, &usc, sizeof(usc)); - - tail->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail; - } - - - //Communicate our change to the kernel. - ll_init_map(&rth); - - if ((req.t.tcm_ifindex = ll_name_to_index(DEVICE)) == 0) { - fprintf(stderr, "Cannot find device %s\n",DEVICE); - return 1; - } - - - if (talk(&rth, &req.n, 0, 0, NULL) < 0) - return 2; - - return 0; -} - -/* - This function is periodically called and updates the - status file for the deamon. The status file can then - be viewed by other processes to tell what is going on. -*/ -void update_status( FILE* fd ) -{ - - struct CLASS_STATS *cptr=dnstats; - u_char i; - char nstr[10]; - int dbw; - - //Link load includes the ping traffic when the pinger is on. - if (pingon) dbw = dbw_fil + 64 * 8 * 1000/period; - else dbw = dbw_fil; - - //Update the status file. - rewind(fd); - fprintf(fd,"State: %s\n",statename[qstate]); - fprintf(fd,"Link limit: %d (kbps)\n",dbw_ul/1000); - fprintf(fd,"Fair Link limit: %d (kbps)\n",new_dbw_ul/1000); - fprintf(fd,"Link load: %d (kbps)\n",dbw/1000); - - if (pingon) { - if (nopingresponse) fprintf(fd,"Ping: Dropped, assume %d mS\n",rawfltime_max/1000); - else fprintf(fd,"Ping: %d (ms)\n",rawfltime); - } - else - fprintf(fd,"Ping: off\n"); - - fprintf(fd,"Filtered/Max recent RTT: %d/%d (ms)\n",fil_triptime/1000,rawfltime_max/1000); - fprintf(fd,"RTT time limit: %d (ms) [%d/%d]\n",plimit/1000,pinglimit/1000,(pinglimit+135*pinglimit_cl/100)/1000); - fprintf(fd,"Classes Active: %u\n",DCA); - - fprintf(fd,"Errors: (mismatch,errors,last err,selerr): %u,%u,%u,%i\n", cnt_mismatch, cnt_errorflg,last_errorflg,sel_err); - - - i=0; - while ((i++ID != 0)) { - fprintf(fd,"ID %4X, Active %u, Backlog %u, BW bps (filtered): %ld\n", - (short unsigned) cptr->ID, - cptr->actflg, - cptr->backlog, - cptr->cbw_flt); - cptr++; - } - - fflush(fd); - -#ifndef ONLYBG - if (DEAMON) return; - - //Home the cursor - mvprintw(0,0,""); - printw("\nqosmon status\n"); - - if (pingon) { - sprintf(nstr,"%d",rawfltime); - } else { - strcpy(nstr,"*"); - } - - printw("ping (%s/%d) DCA=%d, RTDCA=%d, plim=%d, plim2=%d, state=%s\n",nstr,fil_triptime/1000, - DCA,RTDCA,pinglimit/1000,plimit/1000,statename[qstate]); - printw("Link Limit=%6d, Fair Limit=%6d, Current Load=%6d (kbps)\n", - dbw_ul/1000,new_dbw_ul/1000,dbw/1000); - printw("Saved Active Limit=%6d, Saved Realtime Limit=%6d\n",saved_active_limit/1000,saved_realtime_limit/1000); - printw("pings sent=%d, pings received=%d\n", - ntransmitted,nreceived); - - printw("Defined classes for %s\n",DEVICE); - printw("Errors: (mismatches,errors,last err,selerr): %u,%u,%u,%i\n", cnt_mismatch, cnt_errorflg,last_errorflg,sel_err); - cptr=dnstats; - i=0; - while ((i++ID != 0)) { - printw("ID %4X, Active %u, Realtime %u. Backlog %u, BW (filtered kbps): %ld\n", - (short unsigned) cptr->ID, - cptr->actflg, - cptr->rtclass, - cptr->backlog, - cptr->cbw_flt/1000); - cptr++; - } - - refresh(); -#endif - -} - -/* v2.3 feature allows reseting the link limit to the initial value by sending the process SIGUSR1. */ -sig_atomic_t resetbw=1; -void resetsig(int parm) -{ - resetbw=1; -} - - -/* - * M A I N - */ -int main(int argc, char *argv[]) -{ - struct sockaddr_in from; - char **av = argv; - struct sockaddr_in *to = &whereto; - int on = 1; - struct protoent *proto; - float err; - - - argc--, av++; - while (argc > 0 && *av[0] == '-') { - while (*++av[0]) switch (*av[0]) { - case 'b': - pingflags |= BACKGROUND; - break; - - case 'a': - pingflags |= ADDENTITLEMENT; - break; - } - argc--, av++; - } - if ((argc < 3) || (argc >4)) { - printf(usage); - exit(1); - } - -#ifdef ONLYBG - if (!(pingflags & BACKGROUND)) { - fprintf(stderr, "Must use the -b switch\n"); - exit(1); - } -#endif - - //The first parameter is the ping time in ms. - period = atoi( av[0] ); - if ((period > 2000) || (period < 100)) { - fprintf(stderr, "Invalid ping interval '%s'\n", av[0]); - exit(1); - } - - bzero((char *)&whereto, sizeof(whereto) ); - to->sin_family = AF_INET; - to->sin_addr.s_addr = inet_addr(av[1]); - if(to->sin_addr.s_addr != (unsigned)-1) { - strcpy(hnamebuf, av[1]); - hostname = hnamebuf; - } else { - hp = gethostbyname(av[1]); - if (hp) { - to->sin_family = hp->h_addrtype; - bcopy(hp->h_addr, (caddr_t)&to->sin_addr, hp->h_length); - hostname = hp->h_name; - } else { - fprintf(stderr, "%s: unknown host %s\n", argv[1], av[1]); - exit(1); - } - } - - //The third parameter is the maximum download speed in kbps. - DBW_UL = atoi( av[2] ); - if ((DBW_UL < 100) || (DBW_UL >= INT_MAX/1000)) { - fprintf(stderr, "Invalid download bandwidth '%s'\n", av[2]); - exit(1); - } - - //Convert kbps to bps. - dbw_ul = DBW_UL = DBW_UL*1000; - - //The fourth optional parameter is the ping limit in ms. - if (argc == 4) { - pinglimit_cl = pinglimit = atoi( av[3] )*1000; - } - - - ident = getpid() & 0xFFFF; - - if ((proto = getprotobyname("icmp")) == NULL) { - fprintf(stderr, "icmp: unknown protocol\n"); - exit(10); - } - - // where alpha = Sample_Period / (TC + Sample_Period) - // TC needs to be not less than 3 times the sample period - alpha = (period*1000. / (period*4 + period)); - - //Class bandwidth filter time constants - BWTC= (period*1000. / (7500. + period)); - - //Check that we have access to tc functions. - tc_core_init(); - if (rtnl_open(&rth, 0) < 0) { - fprintf(stderr, "Cannot open rtnetlink\n"); - exit(1); - } - - //Make sure the device is present and that we can scan it. - classptr=dnstats; - errorflg=0; - class_list(DEVICE); - if (errorflg) { - fprintf(stderr, "Cannot scan ingress device %s\n",DEVICE); - exit(1); - } - - //If running in the background fork() - if (DEAMON) { - - /* Ignore most signals in background */ - signal( SIGINT, SIG_IGN ); - signal( SIGQUIT, SIG_IGN ); - signal( SIGCHLD, SIG_IGN ); - signal( SIGALRM, SIG_IGN ); - signal( SIGUSR1, SIG_IGN ); - signal( SIGUSR2, SIG_IGN ); - signal( SIGHUP, SIG_IGN ); - signal( SIGTSTP, SIG_IGN ); - signal( SIGPIPE, (__sighandler_t) finish ); - signal( SIGSEGV, (__sighandler_t) finish ); - signal( SIGILL, (__sighandler_t) finish ); - signal( SIGFPE, (__sighandler_t) finish ); - signal( SIGSYS, (__sighandler_t) finish ); - signal( SIGURG, (__sighandler_t) finish ); - signal( SIGTTIN, (__sighandler_t) finish ); - signal( SIGTTOU, (__sighandler_t) finish ); - - //daemonize(); - if ( daemon( 0, 0) < 0 ) - { - fprintf(stderr,"deamon() failed with %i\n",errno); - exit( 1 ); - } - - /* Initialize the logging interface */ - openlog( DAEMON_NAME, LOG_PID, LOG_LOCAL5 ); - } - - //SIGTERM is what we expect to kill us. - signal( SIGTERM, (__sighandler_t) finish ); - - //SIGUSR1 resets the link speed. - signal( SIGUSR1, (__sighandler_t) resetsig ); - - //Create the status file and ping socket - //These are called here because the above daemon() call closes - //open files. - statusfd = fopen("/tmp/qosmon.status","w"); - s = socket(AF_INET, SOCK_RAW, proto->p_proto); - - - //Check that things opened correctly. - if (DEAMON) { - if (statusfd == NULL) { - syslog( LOG_CRIT, "Cannot open /tmp/qosmon.status - %i",errno ); - exit(EXIT_FAILURE); - } - - if (s < 0) { - syslog( LOG_CRIT, "Cannot open ping socket - %i",errno ); - exit(EXIT_FAILURE); - } - - syslog(LOG_INFO, "starting socketfd = %i, statusfd = %i",s,fileno(statusfd)); - } - -#ifndef ONLYBG - else { - if (statusfd == NULL) { - fprintf(stderr, "Cannot open /tmp/qosmon.status - %i",errno ); - exit(EXIT_FAILURE); - } - - if (s < 0) { - fprintf( stderr, "Cannot open ping socket - %i",errno ); - exit(EXIT_FAILURE); - } - - //Ctrl-C terminates - signal( SIGINT, (__sighandler_t) finish ); - - //Close terminal terminates - signal( SIGHUP, (__sighandler_t) finish ); - - setlinebuf( stdout ); - - //Bring up ncurses - initscr(); - - } -#endif - - //Clear all initial stats. - memset((void *)&dnstats,0,sizeof(dnstats)); - - //Initialize the max ping to something reasonable. - //We will fix it later. - rawfltime_max = period*1000; - - while (!sigterm) { - int len = sizeof (packet); - socklen_t fromlen = sizeof (from); - int cc; - u_char chill; - struct timeval timeout; - fd_set fdmask; - FD_ZERO(&fdmask); - FD_SET(s , &fdmask); - - //rawfltime variable will be set in pr_pack() if we get a pong that matched - //our ping, but clearing it here will let us know we did not get a response to our - //ping. - rawfltime=0; - - //Send the next ping - if (pingon) pinger(); - - //Wait for the pong(s). - timeout.tv_sec = 0; - timeout.tv_usec = period*1000; - - //Need a loop here to clean out any old pongs that show up. - //select() returns 1 if there is data to read. - // 0 if the time has expired. - // -1 if a signal arrived. - while (sel_err=select(s+1, &fdmask, NULL, NULL, &timeout)) { - - //Signal arrived, just loop and keep waiting. - if (sel_err == -1) continue; - - //If we got here then data must be waiting, try to read the whole packet - if ( (cc=recvfrom(s,packet,len,0,(struct sockaddr *) &from, &fromlen)) < 0) { - continue; - } - - //OK there is a whole packet, get it and record the triptime. - pr_pack( packet, cc, &from ); - - } - - //Gather new statistics - classptr=dnstats; - cc=classcnt; - classcnt=0; - errorflg=0; - class_list(DEVICE); - - //If there was an error or the number of classes changed then reset everything - if (errorflg || (!firstflg && (cc !=classcnt))) { - - if (errorflg) {cnt_errorflg++; last_errorflg=errorflg;} - else if (cc != classcnt) cnt_mismatch++; - - firstflg=1; - pingon=0; - qstate=QMON_CHK; - continue; - } - - - //Initialize or reinitialize the fair linklimit. - if (resetbw) { - saved_realtime_limit=saved_active_limit=new_dbw_ul= DBW_UL * .9; - resetbw=0; - } - - //Look at an ping response time we got. If we did not get any then it most likely - //got dropped so use the maximum value that we have recently seen as we know the downlink - //queue must be at least this long. - if (!rawfltime) { - rawfltime = rawfltime_max/1000; - nopingresponse=1; - } else - nopingresponse=0; - - //Update the filtered ping response time based on what happened. - //If we are not pinging then no change in the filtered value. - if (pingon) - fil_triptime = ((rawfltime*1000 - fil_triptime)*alpha)/1000 + fil_triptime; - - //Run the state machine - switch (qstate) { - - // Wait to see if the ping targer will respond at all before doing anything - case QMON_CHK: - pingon=1; - - //If we get two pings go ahead and lower the link speed. - if (nreceived >= 2) { - - //If the pinglimit was entered on the command line - //without the add flag then go directly to the - //IDLE state otherwise automatically determine an appropriate - //ping limit. - if ((pinglimit) && !(pingflags & ADDENTITLEMENT)) { - dbw_ul=0; //Forces an update in tc_class_modify() - tc_class_modify(new_dbw_ul); - fil_triptime = rawfltime*1000; - qstate=QMON_IDLE; - } else { - tc_class_modify(1000); //Unload the link for the measurement. - nreceived=0; - qstate=QMON_INIT; - } - } - break; - - // Take a measurement of the practical ping time we can expect in an unsaturated - // link. We do this by making pings and using the filter response after - // throttling all traffic in the link. - case QMON_INIT: - //Filter starts at ten seconds and runs until 15 seconds. - //For the first ten seconds we initialize the filter to the last ping time we saw. - //After the seventh second we start filtering. - if (nreceived < (10000/period)+1) fil_triptime = rawfltime*1000; - - //After 15 seconds we have measured our ping response entitlement. - //Move on to the active state. - if (nreceived > (15000/period)+1) { - qstate=QMON_IDLE; - tc_class_modify(new_dbw_ul); //Restore reasonable bandwidth - - //If the user specified no limit then the RTT ping limit is computed from what was - //entered on the command line. - if (pingflags & ADDENTITLEMENT) { - //Add what the user specified to the 110% of the measure ping time. - pinglimit += (fil_triptime*1.1); - } else { - //Without the '-a' flag we just use 200% of measure ping time. - //This works OK in my system but I have no evidence that it will work in other systems. - pinglimit = fil_triptime*2.0; - } - - //Sanity Checks - if (pinglimit < 10000) pinglimit=10000; - if (pinglimit > 800000) pinglimit=800000; - - //Reasonable max ping. - rawfltime_max = 2*pinglimit; - } - break; - - // In the wait state we have a nearly idle link. - // In these cases it is not necessary to monitor delay times so the active - // ping is disabled. - case QMON_IDLE: - pingon=0; - - //This limit should be the same as the dynamic range or we could get stuck - //in the IDLE state. - if (dbw_fil < 0.15 * DBW_UL) break; - - // In the ACTIVE & REALTIME states we observe ping times as long as the - // link remains active. While we are observing we adjust the - // link upper limit speed to maintain the specified pinglimit. - // If the amount of data we are recieving dies down we enter the WAIT state - case QMON_ACTIVE: - case QMON_REALTIME: - pingon=1; - - //Save the bandwidth limit for each mode. - if (qstate == QMON_REALTIME) saved_realtime_limit = new_dbw_ul; - if (qstate == QMON_ACTIVE) saved_active_limit = new_dbw_ul; - - //The pinglimit we will use depends on if any realtime classes are active - //or not. In realtime mode we only allow 'pinglimit' round trip times which - //makes our pings low but also lowers our throughput. The automatic measurement - //above set pinglimit to the average RTT of the ping assuming it has to wait on - //average for 2/3 of an single MTU sized packet to transmit. The means on - //average there is nothing in the buffer but a packet is transmitting. - - //When not in realtime mode the stradegy is that we allow enough packets in the queue - //to fully utilize the downlink. - - //We are talking about a queue controlled by the ISP so we don't know much about it. - //We make an assumption that the queue is long enough to allow full utilization of the link. - //This should be the case and often the queue is much longer than needed (bufferbloat). - //When not in realtime mode we can allow this buffer to fill but we don't want it to overflow - //because it will then drop packets which will cause our QoS to breakdown. So we want it to fill - //just enough to promote full link utilization. - - //The classical optimum queue size would be equal to the bandwidth * RTT and the - //additional time it will take our ping to pass through such a queue turns out to be the RTT. - //But Barman et all, Globecomm2004 indicates that only 20-30% of this is really needed. - // - //When we measured an RTT above that was to the ISPs gateway so we do not really know what the average - //RTT time to other IPs on the internet. And since not all hosts respond the same anyway I doubt there - //is consistant RTT that we could use. - // - //For ACTIVE mode on a 925kbps/450kbps link I measure the following - //relationship between ping limit and throughput with large packets downloading. - // - //Ping Limit Throughput Percent - // 612ms 918kbps 100 - // 525ms 915kbps 99.6 - // 437ms 898kbps 97.8 - // 350ms 875kbps 95.3 - // 262ms 862kbps 93.8 - // 81ms 870kbps 94.7 - // 60ms 680kbps 69.8 - // 50ms 630kbps 68.6 - // 40ms 490kbps 53.3 - // - //The 1500 byte packet time is 1500*10/925kbps download and 1500*10/425kbps upload for a total - //RTT of around 48ms. Idle ping times on this link are around 35ms. - // - //These results indicate that on my link not much is gained by increasing beyond 81ms. This is pretty much - //the MINRTT mode computed with the -a switch. Still other links may be different so I suspect that - //switching to active mode will benefit some people. - // - //The statedgy I will use for the ACTIVE mode limit will be to add an additional 135% packet delay over - //what we have in RTT mode. The packet delay was entered on the command line or zero if nothing was entered. - - //I hope that this will work well for a broad range of users from satellite links with RTTs of 1 second or more - //or users with hot connections that have small queue upstream of them. - - if ((RTDCA == 0) && (pingflags & ADDENTITLEMENT)) { - plimit=135*pinglimit_cl/100+pinglimit; - - //When switching into active mode for the first time initialize the bandwidth - //limit to the last value that was known to work. - if (qstate != QMON_ACTIVE) { - qstate=QMON_ACTIVE; - new_dbw_ul=saved_active_limit; - tc_class_modify(new_dbw_ul); - } - - } else { - plimit = pinglimit; - - //When switching into realtime mode for the first time initialize the bandwidth - //limit to the last value that was known to work. - if (qstate != QMON_REALTIME) { - qstate=QMON_REALTIME; - new_dbw_ul=saved_realtime_limit; - tc_class_modify(new_dbw_ul); - } - - } - - //When the downlink falls below 10% utilization we turn off the pinger. - if (dbw_fil < 0.1 * DBW_UL) qstate=QMON_IDLE; - - //Compute the ping error - err = fil_triptime - plimit; - - //Negative error means we might be able to increase the link limit. - if (err < 0) { - - //Do not increase the bandwidth until we reach 85% of the current limit. - if (dbw_fil < dbw_ul * 0.85) break; - - //Increase slowly (0.4%/sec). err is negative here. - new_dbw_ul = new_dbw_ul * (1.0 - 0.004*err*(float)period/(float)plimit/1000.0); - if (new_dbw_ul > DBW_UL) new_dbw_ul=DBW_UL; - - } else { - //Positive error means we need to decrease the bandwidth. - - new_dbw_ul = new_dbw_ul * (1.0 - 0.004*err*(float)period/(float)plimit/1000.0); - - //Dynamic range is 1/.15 or 6.67 : 1. - if (new_dbw_ul < DBW_UL*.15) new_dbw_ul=DBW_UL*.15; - } - - //Modify parent download limit as needed. - tc_class_modify(new_dbw_ul); - - //Keep downward pressure on rawfltime_max to keep it fresh. - if (rawfltime_max > plimit) rawfltime_max -= 100; - - break; - - - } - - update_status(statusfd); - - //If we get here the first pass is over. - firstflg=0; - - } //Next ping - - - qstate=QMON_EXIT; - - //We got a signal to terminate so start by restoring the root TC class to - //the original upper limit. - tc_class_modify(DBW_UL); - - update_status(statusfd); - - //Write a message in the system log - if (DEAMON) { - syslog( LOG_NOTICE, "terminated sigterm=%i, sel_err=%i", sigterm, sel_err ); - closelog(); - } - -#ifndef ONLYBG - else { - endwin(); - fflush(stdout); - } -#endif - -} -