#!/bin/sh
##FreshJR_QOS
version=8.8
release=03/07/2019
#Copyright (C) 2017-2019 FreshJR - All Rights Reserved
#Tested with ASUS AC-68U, FW384.9, using Adaptive QOS with Manual Bandwidth Settings
# Script Changes Unidentified traffic destination away from "Defaults" into "Others"
# Script Changes HTTPS traffic destination away from "Net Control" into "Web Surfing"
# Script Changes Guaranteed Bandwidth per QOS category into logical percentages of upload and download.
# Script Repurposes "Defaults" to contain "Game Downloads"
# "Game Downloads" moved into 6th position
# "Lowest Defined" moved into 7th position
#Script includes misc hardcoded rules
# (Wifi Calling) - UDP traffic on remote ports 500 & 4500 moved into VOIP
# (Facetime) - UDP traffic on local ports 16384 - 16415 moved into VOIP
# (Usenet) - TCP traffic on remote ports 119 & 563 moved into Downloads
# (Gaming) - Gaming TCP traffic from remote ports 80 & 443 moved into Game Downloads.
# (Snapchat) - Moved into Others
# (Speedtest.net) - Moved into Downloads
# (Google Play) - Moved into Downloads
# (Apple AppStore)- Moved into Downloads
# (Advertisement) - Moved into Downloads
# (VPN Fix) - Router VPN Client upload traffic moved into Downloads instead of whitelisted
# (VPN Fix) - Router VPN Client download traffic moved into Downloads instead of showing up in Uploads
# (Gaming Manual) - Unidentified traffic for specified devices, not originating from ports 80/443, moved into "Gaming"
#
# Gaming traffic originating from ports 80 & 443 is primarily downloads & patches (some lobby/login protocols mixed within)
# Manually configurable rule will take untracked traffic, not originating from 80/443, for specified devices and place it into Gaming
# Use of this gaming rule REQUIRES devices to have a continuous static ip assignment && this range needs to be defined in the script
#
# Custom rules can be created within the WebUI OR by running the -rules command:
# (custom rules): /jffs/scripts/FreshJR_QOS -rules
#
# Default bandwidth allocation per category can be adjusted via WebUI OR -rates command:
# (custom rates): /jffs/scripts/FreshJR_QOS -rates
#
##For discussion visit this thread:
## https://www.snbforums.com/threads/release-freshjr-adaptive-qos-improvements-custom-rules-and-inner-workings.36836/
## https://github.com/FreshJR07/FreshJR_QOS (Source Code + Backup Link)
#
##License
## FreshJR_QOS is free to use under the GNU General Public License, version 3 (GPL-3.0).
## https://opensource.org/licenses/GPL-3.0
#################### MODIFY BELOW WITH CAUTION #####################
#################### MODIFY BELOW WITH CAUTION #####################
#
### IF YOU MANUALLY ADD RULES TO AREA BELOW THEN KEEP IN MIND THAT YOUR CHANGES WILL TAKE EFFECT BUT WILL NOT BE REFLECTED UNDER THE TRACKED CONNECTIONS SECTION OF THE WEBUI.
### FOR HARDCODED CHANGES TO BE REFLECTED IN TRACKED CONNECTIONS SECTION OF THE WEBUI THEN YOU ALSO HAVE TO MODIFY THE CORRESPONDING JAVASCRIPT CODE IN /jffs/scripts/FreshJR_QoS_Stats.asp
### INSTEAD OF HARDCODED CHANGES (legacy method) YOU CAN USE THE SCRIPTS -RULES COMMAND OR ENTER THE WEBUI PAGE FOR CREATING RULES AND THOSE CHANGES WILL BE REFLECTED IN THE TRACKED CONNECTIONS TABLE.
#
#################### MODIFY BELOW WITH CAUTION #####################
#################### MODIFY BELOW WITH CAUTION #####################
iptable_down_rules() {
echo "Applying - Iptable Down Rules"
##DOWNLOAD (INCOMMING TRAFFIC) CUSTOM RULES START HERE -- legacy method
iptables -D POSTROUTING -t mangle -o br0 -p udp -m multiport --sports 500,4500 -j MARK --set-mark ${VOIP_mark_down} &> /dev/null #Wifi Calling - (All incoming traffic from WAN source ports 500 & 4500 --> VOIP )
iptables -A POSTROUTING -t mangle -o br0 -p udp -m multiport --sports 500,4500 -j MARK --set-mark ${VOIP_mark_down}
iptables -D POSTROUTING -t mangle -o br0 -p udp --dport 16384:16415 -j MARK --set-mark ${VOIP_mark_down} &> /dev/null #Facetime - (All incoming traffic to LAN destination ports 16384-16415 --> VOIP )
iptables -A POSTROUTING -t mangle -o br0 -p udp --dport 16384:16415 -j MARK --set-mark ${VOIP_mark_down}
iptables -D POSTROUTING -t mangle -o br0 -p tcp -m multiport --sports 119,563 -j MARK --set-mark ${Downloads_mark_down} &> /dev/null #Usenet - (All incoming traffic from WAN source ports 119 & 563 --> Downloads )
iptables -A POSTROUTING -t mangle -o br0 -p tcp -m multiport --sports 119,563 -j MARK --set-mark ${Downloads_mark_down}
iptables -D POSTROUTING -t mangle -o br0 -m mark --mark 0x40000000/0xc0000000 -j MARK --set-xmark 0x80000000/0xC0000000 &> /dev/null #VPN Fix - (Fixes download traffic showing up in upload section when router is acting as a VPN Client)
iptables -A POSTROUTING -t mangle -o br0 -m mark --mark 0x40000000/0xc0000000 -j MARK --set-xmark 0x80000000/0xC0000000
iptables -D POSTROUTING -t mangle -o br0 -m mark --mark 0x80080000/0xc03f0000 -p tcp -m multiport --sports 80,443 -j MARK --set-mark ${Default_mark_down} &> /dev/null #Gaming - (Incoming "Gaming" traffic from WAN source ports 80 & 443 --> Defaults//GameDownloads)
iptables -A POSTROUTING -t mangle -o br0 -m mark --mark 0x80080000/0xc03f0000 -p tcp -m multiport --sports 80,443 -j MARK --set-mark ${Default_mark_down}
##DOWNLOAD (INCOMMING TRAFFIC) CUSTOM RULES END HERE -- legacy method
if [ "$( echo $gameCIDR | tr -cd '.' | wc -c )" -eq "3" ] ; then
iptables -D POSTROUTING -t mangle -o br0 -d $gameCIDR -m mark --mark 0x80000000/0x8000ffff -p tcp -m multiport ! --sports 80,443 -j MARK --set-mark ${Gaming_mark_down} &> /dev/null #Gaming - (Incoming "Unidentified" TCP traffic, for devices specified, not from WAN source ports 80 & 443 --> Gaming)
iptables -A POSTROUTING -t mangle -o br0 -d $gameCIDR -m mark --mark 0x80000000/0x8000ffff -p tcp -m multiport ! --sports 80,433 -j MARK --set-mark ${Gaming_mark_down}
iptables -D POSTROUTING -t mangle -o br0 -d $gameCIDR -m mark --mark 0x80000000/0x8000ffff -p udp -m multiport ! --sports 80,443 -j MARK --set-mark ${Gaming_mark_down} &> /dev/null #Gaming - (Incoming "Unidentified" UDP traffic, for devices specified, not from WAN source ports 80 & 443 --> Gaming)
iptables -A POSTROUTING -t mangle -o br0 -d $gameCIDR -m mark --mark 0x80000000/0x8000ffff -p udp -m multiport ! --sports 80,443 -j MARK --set-mark ${Gaming_mark_down}
fi
if ! [ -z "$ip1_down" ] ; then #Script Interactively Defined Rule 1
if [ "$(echo ${ip1_down} | grep -c "both")" -ge "1" ] ; then
iptables -D POSTROUTING -t mangle -o br0 ${ip1_down//both/tcp} &> /dev/null
iptables -A POSTROUTING -t mangle -o br0 ${ip1_down//both/tcp}
iptables -D POSTROUTING -t mangle -o br0 ${ip1_down//both/udp} &> /dev/null
iptables -A POSTROUTING -t mangle -o br0 ${ip1_down//both/udp}
else
iptables -D POSTROUTING -t mangle -o br0 ${ip1_down} &> /dev/null
iptables -A POSTROUTING -t mangle -o br0 ${ip1_down}
fi
fi
if ! [ -z "$ip2_down" ] ; then #Script Interactively Defined Rule 2
if [ "$(echo ${ip2_down} | grep -c "both")" -ge "1" ] ; then
iptables -D POSTROUTING -t mangle -o br0 ${ip2_down//both/tcp} &> /dev/null
iptables -A POSTROUTING -t mangle -o br0 ${ip2_down//both/tcp}
iptables -D POSTROUTING -t mangle -o br0 ${ip2_down//both/udp} &> /dev/null
iptables -A POSTROUTING -t mangle -o br0 ${ip2_down//both/udp}
else
iptables -D POSTROUTING -t mangle -o br0 ${ip2_down} &> /dev/null
iptables -A POSTROUTING -t mangle -o br0 ${ip2_down}
fi
fi
if ! [ -z "$ip3_down" ] ; then #Script Interactively Defined Rule 3
if [ "$(echo ${ip3_down} | grep -c "both")" -ge "1" ] ; then
iptables -D POSTROUTING -t mangle -o br0 ${ip3_down//both/tcp} &> /dev/null
iptables -A POSTROUTING -t mangle -o br0 ${ip3_down//both/tcp}
iptables -D POSTROUTING -t mangle -o br0 ${ip3_down//both/udp} &> /dev/null
iptables -A POSTROUTING -t mangle -o br0 ${ip3_down//both/udp}
else
iptables -D POSTROUTING -t mangle -o br0 ${ip3_down} &> /dev/null
iptables -A POSTROUTING -t mangle -o br0 ${ip3_down}
fi
fi
if ! [ -z "$ip4_down" ] ; then #Script Interactively Defined Rule 4
if [ "$(echo ${ip4_down} | grep -c "both")" -ge "1" ] ; then
iptables -D POSTROUTING -t mangle -o br0 ${ip4_down//both/tcp} &> /dev/null
iptables -A POSTROUTING -t mangle -o br0 ${ip4_down//both/tcp}
iptables -D POSTROUTING -t mangle -o br0 ${ip4_down//both/udp} &> /dev/null
iptables -A POSTROUTING -t mangle -o br0 ${ip4_down//both/udp}
else
iptables -D POSTROUTING -t mangle -o br0 ${ip4_down} &> /dev/null
iptables -A POSTROUTING -t mangle -o br0 ${ip4_down}
fi
fi
}
iptable_up_rules(){
#wan="ppp0" ## WAN interface over-ride for upload traffic if automatic detection is not working properly
echo "Applying - Iptable Up Rules ($wan)"
##UPLOAD (OUTGOING TRAFFIC) CUSTOM RULES START HERE -- legacy method
iptables -D POSTROUTING -t mangle -o $wan -p udp -m multiport --dports 500,4500 -j MARK --set-mark ${VOIP_mark_up} &> /dev/null #Wifi Calling - (All outgoing traffic to WAN destination ports 500 & 4500 --> VOIP )
iptables -A POSTROUTING -t mangle -o $wan -p udp -m multiport --dports 500,4500 -j MARK --set-mark ${VOIP_mark_up}
iptables -D POSTROUTING -t mangle -o $wan -p udp --sport 16384:16415 -j MARK --set-mark ${VOIP_mark_up} &> /dev/null #Facetime - (All outgoing traffic from LAN source ports 16384-16415 --> VOIP )
iptables -A POSTROUTING -t mangle -o $wan -p udp --sport 16384:16415 -j MARK --set-mark ${VOIP_mark_up}
iptables -D POSTROUTING -t mangle -o $wan -p tcp -m multiport --dports 119,563 -j MARK --set-mark ${Downloads_mark_up} &> /dev/null #Usenet - (All outgoing traffic to WAN destination ports 119 & 563 --> Downloads )
iptables -A POSTROUTING -t mangle -o $wan -p tcp -m multiport --dports 119,563 -j MARK --set-mark ${Downloads_mark_up}
iptables -D OUTPUT -t mangle -o $wan -p udp -m multiport ! --dports 53,123 -j MARK --set-mark ${Downloads_mark_up} &> /dev/null #VPN Fix - (Fixes upload traffic not detected when the router is acting as a VPN Client)
iptables -A OUTPUT -t mangle -o $wan -p udp -m multiport ! --dports 53,123 -j MARK --set-mark ${Downloads_mark_up}
iptables -D OUTPUT -t mangle -o $wan -p tcp -m multiport ! --dports 53,123 -j MARK --set-mark ${Downloads_mark_up} &> /dev/null #VPN Fix - (Fixes upload traffic not detected when the router is acting as a VPN Client)
iptables -A OUTPUT -t mangle -o $wan -p tcp -m multiport ! --dports 53,123 -j MARK --set-mark ${Downloads_mark_up}
iptables -D POSTROUTING -t mangle -o $wan -m mark --mark 0x40080000/0xc03f0000 -p tcp -m multiport --sports 80,443 -j MARK --set-mark ${Default_mark_up} &> /dev/null #Gaming - (Outgoing "Gaming" traffic to WAN destinations ports 80 & 443 --> Defaults//GameDownloads)
iptables -A POSTROUTING -t mangle -o $wan -m mark --mark 0x40080000/0xc03f0000 -p tcp -m multiport --sports 80,443 -j MARK --set-mark ${Default_mark_up}
##UPLOAD (OUTGOING TRAFFIC) CUSTOM RULES END HERE -- legacy method
if [ "$( echo $gameCIDR | tr -cd '.' | wc -c )" -eq "3" ] ; then
iptables -D POSTROUTING -t mangle -o $wan -s $gameCIDR -m mark --mark 0x40000000/0x4000ffff -p tcp -m multiport ! --dports 80,443 -j MARK --set-mark ${Gaming_mark_up} &> /dev/null #Gaming - (Outgoing "Unidentified" TCP traffic, for devices specified, not to WAN destination ports 80 & 443 --> Gaming)
iptables -A POSTROUTING -t mangle -o $wan -s $gameCIDR -m mark --mark 0x40000000/0x4000ffff -p tcp -m multiport ! --dports 80,443 -j MARK --set-mark ${Gaming_mark_up}
iptables -D POSTROUTING -t mangle -o $wan -s $gameCIDR -m mark --mark 0x40000000/0x4000ffff -p udp -m multiport ! --dports 80,443 -j MARK --set-mark ${Gaming_mark_up} &> /dev/null #Gaming - (Outgoing "Unidentified" UDP traffic, for devices specified, not to WAN destination ports 80 & 443 --> Gaming)
iptables -A POSTROUTING -t mangle -o $wan -s $gameCIDR -m mark --mark 0x40000000/0x4000ffff -p udp -m multiport ! --dports 80,443 -j MARK --set-mark ${Gaming_mark_up}
fi
if ! [ -z "$ip1_up" ] ; then #Script Interactively Defined Rule 1
if [ "$(echo ${ip1_up} | grep -c "both")" -ge "1" ] ; then
iptables -D POSTROUTING -t mangle -o $wan ${ip1_up//both/tcp} &> /dev/null
iptables -A POSTROUTING -t mangle -o $wan ${ip1_up//both/tcp}
iptables -D POSTROUTING -t mangle -o $wan ${ip1_up//both/udp} &> /dev/null
iptables -A POSTROUTING -t mangle -o $wan ${ip1_up//both/udp}
else
iptables -D POSTROUTING -t mangle -o $wan ${ip1_up} &> /dev/null
iptables -A POSTROUTING -t mangle -o $wan ${ip1_up}
fi
fi
if ! [ -z "$ip2_up" ] ; then #Script Interactively Defined Rule 2
if [ "$(echo ${ip2_up} | grep -c "both")" -ge "1" ] ; then
iptables -D POSTROUTING -t mangle -o $wan ${ip2_up//both/tcp} &> /dev/null
iptables -A POSTROUTING -t mangle -o $wan ${ip2_up//both/tcp}
iptables -D POSTROUTING -t mangle -o $wan ${ip2_up//both/udp} &> /dev/null
iptables -A POSTROUTING -t mangle -o $wan ${ip2_up//both/udp}
else
iptables -D POSTROUTING -t mangle -o $wan ${ip2_up} &> /dev/null
iptables -A POSTROUTING -t mangle -o $wan ${ip2_up}
fi
fi
if ! [ -z "$ip3_up" ] ; then #Script Interactively Defined Rule 3
if [ "$(echo ${ip3_up} | grep -c "both")" -ge "1" ] ; then
iptables -D POSTROUTING -t mangle -o $wan ${ip3_up//both/tcp} &> /dev/null
iptables -A POSTROUTING -t mangle -o $wan ${ip3_up//both/tcp}
iptables -D POSTROUTING -t mangle -o $wan ${ip3_up//both/udp} &> /dev/null
iptables -A POSTROUTING -t mangle -o $wan ${ip3_up//both/udp}
else
iptables -D POSTROUTING -t mangle -o $wan ${ip3_up} &> /dev/null
iptables -A POSTROUTING -t mangle -o $wan ${ip3_up}
fi
fi
if ! [ -z "$ip4_up" ] ; then #Script Interactively Defined Rule 4
if [ "$(echo ${ip4_up} | grep -c "both")" -ge "1" ] ; then
iptables -D POSTROUTING -t mangle -o $wan ${ip4_up//both/tcp} &> /dev/null
iptables -A POSTROUTING -t mangle -o $wan ${ip4_up//both/tcp}
iptables -D POSTROUTING -t mangle -o $wan ${ip4_up//both/udp} &> /dev/null
iptables -A POSTROUTING -t mangle -o $wan ${ip4_up//both/udp}
else
iptables -D POSTROUTING -t mangle -o $wan ${ip4_up} &> /dev/null
iptables -A POSTROUTING -t mangle -o $wan ${ip4_up}
fi
fi
}
tc_redirection_down_rules() {
echo "Applying TC Down Rules"
${tc} filter del dev br0 parent 1: prio $1 #remove original unidentified traffic rule
${tc} filter del dev br0 parent 1: prio 22 &> /dev/null #remove original HTTPS rule
${tc} filter del dev br0 parent 1: prio 23 &> /dev/null #remove original HTTPS rule
! [ -z "$tc4_down" ] && ${tc} filter add dev br0 protocol all ${tc4_down} #Script Interactively Defined Rule 4
! [ -z "$tc3_down" ] && ${tc} filter add dev br0 protocol all ${tc3_down} #Script Interactively Defined Rule 3
! [ -z "$tc2_down" ] && ${tc} filter add dev br0 protocol all ${tc2_down} #Script Interactively Defined Rule 2
! [ -z "$tc1_down" ] && ${tc} filter add dev br0 protocol all ${tc1_down} #Script Interactively Defined Rule 1
${tc} filter add dev br0 protocol all prio 20 u32 match mark 0x8012003F 0xc03fffff flowid ${Web} # HTTP rule with different destination
${tc} filter add dev br0 protocol all prio 22 u32 match mark 0x80130000 0xc03f0000 flowid ${Web} #recreate HTTPS rule with different destination
${tc} filter add dev br0 protocol all prio 23 u32 match mark 0x80140000 0xc03f0000 flowid ${Web} #recreate HTTPS rule with different destination
##DOWNLOAD APP_DB TRAFFIC REDIRECTION RULES START HERE -- legacy method
${tc} filter add dev br0 protocol all prio 2 u32 match mark 0x8000006B 0xc03fffff flowid ${Others} #Snapchat
${tc} filter add dev br0 protocol all prio 15 u32 match mark 0x800D0007 0xc03fffff flowid ${Downloads} #Speedtest.net
${tc} filter add dev br0 protocol all prio 15 u32 match mark 0x800D0086 0xc03fffff flowid ${Downloads} #Google Play
${tc} filter add dev br0 protocol all prio 15 u32 match mark 0x800D00A0 0xc03fffff flowid ${Downloads} #Apple AppStore
${tc} filter add dev br0 protocol all prio 50 u32 match mark 0x801A0000 0xc03f0000 flowid ${Downloads} #Advertisement
##DOWNLOAD APP_DB TRAFFIC REDIRECTION RULES END HERE -- legacy method
${tc} filter add dev br0 protocol all prio $1 u32 match mark 0x80000000 0x8000ffff flowid ${Others} #recreate unidentified traffic rule with different destination - Routes Unidentified Traffic into webUI adjustable "Others" traffic container instead of "Defaults"
${tc} filter add dev br0 protocol all prio 10 u32 match mark 0x803f0001 0xc03fffff flowid ${Defaults} #Used for iptables Default_mark_down functionality
}
tc_redirection_up_rules() {
echo "Applying TC Up Rules"
${tc} filter del dev eth0 parent 1: prio $1 #remove original unidentified traffic rule
${tc} filter del dev eth0 parent 1: prio 22 &> /dev/null #remove original HTTPS rule
${tc} filter del dev eth0 parent 1: prio 23 &> /dev/null #remove original HTTPS rule
! [ -z "$tc4_up" ] && ${tc} filter add dev eth0 protocol all ${tc4_up} #Script Interactively Defined Rule 4
! [ -z "$tc3_up" ] && ${tc} filter add dev eth0 protocol all ${tc3_up} #Script Interactively Defined Rule 3
! [ -z "$tc2_up" ] && ${tc} filter add dev eth0 protocol all ${tc2_up} #Script Interactively Defined Rule 2
! [ -z "$tc1_up" ] && ${tc} filter add dev eth0 protocol all ${tc1_up} #Script Interactively Defined Rule 1
${tc} filter add dev eth0 protocol all prio 20 u32 match mark 0x4012003F 0xc03fffff flowid ${Web} # HTTP rule with different destination
${tc} filter add dev eth0 protocol all prio 22 u32 match mark 0x40130000 0xc03f0000 flowid ${Web} #recreate HTTPS rule with different destination
${tc} filter add dev eth0 protocol all prio 23 u32 match mark 0x40140000 0xc03f0000 flowid ${Web} #recreate HTTPS rule with different destination
##UPLOAD APP_DB TRAFFIC REDIRECTION RULES START HERE -- legacy method
${tc} filter add dev eth0 protocol all prio 2 u32 match mark 0x4000006B 0xc03fffff flowid ${Others} #Snapchat
${tc} filter add dev eth0 protocol all prio 15 u32 match mark 0x400D0007 0xc03fffff flowid ${Downloads} #Speedtest.net
${tc} filter add dev eth0 protocol all prio 15 u32 match mark 0x400D0086 0xc03fffff flowid ${Downloads} #Google Play
${tc} filter add dev eth0 protocol all prio 15 u32 match mark 0x400D00A0 0xc03fffff flowid ${Downloads} #Apple AppStore
${tc} filter add dev eth0 protocol all prio 50 u32 match mark 0x401A0000 0xc03f0000 flowid ${Downloads} #Advertisement
##UPLOAD APP_DB TRAFFIC REDIRECTION RULES END HERE -- legacy method
${tc} filter add dev eth0 protocol all prio $1 u32 match mark 0x40000000 0x4000ffff flowid ${Others} #recreate unidentified traffic rule with different destination - Routes Unidentified Traffic into webUI adjustable "Others" traffic container, instead of "Default" traffic container
${tc} filter add dev eth0 protocol all prio 10 u32 match mark 0x403f0001 0xc03fffff flowid ${Defaults} #Used for iptables Default_mark_up functionality
}
custom_rates() {
echo "Modifying TC Class Rates"
${tc} class change dev br0 parent 1:1 classid 1:10 htb ${PARMS}prio 0 rate ${DownRate0}Kbit ceil ${DownCeil0}Kbit burst ${DownBurst0} cburst ${DownCburst0}
${tc} class change dev br0 parent 1:1 classid 1:11 htb ${PARMS}prio 1 rate ${DownRate1}Kbit ceil ${DownCeil1}Kbit burst ${DownBurst1} cburst ${DownCburst1}
${tc} class change dev br0 parent 1:1 classid 1:12 htb ${PARMS}prio 2 rate ${DownRate2}Kbit ceil ${DownCeil2}Kbit burst ${DownBurst2} cburst ${DownCburst2}
${tc} class change dev br0 parent 1:1 classid 1:13 htb ${PARMS}prio 3 rate ${DownRate3}Kbit ceil ${DownCeil3}Kbit burst ${DownBurst3} cburst ${DownCburst3}
${tc} class change dev br0 parent 1:1 classid 1:14 htb ${PARMS}prio 4 rate ${DownRate4}Kbit ceil ${DownCeil4}Kbit burst ${DownBurst4} cburst ${DownCburst4}
${tc} class change dev br0 parent 1:1 classid 1:15 htb ${PARMS}prio 5 rate ${DownRate5}Kbit ceil ${DownCeil5}Kbit burst ${DownBurst5} cburst ${DownCburst5}
${tc} class change dev br0 parent 1:1 classid 1:16 htb ${PARMS}prio 7 rate ${DownRate6}Kbit ceil ${DownCeil6}Kbit burst ${DownBurst6} cburst ${DownCburst6}
${tc} class change dev br0 parent 1:1 classid 1:17 htb ${PARMS}prio 6 rate ${DownRate7}Kbit ceil ${DownCeil7}Kbit burst ${DownBurst7} cburst ${DownCburst7}
${tc} class change dev eth0 parent 1:1 classid 1:10 htb ${PARMS}prio 0 rate ${UpRate0}Kbit ceil ${UpCeil0}Kbit burst ${UpBurst0} cburst ${UpCburst0}
${tc} class change dev eth0 parent 1:1 classid 1:11 htb ${PARMS}prio 1 rate ${UpRate1}Kbit ceil ${UpCeil1}Kbit burst ${UpBurst1} cburst ${UpCburst1}
${tc} class change dev eth0 parent 1:1 classid 1:12 htb ${PARMS}prio 2 rate ${UpRate2}Kbit ceil ${UpCeil2}Kbit burst ${UpBurst2} cburst ${UpCburst2}
${tc} class change dev eth0 parent 1:1 classid 1:13 htb ${PARMS}prio 3 rate ${UpRate3}Kbit ceil ${UpCeil3}Kbit burst ${UpBurst3} cburst ${UpCburst3}
${tc} class change dev eth0 parent 1:1 classid 1:14 htb ${PARMS}prio 4 rate ${UpRate4}Kbit ceil ${UpCeil4}Kbit burst ${UpBurst4} cburst ${UpCburst4}
${tc} class change dev eth0 parent 1:1 classid 1:15 htb ${PARMS}prio 5 rate ${UpRate5}Kbit ceil ${UpCeil5}Kbit burst ${UpBurst5} cburst ${UpCburst5}
${tc} class change dev eth0 parent 1:1 classid 1:16 htb ${PARMS}prio 7 rate ${UpRate6}Kbit ceil ${UpCeil6}Kbit burst ${UpBurst6} cburst ${UpCburst6}
${tc} class change dev eth0 parent 1:1 classid 1:17 htb ${PARMS}prio 6 rate ${UpRate7}Kbit ceil ${UpCeil7}Kbit burst ${UpBurst7} cburst ${UpCburst7}
}
#################### DO NOT MODIFY BELOW #####################
#################### DO NOT MODIFY BELOW #####################
#################### DO NOT MODIFY BELOW #####################
#################### DO NOT MODIFY BELOW #####################
#################### DO NOT MODIFY BELOW #####################
#################### DO NOT MODIFY BELOW #####################
#################### DO NOT MODIFY BELOW #####################
#################### DO NOT MODIFY BELOW #####################
#################### DO NOT MODIFY BELOW #####################
#################### DO NOT MODIFY BELOW #####################
#################### DO NOT MODIFY BELOW #####################
webpath='/jffs/scripts/www_FreshJR_QoS_Stats.asp' #path of FreshJR_QoS_Stats.asp
#marks for iptable rules
Net_mark_down="0x80090001"
VOIP_mark_down="0x80060001" # Marks for iptables variant of download rules
Gaming_mark_down="0x80080001" # Note these marks are same as filter match/mask combo but have a 1 at the end. That trailing 1 prevents them from being caught by unidentified mask
Others_mark_down="0x800a0001"
Web_mark_down="0x800d0001"
Streaming_mark_down="0x80040001"
Downloads_mark_down="0x80030001"
Default_mark_down="0x803f0001"
Net_mark_up="0x40090001"
VOIP_mark_up="0x40060001" # Marks for iptables variant of upload rules
Gaming_mark_up="0x40080001" # Note these marks are same as filter match/mask combo but have a 1 at the end. That trailing 1 prevents them from being caught by unidentified mask
Others_mark_up="0x400a0001"
Web_mark_up="0x400d0001"
Streaming_mark_up="0x40040001"
Downloads_mark_up="0x40030001"
Default_mark_up="0x403f0001"
set_tc_variables(){
if [ -e "/usr/sbin/realtc" ] ; then
tc="realtc"
else
tc="tc"
fi
#read order of QOS categories
Defaults="1:17"
Net="1:10"
flowid=0
while read -r line; # reads users order of QOS categories
do
#logger -s "${line} ${flowid}"
case ${line} in
'0')
VOIP="1:1${flowid}"
eval "Cat${flowid}DownBandPercent=${drp1}"
eval "Cat${flowid}UpBandPercent=${urp1}"
eval "Cat${flowid}DownCeilPercent=${dcp1}"
eval "Cat${flowid}UpCeilPercent=${ucp1}"
;;
'1')
Downloads="1:1${flowid}"
eval "Cat${flowid}DownBandPercent=${drp7}"
eval "Cat${flowid}UpBandPercent=${urp7}"
eval "Cat${flowid}DownCeilPercent=${dcp7}"
eval "Cat${flowid}UpCeilPercent=${ucp7}"
;;
'4')
Streaming="1:1${flowid}"
eval "Cat${flowid}DownBandPercent=${drp5}"
eval "Cat${flowid}UpBandPercent=${urp5}"
eval "Cat${flowid}DownCeilPercent=${dcp5}"
eval "Cat${flowid}UpCeilPercent=${ucp5}"
;;
'7')
Others="1:1${flowid}"
eval "Cat${flowid}DownBandPercent=${drp3}"
eval "Cat${flowid}UpBandPercent=${urp3}"
eval "Cat${flowid}DownCeilPercent=${dcp3}"
eval "Cat${flowid}UpCeilPercent=${ucp3}"
;;
'8')
Gaming="1:1${flowid}"
eval "Cat${flowid}DownBandPercent=${drp2}"
eval "Cat${flowid}UpBandPercent=${urp2}"
eval "Cat${flowid}DownCeilPercent=${dcp2}"
eval "Cat${flowid}UpCeilPercent=${ucp2}"
;;
'9')
#net control
flowid=0
;;
'13')
Web="1:1${flowid}"
eval "Cat${flowid}DownBandPercent=${drp4}"
eval "Cat${flowid}UpBandPercent=${urp4}"
eval "Cat${flowid}DownCeilPercent=${dcp4}"
eval "Cat${flowid}UpCeilPercent=${ucp4}"
;;
esac
firstchar="${line%%[0-9]*}"
if [ "${firstchar}" == "[" ] ; then
flowid=$((flowid + 1))
#logger -s "flowid = ${flowid} ==========="
fi
done </;/g' | tr -cd ';' | wc -c) -ne 20 ] ; then
$(nvram set fb_comment=";;;;;;>;;;;;;>;;;;;;")
fi
if [ $(nvram get fb_email_dbg | sed 's/>/;/g' | tr -cd ';' | wc -c) -ne 48 ] ; then
$(nvram set fb_email_dbg=";;;;;;>;>;>;>;>>>5;20;15;10;10;30;5;5>100;100;100;100;100;100;100;100>5;20;15;30;10;10;5;5>100;100;100;100;100;100;100;100")
fi
read \
e1 e2 e3 e4 e5 e6 e7 \
f1 f2 f3 f4 f5 f6 f7 \
g1 g2 g3 g4 g5 g6 g7 \
</;/g' )
EOF
read \
h1 h2 h3 h4 h5 h6 h7 \
r1 d1 \
r2 d2 \
r3 d3 \
r4 d4 \
gameCIDR \
ruleFLAG \
drp0 drp1 drp2 drp3 drp4 drp5 drp6 drp7 \
dcp0 dcp1 dcp2 dcp3 dcp4 dcp5 dcp6 dcp7 \
urp0 urp1 urp2 urp3 urp4 urp5 urp6 urp7 \
ucp0 ucp1 ucp2 ucp3 ucp4 ucp5 ucp6 ucp7 \
</;/g' )
EOF
IFS=$OLDIFS
#Verify each read nvram rate is between 5-100 (disabled unless needed in future)
# [ "${drp0//[^0-9]}" -ge "5" ] && [ "${drp0//[^0-9]}" -le "100" ] && drp0="5"
# [ "${drp1//[^0-9]}" -ge "5" ] && [ "${drp1//[^0-9]}" -le "100" ] && drp1="20"
# [ "${drp2//[^0-9]}" -ge "5" ] && [ "${drp2//[^0-9]}" -le "100" ] && drp2="15"
# [ "${drp3//[^0-9]}" -ge "5" ] && [ "${drp3//[^0-9]}" -le "100" ] && drp3="10"
# [ "${drp4//[^0-9]}" -ge "5" ] && [ "${drp4//[^0-9]}" -le "100" ] && drp4="10"
# [ "${drp5//[^0-9]}" -ge "5" ] && [ "${drp5//[^0-9]}" -le "100" ] && drp5="30"
# [ "${drp6//[^0-9]}" -ge "5" ] && [ "${drp6//[^0-9]}" -le "100" ] && drp6="5"
# [ "${drp7//[^0-9]}" -ge "5" ] && [ "${drp7//[^0-9]}" -le "100" ] && drp7="5"
# [ "${dcp0//[^0-9]}" -ge "5" ] && [ "${dcp0//[^0-9]}" -le "100" ] && dcp0="100"
# [ "${dcp1//[^0-9]}" -ge "5" ] && [ "${dcp1//[^0-9]}" -le "100" ] && dcp1="100"
# [ "${dcp2//[^0-9]}" -ge "5" ] && [ "${dcp2//[^0-9]}" -le "100" ] && dcp2="100"
# [ "${dcp3//[^0-9]}" -ge "5" ] && [ "${dcp3//[^0-9]}" -le "100" ] && dcp3="100"
# [ "${dcp4//[^0-9]}" -ge "5" ] && [ "${dcp4//[^0-9]}" -le "100" ] && dcp4="100"
# [ "${dcp5//[^0-9]}" -ge "5" ] && [ "${dcp5//[^0-9]}" -le "100" ] && dcp5="100"
# [ "${dcp6//[^0-9]}" -ge "5" ] && [ "${dcp6//[^0-9]}" -le "100" ] && dcp6="100"
# [ "${dcp7//[^0-9]}" -ge "5" ] && [ "${dcp7//[^0-9]}" -le "100" ] && dcp7="100"
# [ "${urp0//[^0-9]}" -ge "5" ] && [ "${urp0//[^0-9]}" -le "100" ] && urp0="5"
# [ "${urp1//[^0-9]}" -ge "5" ] && [ "${urp1//[^0-9]}" -le "100" ] && urp1="20"
# [ "${urp2//[^0-9]}" -ge "5" ] && [ "${urp2//[^0-9]}" -le "100" ] && urp2="15"
# [ "${urp3//[^0-9]}" -ge "5" ] && [ "${urp3//[^0-9]}" -le "100" ] && urp3="30"
# [ "${urp4//[^0-9]}" -ge "5" ] && [ "${urp4//[^0-9]}" -le "100" ] && urp4="10"
# [ "${urp5//[^0-9]}" -ge "5" ] && [ "${urp5//[^0-9]}" -le "100" ] && urp5="10"
# [ "${urp6//[^0-9]}" -ge "5" ] && [ "${urp6//[^0-9]}" -le "100" ] && urp6="5"
# [ "${urp7//[^0-9]}" -ge "5" ] && [ "${urp7//[^0-9]}" -le "100" ] && urp7="5"
# [ "${ucp0//[^0-9]}" -ge "5" ] && [ "${ucp0//[^0-9]}" -le "100" ] && ucp0="100"
# [ "${ucp1//[^0-9]}" -ge "5" ] && [ "${ucp1//[^0-9]}" -le "100" ] && ucp1="100"
# [ "${ucp2//[^0-9]}" -ge "5" ] && [ "${ucp2//[^0-9]}" -le "100" ] && ucp2="100"
# [ "${ucp3//[^0-9]}" -ge "5" ] && [ "${ucp3//[^0-9]}" -le "100" ] && ucp3="100"
# [ "${ucp4//[^0-9]}" -ge "5" ] && [ "${ucp4//[^0-9]}" -le "100" ] && ucp4="100"
# [ "${ucp5//[^0-9]}" -ge "5" ] && [ "${ucp5//[^0-9]}" -le "100" ] && ucp5="100"
# [ "${ucp6//[^0-9]}" -ge "5" ] && [ "${ucp6//[^0-9]}" -le "100" ] && ucp6="100"
# [ "${ucp7//[^0-9]}" -ge "5" ] && [ "${ucp7//[^0-9]}" -le "100" ] && ucp7="100"
#takes protocol saved in nvram and makes it lower case
e3=$(echo ${e3} | tr '[A-Z]' '[a-z]')
f3=$(echo ${f3} | tr '[A-Z]' '[a-z]')
g3=$(echo ${g3} | tr '[A-Z]' '[a-z]')
h3=$(echo ${h3} | tr '[A-Z]' '[a-z]')
}
## helper function to save nvram variables in csv format
save_nvram(){
$(nvram set fb_comment="${e1};${e2};${e3};${e4};${e5};${e6};${e7}>${f1};${f2};${f3};${f4};${f5};${f6};${f7}>${g1};${g2};${g3};${g4};${g5};${g6};${g7}")
$(nvram set fb_email_dbg="${h1};${h2};${h3};${h4};${h5};${h6};${h7}>${r1};${d1}>${r2};${d2}>${r3};${d3}>${r4};${d4}>${gameCIDR}>${ruleFLAG}>${drp0};${drp1};${drp2};${drp3};${drp4};${drp5};${drp6};${drp7}>${dcp0};${dcp1};${dcp2};${dcp3};${dcp4};${dcp5};${dcp6};${dcp7}>${urp0};${urp1};${urp2};${urp3};${urp4};${urp5};${urp6};${urp7}>${ucp0};${ucp1};${ucp2};${ucp3};${ucp4};${ucp5};${ucp6};${ucp7}")
$(nvram commit)
}
## helper function for interactive menu mode
dst_2_name()
{
case "$1" in
0) echo "Net Control" ;;
1) echo "Gaming" ;;
2) echo "Streaming" ;;
3) echo "VoIP" ;;
4) echo "Web Surfing" ;;
5) echo "Downloads" ;;
6) echo "Others" ;;
7) echo "Game Downloads" ;;
*) echo "" ;;
esac
}
## helper function for interactive menu mode
mark_2_name()
{
return #function disabled since grep is kinda slow
[ -z "$1" ] && return
cat="$( echo ${1} | head -c2 )"
id="$( echo ${1} | tail -c -5 )"
cat="$(printf "%d" 0x${cat})"
id="$(printf "%d" 0x${id})"
cat /tmp/bwdpi/bwdpi.app.db | grep "^${cat},${id}" | head -n1 | cut -d',' -f4
}
## INTERACTIVE mode - rate main page (overview)
rates(){
echo -en "\033c\e[3J" #clear screen
echo -en '\033[?7l' #disable line wrap
printf '\e[8;30;120t' #set height/width of terminal
echo -e "\033[1;32mFreshJR QOS v${version}\033[0m"
echo "QoS Rates: -------Download------- --------Upload--------"
echo " Minimum Maximum Minimum Maximum"
echo " Reserved Reserved Allowed Allowed"
echo " Bandwidth Bandwidth Bandwidth Bandwidth"
echo " (%) (%) (%) (%) "
echo " ----------------------- -----------------------"
format="%-15s %-13s %-18s %-13s %-4s\n"
printf "${format}" "Net Control" "${drp0}" "${dcp0}" "${urp0}" "${ucp0}"
printf "${format}" "VoIP" "${drp1}" "${dcp1}" "${urp1}" "${ucp1}"
printf "${format}" "Gaming" "${drp2}" "${dcp2}" "${urp2}" "${ucp2}"
printf "${format}" "Others" "${drp3}" "${dcp3}" "${urp3}" "${ucp3}"
printf "${format}" "Web Surfing" "${drp4}" "${dcp4}" "${urp4}" "${ucp4}"
printf "${format}" "Streaming" "${drp5}" "${dcp5}" "${urp5}" "${ucp5}"
printf "${format}" "Game Downloads" "${drp6}" "${dcp6}" "${urp6}" "${ucp6}"
printf "${format}" "File Downloads" "${drp7}" "${dcp7}" "${urp7}" "${ucp7}"
echo ""
echo "Available actions:"
echo ""
echo "1) Minimum Reserved Bandwidth -- Download"
echo "2) Minimum Reserved Bandwidth -- Upload"
echo ""
echo "3) Maximum Allowed Bandwidth -- Download"
echo "4) Maximum Allowed Bandwidth -- Upload"
echo ""
echo "r) Reset Values to Defaults"
echo "s) Save & Exit"
echo "e) Exit"
echo -en '\033[?7h' #enable line wrap
echo ""
echo -n "What would you like to do (Enter 1-10): "
read input
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
case $input in
1)
echo "Minimum Reserved Bandwidth"
read -p " Net Control : " in0
read -p " Voip : " in1
read -p " Gaming : " in2
read -p " Others : " in3
read -p " Web Surfing : " in4
read -p " Streaming : " in5
read -p " Game Downloads : " in6
read -p " File Downloads : " in7
[ "${in0//[^0-9]}" -ge "5" ] && [ "${in0//[^0-9]}" -le "100" ] && drp0="${in0//[^0-9]}"
[ "${in1//[^0-9]}" -ge "5" ] && [ "${in1//[^0-9]}" -le "100" ] && drp1="${in1//[^0-9]}"
[ "${in2//[^0-9]}" -ge "5" ] && [ "${in2//[^0-9]}" -le "100" ] && drp2="${in2//[^0-9]}"
[ "${in3//[^0-9]}" -ge "5" ] && [ "${in3//[^0-9]}" -le "100" ] && drp3="${in3//[^0-9]}"
[ "${in4//[^0-9]}" -ge "5" ] && [ "${in4//[^0-9]}" -le "100" ] && drp4="${in4//[^0-9]}"
[ "${in5//[^0-9]}" -ge "5" ] && [ "${in5//[^0-9]}" -le "100" ] && drp5="${in5//[^0-9]}"
[ "${in6//[^0-9]}" -ge "5" ] && [ "${in6//[^0-9]}" -le "100" ] && drp6="${in6//[^0-9]}"
[ "${in7//[^0-9]}" -ge "5" ] && [ "${in7//[^0-9]}" -le "100" ] && drp7="${in7//[^0-9]}"
rates
;;
2)
echo "Minimum Reserved Bandwidth"
read -p " Net Control : " in0
read -p " Voip : " in1
read -p " Gaming : " in2
read -p " Others : " in3
read -p " Web Surfing : " in4
read -p " Streaming : " in5
read -p " Game Downloads : " in6
read -p " File Downloads : " in7
[ "${in0//[^0-9]}" -ge "5" ] && [ "${in0//[^0-9]}" -le "100" ] && urp0="${in0//[^0-9]}"
[ "${in1//[^0-9]}" -ge "5" ] && [ "${in1//[^0-9]}" -le "100" ] && urp1="${in1//[^0-9]}"
[ "${in2//[^0-9]}" -ge "5" ] && [ "${in2//[^0-9]}" -le "100" ] && urp2="${in2//[^0-9]}"
[ "${in3//[^0-9]}" -ge "5" ] && [ "${in3//[^0-9]}" -le "100" ] && urp3="${in3//[^0-9]}"
[ "${in4//[^0-9]}" -ge "5" ] && [ "${in4//[^0-9]}" -le "100" ] && urp4="${in4//[^0-9]}"
[ "${in5//[^0-9]}" -ge "5" ] && [ "${in5//[^0-9]}" -le "100" ] && urp5="${in5//[^0-9]}"
[ "${in6//[^0-9]}" -ge "5" ] && [ "${in6//[^0-9]}" -le "100" ] && urp6="${in6//[^0-9]}"
[ "${in7//[^0-9]}" -ge "5" ] && [ "${in7//[^0-9]}" -le "100" ] && urp7="${in7//[^0-9]}"
rates
;;
3)
echo "Minimum Reserved Bandwidth"
read -p " Net Control : " in0
read -p " Voip : " in1
read -p " Gaming : " in2
read -p " Others : " in3
read -p " Web Surfing : " in4
read -p " Streaming : " in5
read -p " Game Downloads : " in6
read -p " File Downloads : " in7
[ "${in0//[^0-9]}" -ge "5" ] && [ "${in0//[^0-9]}" -le "100" ] && dcp0="${in0//[^0-9]}"
[ "${in1//[^0-9]}" -ge "5" ] && [ "${in1//[^0-9]}" -le "100" ] && dcp1="${in1//[^0-9]}"
[ "${in2//[^0-9]}" -ge "5" ] && [ "${in2//[^0-9]}" -le "100" ] && dcp2="${in2//[^0-9]}"
[ "${in3//[^0-9]}" -ge "5" ] && [ "${in3//[^0-9]}" -le "100" ] && dcp3="${in3//[^0-9]}"
[ "${in4//[^0-9]}" -ge "5" ] && [ "${in4//[^0-9]}" -le "100" ] && dcp4="${in4//[^0-9]}"
[ "${in5//[^0-9]}" -ge "5" ] && [ "${in5//[^0-9]}" -le "100" ] && dcp5="${in5//[^0-9]}"
[ "${in6//[^0-9]}" -ge "5" ] && [ "${in6//[^0-9]}" -le "100" ] && dcp6="${in6//[^0-9]}"
[ "${in7//[^0-9]}" -ge "5" ] && [ "${in7//[^0-9]}" -le "100" ] && dcp7="${in7//[^0-9]}"
rates
;;
4)
echo "Minimum Reserved Bandwidth"
read -p " Net Control : " in0
read -p " Voip : " in1
read -p " Gaming : " in2
read -p " Others : " in3
read -p " Web Surfing : " in4
read -p " Streaming : " in5
read -p " Game Downloads : " in6
read -p " File Downloads : " in7
[ "${in0//[^0-9]}" -ge "5" ] && [ "${in0//[^0-9]}" -le "100" ] && ucp0="${in0//[^0-9]}"
[ "${in1//[^0-9]}" -ge "5" ] && [ "${in1//[^0-9]}" -le "100" ] && ucp1="${in1//[^0-9]}"
[ "${in2//[^0-9]}" -ge "5" ] && [ "${in2//[^0-9]}" -le "100" ] && ucp2="${in2//[^0-9]}"
[ "${in3//[^0-9]}" -ge "5" ] && [ "${in3//[^0-9]}" -le "100" ] && ucp3="${in3//[^0-9]}"
[ "${in4//[^0-9]}" -ge "5" ] && [ "${in4//[^0-9]}" -le "100" ] && ucp4="${in4//[^0-9]}"
[ "${in5//[^0-9]}" -ge "5" ] && [ "${in5//[^0-9]}" -le "100" ] && ucp5="${in5//[^0-9]}"
[ "${in6//[^0-9]}" -ge "5" ] && [ "${in6//[^0-9]}" -le "100" ] && ucp6="${in6//[^0-9]}"
[ "${in7//[^0-9]}" -ge "5" ] && [ "${in7//[^0-9]}" -le "100" ] && ucp7="${in7//[^0-9]}"
rates
;;
'r'|'R')
drp0="5"
drp1="20"
drp2="15"
drp3="10"
drp4="10"
drp5="30"
drp6="5"
drp7="5"
dcp0="100"
dcp1="100"
dcp2="100"
dcp3="100"
dcp4="100"
dcp5="100"
dcp6="100"
dcp7="100"
urp0="5"
urp1="20"
urp2="15"
urp3="30"
urp4="10"
urp5="10"
urp6="5"
urp7="5"
ucp0="100"
ucp1="100"
ucp2="100"
ucp3="100"
ucp4="100"
ucp5="100"
ucp6="100"
ucp7="100"
rates
;;
's'|'S')
save_nvram
echo " Saving Changes"
[ "$(nvram get qos_enable)" == "1" ] && prompt_restart
return 1
;;
'e'|'E')
echo -e "\033[1;31;7m No Changes have been saved \033[0m"
echo ""
return 0 ;;
*)
rates ;;
esac
}
## INTERACTIVE mode - rule main page (overview)
rules(){
echo -en "\033c\e[3J" #clear screen
echo -en '\033[?7l' #disable line wrap
printf '\e[8;30;120t' #set height/width of terminal
echo -e "\033[1;32mFreshJR QOS v${version}\033[0m"
echo "Custom QoS Rules:"
echo " Local IP Remote IP Proto Local Port Remote Port Mark Dst"
printf '1) Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$e1" "$e2" "$e3" "$e4" "$e5" "$e6" "$([ -z $e7 ] || echo "--> $(dst_2_name $e7)")"
printf '2) Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$f1" "$f2" "$f3" "$f4" "$f5" "$f6" "$([ -z $f7 ] || echo "--> $(dst_2_name $f7)")"
printf '3) Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$g1" "$g2" "$g3" "$g4" "$g5" "$g6" "$([ -z $g7 ] || echo "--> $(dst_2_name $g7)")"
printf '4) Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$h1" "$h2" "$h3" "$h4" "$h5" "$h6" "$([ -z $h7 ] || echo "--> $(dst_2_name $h7)")"
printf '5) Gameip %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "${gameCIDR}" "" "$([ -z $gameCIDR ] || echo "both")" "" "$([ -z $gameCIDR ] || echo "!80:443")" "$([ -z $gameCIDR ] || echo "000000")" "--> Gaming"
printf '6) Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r1)" "$r1" "$([ -z $d1 ] || echo "--> $(dst_2_name $d1)")"
printf '7) Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r2)" "$r2" "$([ -z $d2 ] || echo "--> $(dst_2_name $d2)")"
printf '8) Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r3)" "$r3" "$([ -z $d3 ] || echo "--> $(dst_2_name $d3)")"
printf '9) Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r4)" "$r4" "$([ -z $d4 ] || echo "--> $(dst_2_name $d4)")"
echo ""
echo "s) Save & Exit"
echo "e) Exit"
echo -en '\033[?7h' #enable line wrap
echo ""
echo -n "Select Rule to Modify (Enter 1-9): "
read input
case $input in
'1') iprule e1 e2 e3 e4 e5 e6 e7 "Rule 1";;
'2') iprule f1 f2 f3 f4 f5 f6 f7 "Rule 2";;
'3') iprule g1 g2 g3 g4 g5 g6 g7 "Rule 3";;
'4') iprule h1 h2 h3 h4 h5 h6 h7 "Rule 4";;
'5') gamerule ;;
'6') apprule r1 d1 "Appdb 1" ;;
'7') apprule r2 d2 "Appdb 2" ;;
'8') apprule r3 d3 "Appdb 3" ;;
'9') apprule r4 d4 "Appdb 4" ;;
's'|'S')
echo ""
echo "Saving Changes"
save_nvram
[ "$(nvram get qos_enable)" == "1" ] && prompt_restart
return 1
;;
'e'|'E')
echo ""
echo -e "\033[1;31;7m No Changes have been saved \033[0m"
echo ""
return 0 ;;
*)
rules ;;
esac
}
## INTERACTIVE mode - modify iptable rule
iprule()
{
echo -en "\033c\e[3J"
echo -en '\033[?7l' #disable line wrap
echo -e "\033[1;32mFreshJR QOS v${version} \033[0m"
echo "Modifying ${8}"
echo -n "1) Name " && sed -nE 's/var rulename'${8//[^0-9]/}'="(.*?)";/\1/p' "${webpath}"
echo -n "2) Local IP " && eval "echo \${$1}"
echo -n "3) Remote IP " && eval "echo \${$2}"
echo -n "4) Local Port " && [ -z $(eval "echo \${$4}") ] && echo || eval "echo \${$3} \${$4}" #if ${4} is blank then leave field blank else populate
echo -n "5) Remote Port " && [ -z $(eval "echo \${$5}") ] && echo || eval "echo \${$3} \${$5}" #if ${5} is blank then leave field blank else populate
echo -n "6) Protocol " && eval "echo \${$3}"
echo -n "7) QoS Mark " && eval "echo \${$6}"
echo -n "8) Destination " && eval "dst_2_name \${$7}"
echo ""
echo "r) Reset / Disable"
echo "e) Go Back"
echo ""
in_progress=1
while [ ${in_progress} -eq 1 ] ; do
echo -n "Select Parameter to Modify (Enter 1-8): "
read input
echo -en "\033[1A\r\033[0K" #clear user input prompt
case $input in
1) #name
echo -ne "\033[1;32m"
echo " WebUI Rule Name"
echo ""
echo -ne "\033[0m"
echo -n " Name(Rule${8//[^0-9]/})="
#read user input
read input
if [ -z $input ] ; then
input="${8// /}"
fi
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
#make changes to WebUI.asp page
echo "$( cat "${webpath}" | sed -E 's/var rulename'"${8//[^0-9]/}"'="(.*?)";/var rulename'"${8//[^0-9]/}"'="'"${input}"'";/')" > "${webpath}"
#update table entry
echo -en "\033[3;0f\033[0K" #move to line 3 pos 0 \ erase to end
echo -n "1) Name " && sed -nE 's/var rulename'${8//[^0-9]/}'="(.*?)";/\1/p' "${webpath}"
;;
2) #local ip
#show valid syntax
echo -ne "\033[1;32m"
echo " Local IP Syntax: 192.168.X.XXX or !192.168.X.XXX"
echo " 192.168.X.XXX/CIDR or !192.168.X.XXX/CIDR"
echo ""
echo -ne "\033[0m"
echo -n " Local IP="
#read user input
read input
eval "$1=\$input"
#clear syntax+input
echo -en "\033[1A\r\033[0K" #up one line \ beginning line \ erase to end
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
#update table entry
echo -en "\033[4;0f\033[0K" #move to line 4 pos 0 \ erase to end
echo -n "2) Local IP " && eval "echo \${$1}"
;;
3) #remote ip
#show valid syntax
echo -ne "\033[1;32m"
echo " Remote IP Syntax: 75.75.75.75 or !75.75.75.75 "
echo " 75.75.75.75/CIDR or !75.75.75.75/CIDR"
echo ""
echo -ne "\033[0m"
echo -n " Remote IP="
#read user input
read input
eval "$2=\$input"
#clear syntax+input
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
#update table entry
echo -en "\033[5;0f\033[0K" #move to line 5 pos 0 \ erase to end
echo -n "3) Remote IP " && eval "echo \${$2}"
;;
4) #local port
#show valid syntax
echo -ne "\033[1;32m"
echo " Local Port Syntax: XXX or !XXX"
echo " XXXX:YYYY or !XXXX:YYYY"
echo " XXX,YYY,ZZZ or !XXX,YYY,ZZZ"
echo ""
echo -ne "\033[0m"
echo -n " Local Port="
#read user input
read input
eval "$4=\$input"
if [ -z $input ] ; then
#if port entry blank --> do not continue
#clear syntax + input
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
#if both ports are blank then reset protocol variable
[ -z $(eval "echo \${$5}") ] && eval "$3='both'"
else
#else port was defined --> ask for protocol definition
#show additional valid syntax
echo -ne "\033[1;32m"
echo ""
echo " Protocol Syntax: tcp"
echo " udp"
echo " both"
echo ""
echo -ne "\033[0m"
echo -n " Protocol="
#read user input
read user input
input=$(echo ${input} | tr '[A-Z]' '[a-z]')
if [ "${input}" = "udp" ] || [ "${input}" = "both" ] ; then
eval "$3=\$input"
else
eval "$3='tcp'"
fi
#clear syntax+input
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
fi
#update table entry
echo -en "\033[8;0f\033[0K" #move to line 8 pos 0 \ erase to end
echo -en "\033[7;0f\033[0K" #move to line 7 pos 0 \ erase to end
echo -en "\033[6;0f\033[0K" #move to line 6 pos 0 \ erase to end
echo -n "4) Local Port " && [ -z $(eval "echo \${$4}") ] && echo || eval "echo \${$3} \${$4}" #if ${4} is blank then leave field blank else populate
echo -n "5) Remote Port " && [ -z $(eval "echo \${$5}") ] && echo || eval "echo \${$3} \${$5}" #if ${5} is blank then leave field blank else populate
echo -n "6) Protocol " && eval "echo \${$3}"
;;
5) #remote port
#show valid syntax
echo -ne "\033[1;32m"
echo " Remote Port Syntax: XXX or !XXX"
echo " XXXX:YYYY or !XXXX:YYYY"
echo " XXX,YYY,ZZZ or !XXX,YYY,ZZZ"
echo ""
echo -ne "\033[0m"
echo -n " Remote Port="
#read user input
read input
eval "$5=\$input"
if [ -z $input ] ; then
#if port entry blank --> do not continue
#clear syntax + input
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
#if both ports are blank then also clear protocol variable
[ -z $(eval "echo \${$4}") ] && eval "$3='both'"
else
#else port was defined --> ask for protocol definition
#show additional valid syntax
echo -ne "\033[1;32m"
echo ""
echo " Protocol Syntax: tcp"
echo " udp"
echo " both"
echo ""
echo -ne "\033[0m"
echo -n " Protocol="
#read user input
read input
input=$(echo ${input} | tr '[A-Z]' '[a-z]')
if [ "${input}" = "udp" ] || [ "${input}" = "both" ] ; then
eval "$3=\$input"
else
eval "$3='tcp'"
fi
#clear syntax+input
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
fi
#update table entry
echo -en "\033[8;0f\033[0K" #move to line 8 pos 0 \ erase to end
echo -en "\033[7;0f\033[0K" #move to line 7 pos 0 \ erase to end
echo -en "\033[6;0f\033[0K" #move to line 6 pos 0 \ erase to end
echo -n "4) Local Port " && [ -z $(eval "echo \${$4}") ] && echo || eval "echo \${$3} \${$4}" #if ${4} is blank then leave field blank else populate
echo -n "5) Remote Port " && [ -z $(eval "echo \${$5}") ] && echo || eval "echo \${$3} \${$5}" #if ${5} is blank then leave field blank else populate
echo -n "6) Protocol " && eval "echo \${$3}"
;;
6) #protocol
#show valid syntax
echo -ne "\033[1;32m"
echo " Protocol Syntax: tcp"
echo " udp"
echo " both"
echo ""
echo -ne "\033[0m"
echo -n " Protocol="
#read user input
read input
input=$(echo ${input} | tr '[A-Z]' '[a-z]')
if [ "${input}" = "udp" ] || [ "${input}" = "tcp" ] ; then
eval "$3=\$input"
else
eval "$3='both'"
fi
#clear sytnax + input
echo -en "\033[1A\r\033[0K" #up one line \ beginning line \ erase to end
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
#update table entry
echo -en "\033[8;0f\033[0K" #move to line 8 pos 0 \ erase to end
echo -en "\033[7;0f\033[0K" #move to line 7 pos 0 \ erase to end
echo -en "\033[6;0f\033[0K" #move to line 6 pos 0 \ erase to end
echo -n "4) Local Port " && [ -z $(eval "echo \${$4}") ] && echo || eval "echo \${$3} \${$4}" #if ${4} is blank then leave field blank else populate
echo -n "5) Remote Port " && [ -z $(eval "echo \${$5}") ] && echo || eval "echo \${$3} \${$5}" #if ${5} is blank then leave field blank else populate
echo -n "6) Protocol " && eval "echo \${$3}"
;;
7) #qos mark
#show valid syntax
echo -ne "\033[1;32m"
echo " QoS Mark Syntax (hex): XXYYYY"
echo " Note: YYYY can be **** wildcard"
echo ""
echo -ne "\033[0m"
echo -n " QoS Mark="
#read user input
read input
input=${input//!/}
eval "$6=\$input"
#clear sytnax + input
echo -en "\033[1A\r\033[0K" #up one line \ beginning line \ erase to end
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
#update table entry
echo -en "\033[9;0f\033[0K" #move to line 9 pos 0 \ erase to end
echo -n "7) QoS Mark " && eval "echo \${$6}"
;;
8) #packetdestination
#show valid syntax
echo -ne "\033[1;32m"
echo " Destination Syntax: 0-7"
echo ""
echo " Reference: "
echo " 0) Net Control"
echo " 1) VoIP"
echo " 2) Gaming"
echo " 3) Others"
echo " 4) Web Surfing"
echo " 5) Streaming"
echo " 6) Game Downloads"
echo " 7) Downloads"
echo ""
echo -ne "\033[0m"
echo -n " Destination="
#read user input
read input
case $input in
0) eval "$7='0'" ;; #net
1) eval "$7='3'" ;; #voip
2) eval "$7='1'" ;; #game
3) eval "$7='6'" ;; #other
4) eval "$7='4'" ;; #web
5) eval "$7='2'" ;; #video
6) eval "$7='7'" ;; #game download
7) eval "$7='5'" ;; #downloads
*) eval "$7='0'" ;; #invalid input -> net
esac
#clear syntax + input
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
#update table entry
echo -en "\033[10;0f\033[0K" #move to line 10 pos 0 \ erase to end
echo -n "8) Destination " && eval "dst_2_name \${$7}" #if all params empty leave blank else populate
;;
'r'|'R') #reset
eval "$1=''"
eval "$2=''"
eval "$3=''"
eval "$4=''"
eval "$5=''"
eval "$6=''"
eval "$7=''"
echo "$( cat "${webpath}" | sed -E 's/var rulename'"${8//[^0-9]/}"'="(.*?)";/var rulename'"${8//[^0-9]/}"'="Rule'"${8//[^0-9]/}"'";/')" > "${webpath}"
in_progress=0
;;
'e'|'E')
in_progress=0
;;
esac
echo -en "\033[15;0f" #set cursor to user prompt original position
done
rules #go back to rules page after modifying individual rule
}
## INTERACTIVE mode - modify gameip range
gamerule()
{
echo -en "\033c\e[3J"
echo -en '\033[?7l' #disable line wrap
echo -e "\033[1;32mFreshJR QOS v${version} \033[0m"
echo "Modifying Gaming Device IP Range "
echo -ne "\033[1;32m"
echo ""
echo " Gaming Device IP Syntax: 192.168.X.XXX "
echo " 192.168.X.XXX/CIDR"
echo ""
echo -ne "\033[0m"
echo -ne " Gaming Device IP="
read input
if [ "$( echo $input | tr -cd '.' | wc -c )" -eq "3" ] ; then
gameCIDR=${input}
else
gameCIDR=''
fi
rules
}
## INTERACTIVE mode - modify appdb TC rule
apprule()
{
echo -en "\033c\e[3J"
echo -en '\033[?7l' #disable line wrap
echo -e "\033[1;32mFreshJR QOS v${version} \033[0m"
echo "Modifying ${3}"
echo -n "1) QoS Mark " && eval "echo \${$1}"
echo -n "2) Destination " && eval "dst_2_name \${$2}"
echo ""
echo "r) Reset / Disable"
echo "e) Go Back"
echo ""
in_progress=1
while [ ${in_progress} -eq 1 ] ; do
echo -n "Select Parameter to Modify (Enter 1-2): "
read input
echo -en "\033[1A\r\033[0K" #clear user input prompt
case $input in
1) #QoS MARK
#show valid syntax
echo -ne "\033[1;32m"
echo " QoS Mark Syntax: XXYYYY"
echo ""
echo -ne "\033[0m"
echo -n " QoS Mark="
#read user input
read input
eval "$1=\$input"
#clear syntax + input
echo -en "\033[1A\r\033[0K" #up one line \ beginning line \ erase to end
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
#update table entry
echo -en "\033[3;0f\033[0K" #move to line 3 pos 0 \ erase to end
echo -n "1) QoS Mark " && eval "echo \${$1}"
if [ -z $(eval "echo \${$2}") ] ; then
echo -en "\033[9;0f"
#show valid syntax
echo -ne "\033[1;32m"
echo " Destination Syntax: 0-7"
echo ""
echo " Reference: "
echo " 0) Net Control"
echo " 1) VoIP"
echo " 2) Gaming"
echo " 3) Others"
echo " 4) Web Surfing"
echo " 5) Streaming"
echo " 6) Game Downloads"
echo " 7) Downloads"
echo ""
echo -ne "\033[0m"
echo -n " Destination="
#read user input
read input
case $input in
0) eval "$2='0'" ;; #net
1) eval "$2='3'" ;; #voip
2) eval "$2='1'" ;; #game
3) eval "$2='6'" ;; #other
4) eval "$2='4'" ;; #web
5) eval "$2='2'" ;; #video
6) eval "$2='7'" ;; #game download
7) eval "$2='5'" ;; #downloads
*) eval "$2=''" ;; #invalid input -> disable
esac
#clear syntax + input
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
#update table entry
echo -en "\033[4;0f\033[0K" #move to line 4 pos 0 \ erase to end
echo -n "2) Destination " && eval "dst_2_name \${$2}"
fi
;;
2) #packet destination
#show valid syntax
echo -ne "\033[1;32m"
echo " Destination Syntax: 0-7"
echo ""
echo " Reference: "
echo " 0) Net Control"
echo " 1) VoIP"
echo " 2) Gaming"
echo " 3) Others"
echo " 4) Web Surfing"
echo " 5) Streaming"
echo " 6) Game Downloads"
echo " 7) Downloads"
echo ""
echo -ne "\033[0m"
echo -n " Destination="
#read user input
read input
case $input in
0) eval "$2='0'" ;; #net
1) eval "$2='3'" ;; #voip
2) eval "$2='1'" ;; #game
3) eval "$2='6'" ;; #other
4) eval "$2='4'" ;; #web
5) eval "$2='2'" ;; #video
6) eval "$2='7'" ;; #game download
7) eval "$2='5'" ;; #downloads
*) eval "$2=''" ;; #invalid input -> disable
esac
#clear syntax + input
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
echo -en "\033[1A\r\033[0K"
#update table entry
echo -en "\033[4;0f\033[0K" #move to line 4 pos 0 \ erase to end
echo -n "2) Destination " && eval "dst_2_name \${$2}"
;;
'r'|'R') #reset
eval "$1=''"
eval "$2=''"
#apprule $1 $2 "${3}"
in_progress=0
;;
'e'|'E')
in_progress=0
;;
esac
echo -en "\033[9;0f" #set cursor to user prompt original position
done
rules #go back to rules page after modifying individual rule
}
## helper function - parse parameters into tc syntax
parse_tcrule() {
##requires global variables previously set by set_tc_variables
##----------input-----------
##$1 = mark
##$2 = dst
##----------output-----------
##byref sets $3
##byref sets $4
cat="$( echo ${1} | head -c2 )"
id="$( echo ${1} | tail -c -5 )"
#filter field
if [ "$( echo ${1} | wc -c )" -eq "7" ] ; then
if [ "${id}" == "****" ] ; then
DOWN_mark="0x80${1//!/} 0xc03ff0000"
UP_mark="0x40${1//!/} 0xc03ff0000"
else
DOWN_mark="0x80${1//!/} 0xc03fffff"
UP_mark="0x40${1//!/} 0xc03fffff"
fi
else
##return early if mark is less than 6 digits
return
fi
#destination field
case "$2" in
0) flowid=${Net};;
1) flowid=${Gaming};;
2) flowid=${Streaming};;
3) flowid=${VOIP};;
4) flowid=${Web};;
5) flowid=${Downloads};;
6) flowid=${Others};;
7) flowid=${Defaults};;
##return early if destination missing
*) return ;;
esac
#prio field
prio="$(tc filter show dev br0 | grep ${cat}0000 -B1 | tail -2 | cut -d " " -f7 | head -1)"
if [ -z "${prio}" ] ; then
prio="${undf_prio}"
else
prio="$(expr ${prio} - 1)"
fi
down_rule="prio $prio u32 match mark $DOWN_mark flowid $flowid"
up_rule="prio $prio u32 match mark $UP_mark flowid $flowid"
eval "$3=\$down_rule"
eval "$4=\$up_rule"
}
## helper function - parse parameters into iptable syntax
parse_iptablerule() {
##----------input-----------
#$1=local IP accepted XXX.XXX.XXX.XXX or !XXX.XXX.XXX.XXX
#$2=remote IP accepted XXX.XXX.XXX.XXX or !XXX.XXX.XXX.XXX
#$3=protocol accepted tcp or udp
#$4=local port accepted XXXXX or XXXXX:YYYYY or XXX,YYY,ZZZ or !XXXXX or !XXXXX:YYYYY or !XXX,YYY,ZZZ
#$5=remote port accepted XXXXX or XXXXX:YYYYY or XXX,YYY,ZZZ or !XXXXX or !XXXXX:YYYYY or !XXX,YYY,ZZZ
#$6=mark accepted XXYYYY (setting YYYY to **** will filter entire "XX" parent category)
#$7=qos destination accepted 0-7
##----------output-----------
##byref sets $8
##byref sets $9
#local IP
if [ "$( echo ${1} | wc -c )" -gt "1" ] ; then
DOWN_Lip="${1//[^!]*/} -d ${1//!/}"
UP_Lip="${1//[^!]*/} -s ${1//!/}"
else
DOWN_Lip=""
UP_Lip=""
fi
#remote IP
if [ "$( echo ${2} | wc -c )" -gt "1" ] ; then
DOWN_Rip="${2//[^!]*/} -s ${2//!/}"
UP_Rip="${2//[^!]*/} -d ${2//!/}"
else
DOWN_Rip=""
UP_Rip=""
fi
#protocol (required for port rules)
if [ "${3}" = 'tcp' ] || [ "${3}" = 'udp' ] ; then #if tcp/udp
PROTO="-p ${3}"
else
if [ "$( echo ${4} | wc -c )" -gt "1" ] || [ "$( echo ${5} | wc -c )" -gt "1" ] ; then #if both & port rules defined
PROTO="-p both" #"BOTH" gets replaced with tcp & udp during later prior to rule execution
else #if both & port rules not defined
PROTO=""
fi
fi
#local port
if [ "$( echo ${4} | wc -c )" -gt "1" ] ; then
if [ "$( echo ${4} | tr -cd ',' | wc -c )" -ge "1" ] ; then
#multiport XXX,YYY,ZZZ
DOWN_Lport="-m multiport ${4//[^!]*/} --dports ${4//!/}"
UP_Lport="-m multiport ${4//[^!]*/} --sports ${4//!/}"
else
#single port XXX or port range XXX:YYY
DOWN_Lport="${4//[^!]*/} --dport ${4//!/}"
UP_Lport="${4//[^!]*/} --sport ${4//!/}"
fi
else
DOWN_Lport=""
UP_Lport=""
fi
#remote port
if [ "$( echo ${5} | wc -c )" -gt "1" ] ; then
if [ "$( echo ${5} | tr -cd ',' | wc -c )" -ge "1" ] ; then
#multiport XXX,YYY,ZZZ
DOWN_Rport="-m multiport ${5//[^!]*/} --sports ${5//!/}"
UP_Rport="-m multiport ${5//[^!]*/} --dports ${5//!/}"
else
#single port XXX or port range XXX:YYY
DOWN_Rport="${5//[^!]*/} --sport ${5//!/}"
UP_Rport="${5//[^!]*/} --dport ${5//!/}"
fi
else
DOWN_Rport=""
UP_Rport=""
fi
#match mark
if [ "$( echo ${6} | wc -c )" -eq "7" ] ; then
if [ "$( echo ${6} | tail -c -5 )" == "****" ] ; then
DOWN_mark="-m mark --mark 0x80${6//!/}/0xc03f0000"
UP_mark="-m mark --mark 0x40${6//!/}/0xc03f0000"
else
DOWN_mark="-m mark --mark 0x80${6//!/}/0xc03fffff"
UP_mark="-m mark --mark 0x40${6//!/}/0xc03fffff"
fi
else
DOWN_mark=""
UP_mark=""
fi
##if parameters are empty return early
if [ -z "${DOWN_Lip}${DOWN_Rip}${DOWN_Lport}${DOWN_Rport}${DOWN_mark}" ] ; then
return
fi
#destination mark
case "$7" in
0)
DOWN_dst="-j MARK --set-mark ${Net_mark_down}"
UP_dst="-j MARK --set-mark ${Net_mark_up}"
;;
1)
DOWN_dst="-j MARK --set-mark ${Gaming_mark_down}"
UP_dst="-j MARK --set-mark ${Gaming_mark_up}"
;;
2)
DOWN_dst="-j MARK --set-mark ${Streaming_mark_down}"
UP_dst="-j MARK --set-mark ${Streaming_mark_up}"
;;
3)
DOWN_dst="-j MARK --set-mark ${VOIP_mark_down}"
UP_dst="-j MARK --set-mark ${VOIP_mark_up}"
;;
4)
DOWN_dst="-j MARK --set-mark ${Web_mark_down}"
UP_dst="-j MARK --set-mark ${Web_mark_up}"
;;
5)
DOWN_dst="-j MARK --set-mark ${Downloads_mark_down}"
UP_dst="-j MARK --set-mark ${Downloads_mark_up}"
;;
6)
DOWN_dst="-j MARK --set-mark ${Others_mark_down}"
UP_dst="-j MARK --set-mark ${Others_mark_up}"
;;
7)
DOWN_dst="-j MARK --set-mark ${Default_mark_down}"
UP_dst="-j MARK --set-mark ${Default_mark_up}"
;;
*)
##if destinations is empty return early
return
;;
esac
down_rule="$(echo "${DOWN_Lip} ${DOWN_Rip} ${PROTO} ${DOWN_Lport} ${DOWN_Rport} ${DOWN_mark} ${DOWN_dst}" | sed 's/ */ /g')"
up_rule="$(echo "${UP_Lip} ${UP_Rip} ${PROTO} ${UP_Lport} ${UP_Rport} ${UP_mark} ${UP_dst}" | sed 's/ */ /g')"
eval "$8=\$down_rule"
eval "$9=\$up_rule"
}
about(){
echo -en "\033c\e[3J" #clear screen
echo -en '\033[?7l' #disable line wrap
printf '\e[8;41;160t' #set height/width of terminal
echo "FreshJR_QOS v${version} released ${release}"
echo ""
echo 'License'
echo ' FreshJR_QOS is free to use under the GNU General Public License, version 3 (GPL-3.0).'
echo ' https://opensource.org/licenses/GPL-3.0'
echo ""
echo 'For discussion visit this thread:'
echo ' https://www.snbforums.com/threads/release-freshjr-adaptive-qos-improvements-custom-rules-and-inner-workings.36836/'
echo " https://github.com/FreshJR07/FreshJR_QOS (Source Code)"
echo ""
echo -e "\033[1;32mFreshJR QOS v${version} \033[0m"
echo "About"
echo ' Script Changes Unidentified traffic destination away from "Defaults" into "Others"'
echo ' Script Changes HTTPS traffic destination away from "Net Control" into "Web Surfing" '
echo ' Script Changes Guaranteed Bandwidth per QOS category into logical percentages of upload and download.'
echo ""
echo ' Script Repurposes "Defaults" to contain "Game Downloads" '
echo ' "Game Downloads" container moved into 6th position'
echo ' "Lowest Defined" container moved into 7th position'
echo ""
echo ' Script includes misc hardcoded rules '
echo ' (Wifi Calling) - UDP traffic on remote ports 500 & 4500 moved into VOIP'
echo ' (Facetime) - UDP traffic on local ports 16384 - 16415 moved into VOIP '
echo ' (Usenet) - TCP traffic on remote ports 119 & 563 moved into Downloads '
echo ' (Gaming) - Gaming TCP traffic from remote ports 80 & 443 moved into Game Downloads.'
echo ' (Snapchat) - Moved into Others'
echo ' (Speedtest.net) - Moved into Downloads'
echo ' (Google Play) - Moved into Downloads'
echo ' (Apple AppStore)- Moved into Downloads'
echo ' (Advertisement) - Moved into Downloads'
echo ' (VPN Fix) - Router VPN Client upload traffic moved into Downloads instead of whitelisted'
echo ' (VPN Fix) - Router VPN Client download traffic moved into Downloads instead of showing up in Uploads'
echo ' (Gaming Manual) - Unidentified traffic for specified devices, not originating from ports 80/443, moved into "Gaming"'
echo ""
echo 'Gaming Rule Note'
echo ' Gaming traffic originating from ports 80 & 443 is primarily downloads & patches (some lobby/login protocols mixed within)'
echo ' Manually configurable rule will take untracked traffic for specified devices, not originating from server ports 80/443, and place it into Gaming'
echo ' Use of this gaming rule REQUIRES devices to have a continous static ip assignment && this range needs to be passed into the script'
echo ""
echo "How to Use Advanced Functionality"
echo ' Interactive terminal mode can be accessed by running the -menu command:'
echo ' (interactive mode) : /jffs/scripts/FreshJR_QOS -menu'
echo ' Custom rules can be created via the WebUI OR directly accessed by running the -rules command:'
echo ' (custom rules) : /jffs/scripts/FreshJR_QOS -rules'
echo ' Bandwidth allocation per category can be adjusted via the WebUI OR directly accessed by running the -rates command:'
echo ' (custom rates) : /jffs/scripts/FreshJR_QOS -rates'
echo ""
echo 'Development'
echo ' Tested with ASUS AC-68U, FW384.9, using Adaptive QOS with Manual Bandwidth Settings'
echo ' Copyright (C) 2017-2019 FreshJR - All Rights Reserved '
echo -en '\033[?7h' #enable line wrap
}
update(){
echo -en "\033c\e[3J" #clear screen
echo -en '\033[?7l' #disable line wrap
printf '\e[8;30;120t' #set height/width of terminal
echo -e "\033[1;32mFreshJR QOS v${version} \033[0m"
echo "Checking for updates"
echo ""
url="https://raw.githubusercontent.com/FreshJR07/FreshJR_QOS/master/FreshJR_QOS.sh"
remotever=$(curl -fsN --retry 3 ${url} | grep "^version=" | sed -e s/version=//)
if [ "$version" != "$remotever" ]; then
echo " FreshJR QOS v${remotever} is now available!"
echo ""
echo -n " Would you like to update now? [1=Yes 2=No] : "
read yn
echo ""
if ! [ "${yn}" == "1" ] ; then
echo -e "\033[1;31;7m No Changes have been made \033[0m"
echo ""
return 0
fi
else
echo " You have the latest version installed"
echo -n " Would you like to overwrite your existing installation anyway? [1=Yes 2=No] : "
read yn
echo ""
if ! [ "${yn}" == "1" ] ; then
echo -e "\033[1;31;7m No Changes have been made \033[0m"
echo ""
return 0
fi
fi
echo -e "Installing: FreshJR_QOS_v${remotever}"
echo ""
echo "Curl Output:"
curl "https://raw.githubusercontent.com/FreshJR07/FreshJR_QOS/master/FreshJR_QOS.sh" -o /jffs/scripts/FreshJR_QOS --create-dirs && curl "https://raw.githubusercontent.com/FreshJR07/FreshJR_QOS/master/FreshJR_QoS_Stats.asp" -o "${webpath}" && sh /jffs/scripts/FreshJR_QOS -install
exit
}
prompt_restart(){
echo ""
echo -en " Would you like to \033[1;32m[Restart QoS]\033[0m for modifications to take effect? [1=Yes 2=No] : "
read yn
if [ "${yn}" == "1" ] ; then
if grep -q -x '/jffs/scripts/FreshJR_QOS -start $1 & ' /jffs/scripts/firewall-start ; then #RMerlin install
service "restart_qos;restart_firewall"
else #Stock Install
service "restart_qos;restart_firewall"
cru a FreshJR_QOS_run_once "* * * * * /jffs/scripts/FreshJR_QOS -mount &" #cron task so keeps running after terminal is closed
fi
echo ""
else
echo ""
if grep -q -x '/jffs/scripts/FreshJR_QOS -start $1 & ' /jffs/scripts/firewall-start ; then #RMerlin install
echo -e "\033[1;31;7m Remember: [ Restart QOS ] for modifications to take effect \033[0m"
echo ""
else #Stock install
echo -e "\033[1;31;7m Remember: [ Restart Router ] for modifications to take effect \033[0m"
echo ""
fi
fi
}
menu(){
read_nvram
echo -en "\033c\e[3J" #clear screen
echo -en '\033[?7l' #disable line wrap
printf '\e[8;30;120t' #set height/width of terminal
echo -e "\033[1;32mFreshJR QOS v${version} released ${release} \033[0m"
echo " (1) about explain functionality"
echo " (2) update check for updates "
echo ""
echo " (3) QoS rules QoS rules (user defined)"
echo " (4) QoS rates QoS rates (bandwidth allocation per category)"
echo ""
echo " (5) debug traffic control parameters"
echo " (6) debug2 parsed nvram parameters"
echo ""
echo " (u) uninstall uninstall script"
echo ""
echo " (e) exit"
echo ""
echo " Current Setup:"
echo " Local IP Remote IP Proto Local Port Remote Port Mark Dst"
printf ' Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$e1" "$e2" "$e3" "$e4" "$e5" "$e6" "$([ -z $e7 ] || echo "--> $(dst_2_name $e7)")"
printf ' Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$f1" "$f2" "$f3" "$f4" "$f5" "$f6" "$([ -z $f7 ] || echo "--> $(dst_2_name $f7)")"
printf ' Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$g1" "$g2" "$g3" "$g4" "$g5" "$g6" "$([ -z $g7 ] || echo "--> $(dst_2_name $g7)")"
printf ' Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$h1" "$h2" "$h3" "$h4" "$h5" "$h6" "$([ -z $h7 ] || echo "--> $(dst_2_name $h7)")"
printf ' Gameip %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "${gameCIDR}" "" "$([ -z $gameCIDR ] || echo "both")" "" "$([ -z $gameCIDR ] || echo "!80:443")" "$([ -z $gameCIDR ] || echo "000000")" "--> Gaming"
printf ' Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r1)" "$r1" "$([ -z $d1 ] || echo "--> $(dst_2_name $d1)")"
printf ' Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r2)" "$r2" "$([ -z $d2 ] || echo "--> $(dst_2_name $d2)")"
printf ' Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r3)" "$r3" "$([ -z $d3 ] || echo "--> $(dst_2_name $d3)")"
printf ' Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r4)" "$r4" "$([ -z $d4 ] || echo "--> $(dst_2_name $d4)")"
echo ""
echo -en '\033[?7h' #enable line wrap
echo -n "Make a selection: "
read input
case $input in
'1')
about
read -n 1 -s -r -p "(Press any key to return)"
echo -en "\033c" #clear screen
;;
'2')
update
read -n 1 -s -r -p "(Press any key to return)"
echo -en "\033c" #clear screen
;;
'3')
rules
read -n 1 -s -r -p "(Press any key to return)"
echo -en "\033c" #clear screen
;;
'4')
rates
read -n 1 -s -r -p "(Press any key to return)"
echo -en "\033c" #clear screen
;;
'5')
debug
echo ""
read -n 1 -s -r -p "(Press any key to return)"
echo -en "\033c" #clear screen
;;
'6')
debug2
echo ""
read -n 1 -s -r -p "(Press any key to return)"
echo -en "\033c" #clear screen
;;
'u'|'U')
clear
echo -e "\033[1;32mFreshJR QOS v${version} released ${release} \033[0m"
echo ""
echo -en " Confirm you want to \033[1;32m[uninstall]\033[0m FreshJR_QOS [1=Yes 2=No] : "
read yn
if [ "${yn}" == "1" ] ; then
echo ""
sh /jffs/scripts/FreshJR_QOS -uninstall
echo ""
exit
fi
echo ""
echo -e "\033[1;31;7m FreshJR QOS has NOT been uninstalled \033[0m"
echo ""
read -n 1 -s -r -p "(Press any key to return)"
echo -en "\033c" #clear screen
;;
'e'|'E')
echo -en "\033[1A\r\033[0K"
return
;;
esac
menu
}
##alternative install for (non-RMerlin) firmware
stock_install(){
if [ "$(nvram get script_usbmount)" != "/jffs/scripts/script_usbmount" ] ; then
echo ""
echo -e "\033[1;32m Creating environment to trigger scripts post USB Mount \033[0m"
nvram set script_usbmount="/jffs/scripts/script_usbmount"
nvram commit
fi
if [ -f /jffs/scripts/script_usbmount ] ; then #check if script_usbmount exists
if grep -q "#!/bin/sh" /jffs/scripts/script_usbmount ; then #check if script_usbmount header is correct
: #if header is correct, do nothing
else #if header is incorrect, fix header
echo " Detected improper header in script_usbmount, fixing header"
sed -i "1i #!/bin/sh" /jffs/scripts/script_usbmount
chmod 0755 /jffs/scripts/script_usbmount
fi
sed -i '/FreshJR_QOS/d' /jffs/scripts/script_usbmount
echo '/jffs/scripts/FreshJR_QOS mount &' >> /jffs/scripts/script_usbmount
else #if script_usbmount did not exist then set it up entirely
echo " Creating script_usbmount in /jffs/scripts/"
echo " Placing FreshJR_QOS into script_usbmount"
echo "#!/bin/sh" > /jffs/scripts/script_usbmount
echo '/jffs/scripts/FreshJR_QOS mount &' >> /jffs/scripts/script_usbmount
chmod 0755 /jffs/scripts/script_usbmount
fi
echo -e "\033[1;32mFreshJR QOS v${version} has been installed \033[0m"
echo -e "\033[1;32m make sure a USB storage device is plugged in and \033[0m"
echo -e "\033[1;31;7m [ reboot router ] to finalize installation\033[0m"
echo ""
}
#Main program here, will execute different things depending on arguments
arg1="$(echo "$1" | tr -d "-")"
case "$arg1" in
'start'|'check'|'mount') ##RAN ON FIREWALL-START OR CRON TASK, (RAN ONLY POST USB MOUNT IF USING STOCK ASUS FIRMWARE)
cru a FreshJR_QOS "30 3 * * * /jffs/scripts/FreshJR_QOS -check" #makes sure daily check if active
cru d FreshJR_QOS_run_once #(used for stock firmware to trigger script and have it run after terminal is closed when making changes)
if [ "$(nvram get qos_enable)" == "1" ] ; then
for pid in $(pidof FreshJR_QOS); do
if [ $pid != $$ ]; then
if ! [ "$(ps -w | grep "${pid}.*\(install\|menu\|rules\|rates\)" | grep -v "grep")" ] ; then #kill all previous instances of FreshJR_QOS (-install, -menu, -rules, -rates instances are whitelisted)
kill $pid
logger -t "adaptive QOS" -s "Delayed Start Canceled"
fi
fi
done
##check if should mount QoS_stats page
if [ "$(uname -o)" == "ASUSWRT-Merlin" ] ; then
buildno="$(nvram get buildno)"; #Example "User12 v17.2 Beta4"
if [ "$(echo ${buildno} | tr -cd '.' | wc -c)" -ne 0 ] ; then #if has decimal
CV="$(echo ${buildno} | cut -d "." -f 1 | grep -o '[0-9]\+' | tail -1)" #get first number before decimal --> 17
MV="$(echo ${buildno} | cut -d "." -f 2 | grep -o '[0-9]\+' | head -1)" #get first number after decimal --> 2
else
CV="$(echo ${buildno} | grep -o '[0-9]\+' | head -1)" #get first number --> 17
MV="0"
fi
if [ "${CV}" -ge "382" ] ; then
if ! [ "${webpath}" -ef "/www/QoS_Stats.asp" ] ; then
mount -o bind "${webpath}" /www/QoS_Stats.asp
fi
#elif [ "${CV}" = "384" ] && [ ${MV} -ge "9" ] ; then
fi
fi
read_nvram #needs to be set before parse_iptablerule or custom rates
if [ "$arg1" == "start" ] ; then
##iptables rules will only be reapplied on firewall "start" due to receiving interface name
wan="${2}"
if [ -z "$wan" ] ; then
wan="eth0"
fi
parse_iptablerule "${e1}" "${e2}" "${e3}" "${e4}" "${e5}" "${e6}" "${e7}" ip1_down ip1_up ##last two arguments are variables that get set "ByRef"
parse_iptablerule "${f1}" "${f2}" "${f3}" "${f4}" "${f5}" "${f6}" "${f7}" ip2_down ip2_up
parse_iptablerule "${g1}" "${g2}" "${g3}" "${g4}" "${g5}" "${g6}" "${g7}" ip3_down ip3_up
parse_iptablerule "${h1}" "${h2}" "${h3}" "${h4}" "${h5}" "${h6}" "${h7}" ip4_down ip4_up
iptable_down_rules 2>&1 | logger -t "adaptive QOS"
iptable_up_rules 2>&1 | logger -t "adaptive QOS"
logger -t "adaptive QOS" -s -- "TC Modification Delayed Start (5min)"
sleep 300s
fi
if [ "$arg1" == "mount" ] ; then
logger -t "adaptive QOS" -s -- "--Post USB Mount-- Delayed Start (10min)"
sleep 600s
fi
current_undf_rule="$(tc filter show dev br0 | grep -v "/" | grep "000ffff" -B1)"
undf_flowid=$(echo $current_undf_rule | grep -o "flowid.*" | cut -d" " -f2 | head -1)
undf_prio=$(echo $current_undf_rule | grep -o "pref.*" | cut -d" " -f2 | head -1)
#if TC modifcations have no been applied then run modification script
#eg (if rule setting unidentified traffic to 1:17 exists) --> run modification script
if [ "${undf_flowid}" == "1:17" ] ; then
if [ "$arg1" == "check" ] ; then
logger -t "adaptive QOS" -s "Scheduled Persistence Check -> Reapplying Changes"
fi
#this section is only used stock ASUS firmware. It will will evaluate on (-mount && -check) parameters only on STOCK firmware
if [ "$(nvram get script_usbmount)" == "/jffs/scripts/script_usbmount" ] && [ "$arg1" != "start" ] ; then
wan="$(iptables -vL -t mangle | grep -m 1 "BWDPI_FILTER" | tr -s ' ' | cut -d ' ' -f 7)" #try to detect upload interface automatically
if [ -z "$wan" ] ; then
wan="eth0"
fi
parse_iptablerule "${e1}" "${e2}" "${e3}" "${e4}" "${e5}" "${e6}" "${e7}" ip1_down ip1_up ##last two arguments are variables that get set "ByRef"
parse_iptablerule "${f1}" "${f2}" "${f3}" "${f4}" "${f5}" "${f6}" "${f7}" ip2_down ip2_up
parse_iptablerule "${g1}" "${g2}" "${g3}" "${g4}" "${g5}" "${g6}" "${g7}" ip3_down ip3_up
parse_iptablerule "${h1}" "${h2}" "${h3}" "${h4}" "${h5}" "${h6}" "${h7}" ip4_down ip4_up
iptable_down_rules 2>&1 | logger -t "adaptive QOS"
iptable_up_rules 2>&1 | logger -t "adaptive QOS"
fi
set_tc_variables #needs to be set before parse_tcrule
##last two arguments are variables that get set "ByRef"
parse_tcrule "${r1}" "${d1}" tc1_down tc1_up
parse_tcrule "${r2}" "${d2}" tc2_down tc2_up
parse_tcrule "${r3}" "${d3}" tc3_down tc3_up
parse_tcrule "${r4}" "${d4}" tc4_down tc4_up
tc_redirection_down_rules "$undf_prio" 2>&1 | logger -t "adaptive QOS" #forwards terminal output & errors to logger
tc_redirection_up_rules "$undf_prio" 2>&1 | logger -t "adaptive QOS" #forwards terminal output & errors to logger
if [ "$ClassesPresent" -lt "8" ] ; then
logger -t "adaptive QOS" -s "Adaptive QOS not fully done setting up prior to modification script"
logger -t "adaptive QOS" -s "(Skipping class modification, delay trigger time period needs increase)"
else
if [ "$DownCeil" -gt "500" ] && [ "$UpCeil" -gt "500" ] ; then
custom_rates 2>&1 | logger -t "adaptive QOS" #forwards terminal output & errors to logger
fi
fi
else
if [ "$arg1" == "check" ] ; then
logger -t "adaptive QOS" -s "Scheduled Persistence Check -> No modifications necessary"
else
logger -t "adaptive QOS" -s "No modifications necessary"
fi
fi
fi
;;
'install'|'enable') ## INSTALLS AND TURNS ON SCRIPT
printf '\e[8;30;120t' #set height/width of terminal
clear
chmod 0755 /jffs/scripts/FreshJR_QOS
if grep -qs "FreshJR_QOS" /jffs/scripts/init-start ; then
sed -i '/FreshJR_QOS/d' /jffs/scripts/init-start 2>/dev/null
fi
if [ "/jffs/scripts/FreshJR_QOS_fakeTC" -ef "/bin/tc" ] || [ "/jffs/scripts/FreshJR_QOS_fakeTC" -ef "/usr/sbin/tc" ] ; then ##uninstall previous version FreshJR_QOS_fakeTC if not already uninstalled
echo "Old version of FreshJR_QOS_fast(fakeTC) has been Detected"
if [ -e "/bin/tc" ] ; then
umount /bin/tc &> /dev/null #suppresses error if present
mount -o bind /usr/sbin/faketc /bin/tc
elif [ -e "/usr/sbin/tc" ] ; then
umount /usr/sbin/tc &> /dev/null #suppresses error if present
mount -o bind /usr/sbin/faketc /usr/sbin/tc
fi
rm -f /jffs/scripts/FreshJR_QOS_fakeTC
nvram unset qos_downrates
nvram unset qos_uprates
nvram commit
if [ "/usr/sbin/faketc" -ef "/usr/sbin/tc" ] || [ "/usr/sbin/faketc" -ef "/bin/tc" ] ; then
echo "Old version of FreshJR_QOS_fast(fakeTC) has been Successfully Uninstalled"
else
echo "FreshJR_QOS_fast(fakeTC) Uninstall Process has been Initiated "
echo -e "\033[1;31;7m Please [ reboot router ] to finish the uninstall process \033[0m"
echo -e "\033[1;31;7m Rerun this install procedure after system reboot \033[0m"
exit 0
fi
fi
if [ "$(uname -o)" != "ASUSWRT-Merlin" ] ; then ##GIVE USER CHOICE TO RUN STOCK INSTALL IF Non-RMerlin FIRMWARE detected
echo -e "\033[1;31m Non-RMerlin Firmware Detected \033[0m"
echo -e -n "\033[1;31m Is this installation for (Stock / Default / Unmodified) Asus firmware? [1=Yes 2=No] : \033[0m" # Display prompt in red
read yn
echo ""
case $yn in
'1')
sed -i '/FreshJR_QOS/d' /jffs/scripts/firewall-start 2>/dev/null
stock_install;
exit 0
;;
'2')
sed -i '/FreshJR_QOS/d' /jffs/scripts/script_usbmount 2>/dev/null
echo -e "\033[1;32m Installing RMerlin version of the script \033[0m" # Display prompt in red
echo ""
break
;;
*)
echo "Invalid Option"
echo "ABORTING INSTALLATION "
exit 0
;;
esac
fi
if [ -f /jffs/scripts/firewall-start ] ; then #check if firewall-start exists
if grep -q "#!/bin/sh" /jffs/scripts/firewall-start ; then #check if firewall-start header is correct
: #if header is correct, do nothing
else #if header is incorrect, fix header
echo "Detected improper header in firewall-start, fixing header"
sed -i "1i #!/bin/sh" /jffs/scripts/firewall-start
chmod 0755 /jffs/scripts/firewall-start
fi
if grep -q -x '/jffs/scripts/FreshJR_QOS -start $1 & ' /jffs/scripts/firewall-start ; then #check if FreshJR_QOS is present as item in firewall start
: #if FreshJR_QOS is present do nothing
else #if not, appened it to the last line (also delete any previously formated entry)
echo "Placing FreshJR_QOS entry into firewall-start"
sed -i '/FreshJR_QOS/d' /jffs/scripts/firewall-start
echo '/jffs/scripts/FreshJR_QOS -start $1 & ' >> /jffs/scripts/firewall-start
fi
else #if firewall-start does not exist then set it up entirely
echo "Firewall-start not detected, creating firewall-start"
echo "Placing FreshJR_QOS entry into firewall-start"
echo "#!/bin/sh" > /jffs/scripts/firewall-start
echo '/jffs/scripts/FreshJR_QOS -start $1 & ' >> /jffs/scripts/firewall-start
chmod 0755 /jffs/scripts/firewall-start
fi
cru a FreshJR_QOS "30 3 * * * /jffs/scripts/FreshJR_QOS -check"
if [ "$(uname -o)" == "ASUSWRT-Merlin" ] ; then #Mounts webpage on RMerlin v382+
buildno="$(nvram get buildno)"; #Example "User12 v17.2 Beta4"
if [ "$(echo ${buildno} | tr -cd '.' | wc -c)" -ne 0 ] ; then #if has decimal
CV="$(echo ${buildno} | cut -d "." -f 1 | grep -o '[0-9]\+' | tail -1)" #get first number before decimal --> 17
MV="$(echo ${buildno} | cut -d "." -f 2 | grep -o '[0-9]\+' | head -1)" #get first number after decimal --> 2
else
CV="$(echo ${buildno} | grep -o '[0-9]\+' | head -1)" #get first number --> 17
MV="0"
fi
if [ "${CV}" -ge "382" ] ; then
if ! [ "${webpath}" -ef "/www/QoS_Stats.asp" ] ; then
mount -o bind "${webpath}" /www/QoS_Stats.asp
fi
#elif [ "${CV}" = "384" ] && [ ${MV} -ge "9" ] ; then
fi
fi
#shortcut to launching FreshJR_QOS (/usr/bin was readonly)
alias freshjr="sh /jffs/scripts/FreshJR_QOS -menu"
alias freshjrqos="sh /jffs/scripts/FreshJR_QOS -menu"
alias freshjr_qos="sh /jffs/scripts/FreshJR_QOS -menu"
alias FreshJR_QOS="sh /jffs/scripts/FreshJR_QOS -menu"
sed -i '/fresh/d' /jffs/configs/profile.add 2>/dev/null
echo 'alias freshjr="sh /jffs/scripts/FreshJR_QOS -menu"' >> /jffs/configs/profile.add
echo 'alias freshjrqos="sh /jffs/scripts/FreshJR_QOS -menu"' >> /jffs/configs/profile.add
echo 'alias freshjr_qos="sh /jffs/scripts/FreshJR_QOS -menu"' >> /jffs/configs/profile.add
echo 'alias FreshJR_QOS="sh /jffs/scripts/FreshJR_QOS -menu"' >> /jffs/configs/profile.add
echo -e "\033[1;32mFreshJR QOS v${version} has been installed \033[0m"
echo ""
echo -n " Advanced configuration available via: "
if [ "$(uname -o)" == "ASUSWRT-Merlin" ] ; then
if [ -e "/jffs/scripts/amtm" ] ; then
echo -e "\033[1;32m[ WebUI ]\033[0m or \033[1;32m[ /jffs/scripts/FreshJR_QOS -menu ]\033[0m or \033[1;32m[ amtm ]\033[0m "
else
echo -e "\033[1;32m[ WebUI ]\033[0m or \033[1;32m[ /jffs/scripts/FreshJR_QOS -menu ]\033[0m "
fi
else
echo -e "\033[1;32m[ /jffs/scripts/FreshJR_QOS -menu ]\033[0m "
fi
[ "$(nvram get qos_enable)" == "1" ] && prompt_restart
;;
'uninstall') ## UNINSTALLS SCRIPT AND DELETES FILES
sed -i '/FreshJR_QOS/d' /jffs/scripts/firewall-start 2>/dev/null #remove FreshJR_QOS from firewall start
sed -i '/FreshJR_QOS/d' /jffs/scripts/script_usbmount 2>/dev/null #remove FreshJR_QOS from script_usbmount - only used on stock ASUS firmware installs
sed -i '/freshjr/d' /jffs/configs/profile.add 2>/dev/null #remove aliases used to launch interactive mode
sed -i '/FreshJR/d' /jffs/configs/profile.add 2>/dev/null
cru d FreshJR_QOS
rm -f /jffs/scripts/FreshJR_QOS
umount /www/QoS_Stats.asp &> /dev/null #suppresses error if present
mount -o bind /www/QoS_Stats.asp /www/QoS_Stats.asp
umount /www/QoS_Stats.asp &> /dev/null
rm -f "${webpath}"
if [ "$(nvram get script_usbmount)" == "/jffs/scripts/script_usbmount" ] ; then #only used on stock ASUS firmware installs
nvram unset script_usbmount
fi
nvram set fb_comment=""
nvram set fb_email_dbg=""
nvram commit
echo -e "\033[1;32m FreshJR QOS has been uninstalled \033[0m"
;;
'disable') ## TURNS OFF SCRIPT BUT KEEP FILES
sed -i '/FreshJR_QOS/d' /jffs/scripts/firewall-start 2>/dev/null
sed -i '/FreshJR_QOS/d' /jffs/scripts/script_usbmount 2>/dev/null
cru d FreshJR_QOS
umount /www/QoS_Stats.asp &> /dev/null #suppresses error if present
mount -o bind /www/QoS_Stats.asp /www/QoS_Stats.asp
umount /www/QoS_Stats.asp &> /dev/null
;;
'debug')
debug
;;
'debug2')
debug2
;;
'debug3')
debug3
;;
'appdb')
appdb "$2"
;;
'gameip')
read_nvram
gameip "$2"
;;
'rules')
read_nvram
rules
;;
'rates')
read_nvram
rates
;;
'about')
about
;;
'update')
update
;;
'menu')
menu
;;
'isinstalled')
if grep -q -x '/jffs/scripts/FreshJR_QOS -start $1 & ' /jffs/scripts/firewall-start ; then
exit 0 #script IS installed
else
exit 1 #script in NOT installed
fi
;;
'isuptodate')
url="https://raw.githubusercontent.com/FreshJR07/FreshJR_QOS/master/FreshJR_QOS.sh"
remotever=$(curl -fsN --retry 3 ${url} | grep "^version=" | sed -e s/version=//)
if [ "$version" == "$remotever" ]; then
exit 0 #script IS current
else
exit 1 #script is NOT up to date
fi
;;
*)
read_nvram
echo -en "\033c\e[3J" #clear screen
echo -en '\033[?7l' #disable line wrap
# printf '\e[8;30;120t' #set height/width of terminal
echo -e "\033[1;32mFreshJR QOS v${version} \033[0m"
echo -e "\033[1;32mreleased ${release} \033[0m"
echo ""
echo "You have inputted an UNRECOGNIZED COMMAND"
echo ""
echo " Available commands:"
echo ""
echo " FreshJR_QOS -about explains functionality"
echo " FreshJR_QOS -update checks for updates "
echo ""
echo " FreshJR_QOS -install install script"
echo " FreshJR_QOS -uninstall uninstall script && delete from disk "
echo ""
echo " FreshJR_QOS -enable enable script "
echo " FreshJR_QOS -disable disable script but do not delete from disk"
echo ""
echo " FreshJR_QOS -debug print traffic control parameters"
echo " FreshJR_QOS -debug2 print parsed nvram parameters"
echo ""
echo ' FreshJR_QOS -appdb "App Name" looks up mark for specifed application'
echo ""
echo " FreshJR_QOS -rules create/modify custom rules"
echo " FreshJR_QOS -rates modify bandwidth allocations"
echo ""
echo ' FreshJR_QOS -menu interactive main menu'
echo ""
echo " Current Setup:"
echo " Local IP Remote IP Proto Local Port Remote Port Mark Dst"
printf ' Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$e1" "$e2" "$e3" "$e4" "$e5" "$e6" "$([ -z $e7 ] || echo "--> $(dst_2_name $e7)")"
printf ' Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$f1" "$f2" "$f3" "$f4" "$f5" "$f6" "$([ -z $f7 ] || echo "--> $(dst_2_name $f7)")"
printf ' Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$g1" "$g2" "$g3" "$g4" "$g5" "$g6" "$([ -z $g7 ] || echo "--> $(dst_2_name $g7)")"
printf ' Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$h1" "$h2" "$h3" "$h4" "$h5" "$h6" "$([ -z $h7 ] || echo "--> $(dst_2_name $h7)")"
printf ' Gameip %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "${gameCIDR}" "" "$([ -z $gameCIDR ] || echo "both")" "" "$([ -z $gameCIDR ] || echo "!80:443")" "$([ -z $gameCIDR ] || echo "000000")" "--> Gaming"
printf ' Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r1)" "$r1" "$([ -z $d1 ] || echo "--> $(dst_2_name $d1)")"
printf ' Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r2)" "$r2" "$([ -z $d2 ] || echo "--> $(dst_2_name $d2)")"
printf ' Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r3)" "$r3" "$([ -z $d3 ] || echo "--> $(dst_2_name $d3)")"
printf ' Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r4)" "$r4" "$([ -z $d4 ] || echo "--> $(dst_2_name $d4)")"
echo ""
echo -en '\033[?7h' #enable line wrap
;;
esac