Update Help Output (#1467)

* File consistency

* Tabs to 2 spaces
* Corrected indenting
* Double braced conditionals
* Quoted variables within conditionals

* Standardise core help text

* Added help text for disable command
* Added help text for logging command

* Clean up

* Fixed certain new lines and spaces

* Sync with development branch

* Formatting consistency

* Tabs to 2 spaces
* Corrected indenting
* Double braced conditionals
* Quoted variables within conditionals
* Fixed certain newlines and spaces

* Admin help text

* Added help text for interface command

* Sync with development branch

* Formatting consistency

* Tabs to 2 spaces
* Fixed some wording
* Fixed certain spaces

* Formatting consistency

* Minor wording changes
* Tabs to 2 spaces
* Corrected indenting
* Double braced conditionals
* Quoted variables within conditionals
* Fixed certain newlines and spaces

* Blacklist help text

* Formatting consistency

* Tabs to 2 spaces
* Corrected indenting

* Cronometer help text

* Formatting consistency

* Fixed certain newlines and spaces
* Corrected indenting

* Checkout warning alteration

* Add checkout help text

* Corrected help output
pull/1468/head
WaLLy3K 7 years ago committed by GitHub
parent 26fcb1b2a0
commit b721ed49ab

@ -8,101 +8,98 @@
# This file is copyright under the latest version of the EUPL. # This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license. # Please see LICENSE file for your rights under this license.
#Functions############################################################################################################## # Functions
piLog="/var/log/pihole.log" piLog="/var/log/pihole.log"
gravity="/etc/pihole/gravity.list" gravity="/etc/pihole/gravity.list"
. /etc/pihole/setupVars.conf . /etc/pihole/setupVars.conf
function GetFTLData { function GetFTLData {
# Open connection to FTL # Open connection to FTL
exec 3<>/dev/tcp/localhost/"$(cat /var/run/pihole-FTL.port)" exec 3<>/dev/tcp/localhost/"$(cat /var/run/pihole-FTL.port)"
# Test if connection is open # Test if connection is open
if { >&3; } 2> /dev/null; then if { >&3; } 2> /dev/null; then
# Send command to FTL # Send command to FTL
echo -e ">$1" >&3 echo -e ">$1" >&3
# Read input # Read input
read -r -t 1 LINE <&3
until [ ! $? ] || [[ "$LINE" == *"EOM"* ]]; do
echo "$LINE" >&1
read -r -t 1 LINE <&3 read -r -t 1 LINE <&3
until [ ! $? ] || [[ "$LINE" == *"EOM"* ]]; do done
echo "$LINE" >&1
read -r -t 1 LINE <&3
done
# Close connection # Close connection
exec 3>&- exec 3>&-
exec 3<&- exec 3<&-
fi fi
} }
outputJSON() { outputJSON() {
get_summary_data get_summary_data
echo "{\"domains_being_blocked\":${domains_being_blocked_raw},\"dns_queries_today\":${dns_queries_today_raw},\"ads_blocked_today\":${ads_blocked_today_raw},\"ads_percentage_today\":${ads_percentage_today_raw}}" echo "{\"domains_being_blocked\":${domains_being_blocked_raw},\"dns_queries_today\":${dns_queries_today_raw},\"ads_blocked_today\":${ads_blocked_today_raw},\"ads_percentage_today\":${ads_percentage_today_raw}}"
} }
get_summary_data() { get_summary_data() {
local summary=$(GetFTLData "stats") local summary=$(GetFTLData "stats")
domains_being_blocked_raw=$(grep "domains_being_blocked" <<< "${summary}" | grep -Eo "[0-9]+$") domains_being_blocked_raw=$(grep "domains_being_blocked" <<< "${summary}" | grep -Eo "[0-9]+$")
domains_being_blocked=$(printf "%'.f" ${domains_being_blocked_raw}) domains_being_blocked=$(printf "%'.f" ${domains_being_blocked_raw})
dns_queries_today_raw=$(grep "dns_queries_today" <<< "$summary" | grep -Eo "[0-9]+$") dns_queries_today_raw=$(grep "dns_queries_today" <<< "$summary" | grep -Eo "[0-9]+$")
dns_queries_today=$(printf "%'.f" ${dns_queries_today_raw}) dns_queries_today=$(printf "%'.f" ${dns_queries_today_raw})
ads_blocked_today_raw=$(grep "ads_blocked_today" <<< "$summary" | grep -Eo "[0-9]+$") ads_blocked_today_raw=$(grep "ads_blocked_today" <<< "$summary" | grep -Eo "[0-9]+$")
ads_blocked_today=$(printf "%'.f" ${ads_blocked_today_raw}) ads_blocked_today=$(printf "%'.f" ${ads_blocked_today_raw})
ads_percentage_today_raw=$(grep "ads_percentage_today" <<< "$summary" | grep -Eo "[0-9.]+$") ads_percentage_today_raw=$(grep "ads_percentage_today" <<< "$summary" | grep -Eo "[0-9.]+$")
LC_NUMERIC=C ads_percentage_today=$(printf "%'.f" ${ads_percentage_today_raw}) LC_NUMERIC=C ads_percentage_today=$(printf "%'.f" ${ads_percentage_today_raw})
} }
normalChrono() { normalChrono() {
for (( ; ; )); do for (( ; ; )); do
get_summary_data get_summary_data
domain=$(GetFTLData recentBlocked) domain=$(GetFTLData recentBlocked)
clear clear
# Displays a colorful Pi-hole logo # Displays a colorful Pi-hole logo
echo " ___ _ _ _" echo " ___ _ _ _"
echo "| _ (_)___| |_ ___| |___" echo "| _ (_)___| |_ ___| |___"
echo "| _/ |___| ' \/ _ \ / -_)" echo "| _/ |___| ' \/ _ \ / -_)"
echo "|_| |_| |_||_\___/_\___|" echo "|_| |_| |_||_\___/_\___|"
echo "" echo ""
echo " ${IPV4_ADDRESS}" echo " ${IPV4_ADDRESS}"
echo "" echo ""
uptime | cut -d' ' -f11- uptime | cut -d' ' -f11-
#uptime -p #Doesn't work on all versions of uptime #uptime -p # Doesn't work on all versions of uptime
uptime | awk -F'( |,|:)+' '{if ($7=="min") m=$6; else {if ($7~/^day/) {d=$6;h=$8;m=$9} else {h=$6;m=$7}}} {print d+0,"days,",h+0,"hours,",m+0,"minutes."}' uptime | awk -F'( |,|:)+' '{if ($7=="min") m=$6; else {if ($7~/^day/) {d=$6;h=$8;m=$9} else {h=$6;m=$7}}} {print d+0,"days,",h+0,"hours,",m+0,"minutes."}'
echo "-------------------------------" echo "-------------------------------"
echo "Recently blocked:" echo "Recently blocked:"
echo " $domain" echo " $domain"
echo "Blocking: ${domains_being_blocked}" echo "Blocking: ${domains_being_blocked}"
echo "Queries: ${dns_queries_today}" echo "Queries: ${dns_queries_today}"
echo "Pi-holed: ${ads_blocked_today} (${ads_percentage_today}%)" echo "Pi-holed: ${ads_blocked_today} (${ads_percentage_today}%)"
sleep 5 sleep 5
done done
} }
displayHelp() { displayHelp() {
cat << EOM echo "Usage: pihole -c [options]
::: Displays stats about your piHole! Example: 'pihole -c -j'
::: Calculates stats and displays to an LCD
::: Usage: sudo pihole -c [optional:-j]
::: Note: If no option is passed, then stats are displayed on screen, updated every 5 seconds Options:
::: -j, --json Output stats as JSON formatted string
::: Options: -h, --help Display this help text"
::: -j, --json output stats as JSON formatted string exit 0
::: -h, --help display this help text
EOM
exit 0
} }
if [[ $# = 0 ]]; then if [[ $# = 0 ]]; then
normalChrono normalChrono
fi fi
for var in "$@"; do for var in "$@"; do
case "$var" in case "$var" in
"-j" | "--json" ) outputJSON;; "-j" | "--json" ) outputJSON;;
"-h" | "--help" ) displayHelp;; "-h" | "--help" ) displayHelp;;
* ) exit 1;; * ) exit 1;;
esac esac
done done

@ -3,14 +3,12 @@
# (c) 2017 Pi-hole, LLC (https://pi-hole.net) # (c) 2017 Pi-hole, LLC (https://pi-hole.net)
# Network-wide ad blocking via your own hardware. # Network-wide ad blocking via your own hardware.
# #
# Whitelists and blacklists domains # Whitelist and blacklist domains
# #
# This file is copyright under the latest version of the EUPL. # This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license. # Please see LICENSE file for your rights under this license.
# Globals
#globals
basename=pihole basename=pihole
piholeDir=/etc/${basename} piholeDir=/etc/${basename}
whitelist=${piholeDir}/whitelist.txt whitelist=${piholeDir}/whitelist.txt
@ -27,122 +25,120 @@ listMain=""
listAlt="" listAlt=""
helpFunc() { helpFunc() {
if [[ "${listMain}" == "${whitelist}" ]]; then
if [[ ${listMain} == ${whitelist} ]]; then letter="w"
letter="w" word="white"
word="white" else
else letter="b"
letter="b" word="black"
word="black" fi
fi
echo "Usage: pihole -${letter} [options] <domain> <domain2 ...>
cat << EOM Example: 'pihole -${letter} site.com', or 'pihole -${letter} site1.com site2.com'
::: Immediately ${word}lists one or more domains in the hosts file ${word^}list one or more domains
:::
::: Usage: pihole -${letter} domain1 [domain2 ...] Options:"
:::
::: Options: if [[ "${letter}" == "b" ]]; then
::: -d, --delmode Remove domains from the ${word}list echo " -wild, --wildcard Add wildcard entry to blacklist"
::: -nr, --noreload Update ${word}list without refreshing dnsmasq fi
::: -q, --quiet Output is less verbose
::: -h, --help Show this help dialog echo " -d, --delmode Remove domain(s) from the ${word}list
::: -l, --list Display your ${word}listed domains -nr, --noreload Update ${word}list without refreshing dnsmasq
EOM -q, --quiet Make output less verbose
if [[ "${letter}" == "b" ]]; then -h, --help Show this help dialog
echo "::: -wild, --wildcard Add wildcard entry (only blacklist)" -l, --list Display all your ${word}listed domains"
fi
exit 0 exit 0
} }
EscapeRegexp() { EscapeRegexp() {
# This way we may safely insert an arbitrary # This way we may safely insert an arbitrary
# string in our regular expressions # string in our regular expressions
# Also remove leading "." if present # Also remove leading "." if present
echo $* | sed 's/^\.*//' | sed "s/[]\.|$(){}?+*^]/\\\\&/g" | sed "s/\\//\\\\\//g" echo $* | sed 's/^\.*//' | sed "s/[]\.|$(){}?+*^]/\\\\&/g" | sed "s/\\//\\\\\//g"
} }
HandleOther(){ HandleOther() {
# First, convert everything to lowercase # First, convert everything to lowercase
domain=$(sed -e "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/" <<< "$1") domain=$(sed -e "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/" <<< "$1")
#check validity of domain # Check validity of domain
validDomain=$(echo "${domain}" | perl -lne 'print if /(?!.*[^a-z0-9-\.].*)^((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9-]+\.)*[a-z]{2,63}/') validDomain=$(echo "${domain}" | perl -lne 'print if /(?!.*[^a-z0-9-\.].*)^((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9-]+\.)*[a-z]{2,63}/')
if [ -z "${validDomain}" ]; then if [[ -z "${validDomain}" ]]; then
echo "::: $1 is not a valid argument or domain name" echo "::: $1 is not a valid argument or domain name"
else else
domList=("${domList[@]}" ${validDomain}) domList=("${domList[@]}" ${validDomain})
fi fi
} }
PoplistFile() { PoplistFile() {
#check whitelist file exists, and if not, create it # Check whitelist file exists, and if not, create it
if [[ ! -f ${whitelist} ]]; then if [[ ! -f ${whitelist} ]]; then
touch ${whitelist} touch ${whitelist}
fi fi
for dom in "${domList[@]}"; do
# Logic : If addmode then add to desired list and remove from the other; if delmode then remove from desired list but do not add to the other for dom in "${domList[@]}"; do
if ${addmode}; then # Logic: If addmode then add to desired list and remove from the other; if delmode then remove from desired list but do not add to the other
AddDomain "${dom}" "${listMain}" if ${addmode}; then
RemoveDomain "${dom}" "${listAlt}" AddDomain "${dom}" "${listMain}"
if [[ "${listMain}" == "${whitelist}" || "${listMain}" == "${blacklist}" ]]; then RemoveDomain "${dom}" "${listAlt}"
RemoveDomain "${dom}" "${wildcardlist}" if [[ "${listMain}" == "${whitelist}" || "${listMain}" == "${blacklist}" ]]; then
fi RemoveDomain "${dom}" "${wildcardlist}"
else fi
RemoveDomain "${dom}" "${listMain}" else
fi RemoveDomain "${dom}" "${listMain}"
done fi
done
} }
AddDomain() { AddDomain() {
list="$2" list="$2"
domain=$(EscapeRegexp "$1") domain=$(EscapeRegexp "$1")
if [[ "${list}" == "${whitelist}" || "${list}" == "${blacklist}" ]]; then if [[ "${list}" == "${whitelist}" || "${list}" == "${blacklist}" ]]; then
bool=true
bool=true # Is the domain in the list we want to add it to?
#Is the domain in the list we want to add it to? grep -Ex -q "${domain}" "${list}" > /dev/null 2>&1 || bool=false
grep -Ex -q "${domain}" "${list}" > /dev/null 2>&1 || bool=false
if [[ "${bool}" == false ]]; then
if [[ "${bool}" == false ]]; then # Domain not found in the whitelist file, add it!
#domain not found in the whitelist file, add it! if [[ "${verbose}" == true ]]; then
if [[ "${verbose}" == true ]]; then echo "::: Adding $1 to $list..."
echo "::: Adding $1 to $list..." fi
fi reload=true
reload=true # Add it to the list we want to add it to
# Add it to the list we want to add it to echo "$1" >> "${list}"
echo "$1" >> "${list}" else
else if [[ "${verbose}" == true ]]; then
if [[ "${verbose}" == true ]]; then echo "::: ${1} already exists in ${list}, no need to add!"
echo "::: ${1} already exists in ${list}, no need to add!" fi
fi fi
fi elif [[ "${list}" == "${wildcardlist}" ]]; then
source "${piholeDir}/setupVars.conf"
elif [[ "${list}" == "${wildcardlist}" ]]; then # Remove the /* from the end of the IPv4addr.
IPV4_ADDRESS=${IPV4_ADDRESS%/*}
source "${piholeDir}/setupVars.conf" IPV6_ADDRESS=${IPV6_ADDRESS}
#Remove the /* from the end of the IPv4addr.
IPV4_ADDRESS=${IPV4_ADDRESS%/*} bool=true
IPV6_ADDRESS=${IPV6_ADDRESS} # Is the domain in the list?
grep -e "address=\/${domain}\/" "${wildcardlist}" > /dev/null 2>&1 || bool=false
bool=true
#Is the domain in the list? if [[ "${bool}" == false ]]; then
grep -e "address=\/${domain}\/" "${wildcardlist}" > /dev/null 2>&1 || bool=false if [[ "${verbose}" == true ]]; then
echo "::: Adding $1 to wildcard blacklist..."
if [[ "${bool}" == false ]]; then fi
if [[ "${verbose}" == true ]]; then reload=true
echo "::: Adding $1 to wildcard blacklist..." echo "address=/$1/${IPV4_ADDRESS}" >> "${wildcardlist}"
fi if [[ "${#IPV6_ADDRESS}" > 0 ]]; then
reload=true echo "address=/$1/${IPV6_ADDRESS}" >> "${wildcardlist}"
echo "address=/$1/${IPV4_ADDRESS}" >> "${wildcardlist}" fi
if [[ ${#IPV6_ADDRESS} > 0 ]] ; then else
echo "address=/$1/${IPV6_ADDRESS}" >> "${wildcardlist}" if [[ "${verbose}" == true ]]; then
fi echo "::: ${1} already exists in wildcard blacklist, no need to add!"
else fi
if [[ "${verbose}" == true ]]; then fi
echo "::: ${1} already exists in wildcard blacklist, no need to add!" fi
fi
fi
fi
} }
RemoveDomain() { RemoveDomain() {
@ -150,85 +146,82 @@ RemoveDomain() {
domain=$(EscapeRegexp "$1") domain=$(EscapeRegexp "$1")
if [[ "${list}" == "${whitelist}" || "${list}" == "${blacklist}" ]]; then if [[ "${list}" == "${whitelist}" || "${list}" == "${blacklist}" ]]; then
bool=true
bool=true # Is it in the list? Logic follows that if its whitelisted it should not be blacklisted and vice versa
#Is it in the list? Logic follows that if its whitelisted it should not be blacklisted and vice versa grep -Ex -q "${domain}" "${list}" > /dev/null 2>&1 || bool=false
grep -Ex -q "${domain}" "${list}" > /dev/null 2>&1 || bool=false if [[ "${bool}" == true ]]; then
if [[ "${bool}" == true ]]; then # Remove it from the other one
# Remove it from the other one echo "::: Removing $1 from $list..."
echo "::: Removing $1 from $list..." # /I flag: search case-insensitive
# /I flag: search case-insensitive sed -i "/${domain}/Id" "${list}"
sed -i "/${domain}/Id" "${list}" reload=true
reload=true else
else if [[ "${verbose}" == true ]]; then
if [[ "${verbose}" == true ]]; then echo "::: ${1} does not exist in ${list}, no need to remove!"
echo "::: ${1} does not exist in ${list}, no need to remove!"
fi
fi fi
fi
elif [[ "${list}" == "${wildcardlist}" ]]; then elif [[ "${list}" == "${wildcardlist}" ]]; then
bool=true
bool=true # Is it in the list?
#Is it in the list? grep -e "address=\/${domain}\/" "${wildcardlist}" > /dev/null 2>&1 || bool=false
grep -e "address=\/${domain}\/" "${wildcardlist}" > /dev/null 2>&1 || bool=false if [[ "${bool}" == true ]]; then
if [[ "${bool}" == true ]]; then # Remove it from the other one
# Remove it from the other one echo "::: Removing $1 from $list..."
echo "::: Removing $1 from $list..." # /I flag: search case-insensitive
# /I flag: search case-insensitive sed -i "/address=\/${domain}/Id" "${list}"
sed -i "/address=\/${domain}/Id" "${list}" reload=true
reload=true else
else if [[ "${verbose}" == true ]]; then
if [[ "${verbose}" == true ]]; then echo "::: ${1} does not exist in ${list}, no need to remove!"
echo "::: ${1} does not exist in ${list}, no need to remove!"
fi
fi fi
fi
fi fi
} }
Reload() { Reload() {
# Reload hosts file # Reload hosts file
pihole -g -sd pihole -g -sd
} }
Displaylist() { Displaylist() {
if [[ ${listMain} == ${whitelist} ]]; then if [[ "${listMain}" == "${whitelist}" ]]; then
string="gravity resistant domains" string="gravity resistant domains"
else else
string="domains caught in the sinkhole" string="domains caught in the sinkhole"
fi fi
verbose=false verbose=false
echo -e " Displaying $string \n" echo -e "Displaying $string:\n"
count=1 count=1
while IFS= read -r RD; do while IFS= read -r RD; do
echo "${count}: ${RD}" echo "${count}: ${RD}"
count=$((count+1)) count=$((count+1))
done < "${listMain}" done < "${listMain}"
exit 0; exit 0;
} }
for var in "$@"; do for var in "$@"; do
case "${var}" in case "${var}" in
"-w" | "whitelist" ) listMain="${whitelist}"; listAlt="${blacklist}";; "-w" | "whitelist" ) listMain="${whitelist}"; listAlt="${blacklist}";;
"-b" | "blacklist" ) listMain="${blacklist}"; listAlt="${whitelist}";; "-b" | "blacklist" ) listMain="${blacklist}"; listAlt="${whitelist}";;
"-wild" | "wildcard" ) listMain="${wildcardlist}";; "-wild" | "wildcard" ) listMain="${wildcardlist}";;
"-nr"| "--noreload" ) reload=false;; "-nr"| "--noreload" ) reload=false;;
"-d" | "--delmode" ) addmode=false;; "-d" | "--delmode" ) addmode=false;;
"-f" | "--force" ) force=true;; "-f" | "--force" ) force=true;;
"-q" | "--quiet" ) verbose=false;; "-q" | "--quiet" ) verbose=false;;
"-h" | "--help" ) helpFunc;; "-h" | "--help" ) helpFunc;;
"-l" | "--list" ) Displaylist;; "-l" | "--list" ) Displaylist;;
* ) HandleOther "${var}";; * ) HandleOther "${var}";;
esac esac
done done
shift shift
if [[ $# = 0 ]]; then if [[ $# = 0 ]]; then
helpFunc helpFunc
fi fi
PoplistFile PoplistFile
if ${reload}; then if ${reload}; then
Reload Reload
fi fi

@ -3,7 +3,7 @@
# (c) 2017 Pi-hole, LLC (https://pi-hole.net) # (c) 2017 Pi-hole, LLC (https://pi-hole.net)
# Network-wide ad blocking via your own hardware. # Network-wide ad blocking via your own hardware.
# #
# Checkout other branches than master # Switch Pi-hole subsystems to a different Github branch
# #
# This file is copyright under the latest version of the EUPL. # This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license. # Please see LICENSE file for your rights under this license.
@ -18,9 +18,12 @@ PH_TEST="true" source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh"
# setupVars set in basic-install.sh # setupVars set in basic-install.sh
source "${setupVars}" source "${setupVars}"
update="false" update="false"
# Colour codes
red="\e[1;31m"
def="\e[0m"
fully_fetch_repo() { fully_fetch_repo() {
# Add upstream branches to shallow clone # Add upstream branches to shallow clone
local directory="${1}" local directory="${1}"
@ -35,7 +38,7 @@ fully_fetch_repo() {
return 0 return 0
} }
get_available_branches(){ get_available_branches() {
# Return available branches # Return available branches
local directory="${1}" local directory="${1}"
@ -79,23 +82,23 @@ checkout_pull_branch() {
} }
warning1() { warning1() {
echo "::: Note that changing the branch is a severe change of your Pi-hole system." echo " Please note that changing branches severely alters your Pi-hole subsystems"
echo "::: This is not supported unless one of the developers explicitly asks you to do this!" echo " Features that work on the master branch, may not on a development branch"
read -r -p "::: Have you read and understood this? [y/N] " response echo -e " ${red}This feature is NOT supported unless a Pi-hole developer explicitly asks!${def}"
read -r -p " Have you read and understood this? [Y/N] " response
case ${response} in case ${response} in
[yY][eE][sS]|[yY]) [yY][eE][sS]|[yY])
echo "::: Continuing." echo "::: Continuing with branch change."
return 0 return 0
;; ;;
*) *)
echo "::: Aborting." echo "::: Branch change has been cancelled."
return 1 return 1
;; ;;
esac esac
} }
checkout() checkout() {
{
local corebranches local corebranches
local webbranches local webbranches
@ -192,11 +195,10 @@ checkout()
if [[ ! "${1}" == "web" && "${update}" == "true" ]]; then if [[ ! "${1}" == "web" && "${update}" == "true" ]]; then
echo "::: Running installer to upgrade your installation" echo "::: Running installer to upgrade your installation"
if "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" --unattended; then if "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" --unattended; then
exit 0 exit 0
else else
echo "Unable to complete update, contact Pi-hole" echo "Unable to complete update, contact Pi-hole"
exit 1 exit 1
fi fi
fi fi
} }

@ -3,24 +3,29 @@
# (c) 2017 Pi-hole, LLC (https://pi-hole.net) # (c) 2017 Pi-hole, LLC (https://pi-hole.net)
# Network-wide ad blocking via your own hardware. # Network-wide ad blocking via your own hardware.
# #
# shows version numbers # Show version numbers
# #
# This file is copyright under the latest version of the EUPL. # This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license. # Please see LICENSE file for your rights under this license.
# Variables # Variables
DEFAULT="-1" DEFAULT="-1"
PHGITDIR="/etc/.pihole/" COREGITDIR="/etc/.pihole/"
WEBGITDIR="/var/www/html/admin/" WEBGITDIR="/var/www/html/admin/"
getLocalVersion() { getLocalVersion() {
# FTL requires a different method
if [[ "$1" == "FTL" ]]; then
pihole-FTL version
return 0
fi
# Get the tagged version of the local repository # Get the tagged version of the local repository
local directory="${1}" local directory="${1}"
local version local version
cd "${directory}" || { echo "${DEFAULT}"; return 1; } cd "${directory}" 2> /dev/null || { echo "${DEFAULT}"; return 1; }
version=$(git describe --tags --always || \ version=$(git describe --tags --always || echo "$DEFAULT")
echo "${DEFAULT}")
if [[ "${version}" =~ ^v ]]; then if [[ "${version}" =~ ^v ]]; then
echo "${version}" echo "${version}"
elif [[ "${version}" == "${DEFAULT}" ]]; then elif [[ "${version}" == "${DEFAULT}" ]]; then
@ -33,13 +38,18 @@ getLocalVersion() {
} }
getLocalHash() { getLocalHash() {
# Local FTL hash does not exist on filesystem
if [[ "$1" == "FTL" ]]; then
echo "N/A"
return 0
fi
# Get the short hash of the local repository # Get the short hash of the local repository
local directory="${1}" local directory="${1}"
local hash local hash
cd "${directory}" || { echo "${DEFAULT}"; return 1; } cd "${directory}" 2> /dev/null || { echo "${DEFAULT}"; return 1; }
hash=$(git rev-parse --short HEAD || \ hash=$(git rev-parse --short HEAD || echo "$DEFAULT")
echo "${DEFAULT}")
if [[ "${hash}" == "${DEFAULT}" ]]; then if [[ "${hash}" == "${DEFAULT}" ]]; then
echo "ERROR" echo "ERROR"
return 1 return 1
@ -49,12 +59,33 @@ getLocalHash() {
return 0 return 0
} }
getRemoteHash(){
# Remote FTL hash is not applicable
if [[ "$1" == "FTL" ]]; then
echo "N/A"
return 0
fi
local daemon="${1}"
local branch="${2}"
hash=$(git ls-remote --heads "https://github.com/pi-hole/${daemon}" | \
awk -v bra="$branch" '$0~bra {print substr($0,0,8);exit}')
if [[ -n "$hash" ]]; then
echo "$hash"
else
echo "ERROR"
return 1
fi
return 0
}
getRemoteVersion(){ getRemoteVersion(){
# Get the version from the remote origin # Get the version from the remote origin
local daemon="${1}" local daemon="${1}"
local version local version
version=$(curl --silent --fail https://api.github.com/repos/pi-hole/${daemon}/releases/latest | \ version=$(curl --silent --fail "https://api.github.com/repos/pi-hole/${daemon}/releases/latest" | \
awk -F: '$1 ~/tag_name/ { print $2 }' | \ awk -F: '$1 ~/tag_name/ { print $2 }' | \
tr -cd '[[:alnum:]]._-') tr -cd '[[:alnum:]]._-')
if [[ "${version}" =~ ^v ]]; then if [[ "${version}" =~ ^v ]]; then
@ -66,72 +97,73 @@ getRemoteVersion(){
return 0 return 0
} }
#PHHASHLATEST=$(curl -s https://api.github.com/repos/pi-hole/pi-hole/commits/master | \ versionOutput() {
# grep sha | \ [[ "$1" == "pi-hole" ]] && GITDIR=$COREGITDIR
# head -n1 | \ [[ "$1" == "AdminLTE" ]] && GITDIR=$WEBGITDIR
# awk -F ' ' '{ print $2 }' | \ [[ "$1" == "FTL" ]] && GITDIR="FTL"
# tr -cd '[[:alnum:]]._-')
[[ "$2" == "-c" ]] || [[ "$2" == "--current" ]] || [[ -z "$2" ]] && current=$(getLocalVersion $GITDIR)
#WEBHASHLATEST=$(curl -s https://api.github.com/repos/pi-hole/AdminLTE/commits/master | \ [[ "$2" == "-l" ]] || [[ "$2" == "--latest" ]] || [[ -z "$2" ]] && latest=$(getRemoteVersion "$1")
# grep sha | \ if [[ "$2" == "-h" ]] || [[ "$2" == "--hash" ]]; then
# head -n1 | \ [[ "$3" == "-c" ]] || [[ "$3" == "--current" ]] || [[ -z "$3" ]] && curHash=$(getLocalHash "$GITDIR")
# awk -F ' ' '{ print $2 }' | \ [[ "$3" == "-l" ]] || [[ "$3" == "--latest" ]] || [[ -z "$3" ]] && latHash=$(getRemoteHash "$1" "$(cd "$GITDIR" 2> /dev/null && git rev-parse --abbrev-ref HEAD)")
# tr -cd '[[:alnum:]]._-') fi
normalOutput() {
echo "::: Pi-hole version is $(getLocalVersion "${PHGITDIR}") (Latest version is $(getRemoteVersion pi-hole))"
if [ -d "${WEBGITDIR}" ]; then
echo "::: Web-Admin version is $(getLocalVersion "${WEBGITDIR}") (Latest version is $(getRemoteVersion AdminLTE))"
fi
}
webOutput() { if [[ -n "$current" ]] && [[ -n "$latest" ]]; then
if [ -d "${WEBGITDIR}" ]; then output="${1^} version is $current (Latest: $latest)"
case "${1}" in elif [[ -n "$current" ]] && [[ -z "$latest" ]]; then
"-l" | "--latest" ) echo $(getRemoteVersion AdminLTE);; output="Current ${1^} version is $current"
"-c" | "--current" ) echo $(getLocalVersion "${WEBGITDIR}");; elif [[ -z "$current" ]] && [[ -n "$latest" ]]; then
"-h" | "--hash" ) echo $(getLocalHash "${WEBGITDIR}");; output="Latest ${1^} version is $latest"
* ) echo "::: Invalid Option!"; exit 1; elif [[ "$curHash" == "N/A" ]] || [[ "$latHash" == "N/A" ]]; then
esac output="${1^} hash is not applicable"
elif [[ -n "$curHash" ]] && [[ -n "$latHash" ]]; then
output="${1^} hash is $curHash (Latest: $latHash)"
elif [[ -n "$curHash" ]] && [[ -z "$latHash" ]]; then
output="Current ${1^} hash is $curHash"
elif [[ -z "$curHash" ]] && [[ -n "$latHash" ]]; then
output="Latest ${1^} hash is $latHash"
else else
echo "::: Web interface not installed!"; exit 1; errorOutput
fi fi
[[ -n "$output" ]] && echo "$output"
} }
coreOutput() { errorOutput() {
case "${1}" in echo "Invalid Option! Try 'pihole -v -h' for more information."
"-l" | "--latest" ) echo $(getRemoteVersion pi-hole);; exit 1
"-c" | "--current" ) echo $(getLocalVersion "${PHGITDIR}");; }
"-h" | "--hash" ) echo $(getLocalHash "${PHGITDIR}");;
* ) echo "::: Invalid Option!"; exit 1; defaultOutput() {
esac versionOutput "pi-hole" "$@"
versionOutput "AdminLTE" "$@"
versionOutput "FTL" "$@"
} }
helpFunc() { helpFunc() {
cat << EOM echo "Usage: pihole -v [REPO | OPTION] [OPTION]
::: Example: 'pihole -v -p -l'
::: Show Pi-hole/Web Admin versions Show Pi-hole, Admin Console & FTL versions
:::
::: Usage: pihole -v [ -a | -p ] [ -l | -c ] Repositories:
::: -p, --pihole Only retrieve info regarding Pi-hole repository
::: Options: -a, --admin Only retrieve info regarding AdminLTE repository
::: -a, --admin Show both current and latest versions of web admin -f, --ftl Only retrieve info regarding FTL repository
::: -p, --pihole Show both current and latest versions of Pi-hole core files
::: -l, --latest (Only after -a | -p) Return only latest version Options:
::: -c, --current (Only after -a | -p) Return only current version -c, --current Return the current version
::: -h, --help Show this help dialog -l, --latest Return the latest version
::: -h, --hash Return the Github hash from your local repositories
EOM --help Show this help dialog
exit 0 "
exit 0
} }
if [[ $# = 0 ]]; then
normalOutput
fi
case "${1}" in case "${1}" in
"-a" | "--admin" ) shift; webOutput "$@";; "-p" | "--pihole" ) shift; versionOutput "pi-hole" "$@";;
"-p" | "--pihole" ) shift; coreOutput "$@" ;; "-a" | "--admin" ) shift; versionOutput "AdminLTE" "$@";;
"-h" | "--help" ) helpFunc;; "-f" | "--ftl" ) shift; versionOutput "FTL" "$@";;
"--help" ) helpFunc;;
* ) defaultOutput "$@";;
esac esac

@ -8,7 +8,6 @@
# This file is copyright under the latest version of the EUPL. # This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license. # Please see LICENSE file for your rights under this license.
readonly setupVars="/etc/pihole/setupVars.conf" readonly setupVars="/etc/pihole/setupVars.conf"
readonly dnsmasqconfig="/etc/dnsmasq.d/01-pihole.conf" readonly dnsmasqconfig="/etc/dnsmasq.d/01-pihole.conf"
readonly dhcpconfig="/etc/dnsmasq.d/02-pihole-dhcp.conf" readonly dhcpconfig="/etc/dnsmasq.d/02-pihole-dhcp.conf"
@ -16,23 +15,19 @@ readonly dhcpconfig="/etc/dnsmasq.d/02-pihole-dhcp.conf"
readonly dhcpstaticconfig="/etc/dnsmasq.d/04-pihole-static-dhcp.conf" readonly dhcpstaticconfig="/etc/dnsmasq.d/04-pihole-static-dhcp.conf"
helpFunc() { helpFunc() {
cat << EOM echo "Usage: pihole -a [options]
::: Set admin options for the web interface of pihole Example: pihole -a -p password
::: Set options for the Admin Console
::: Usage: pihole -a [options]
::: Options:
::: Options: -f, flush Flush the Pi-hole log
::: -p, password Set web interface password, an empty input will remove any previously set password -p, password Set Admin Console password
::: -c, celsius Set Celsius temperature unit -c, celsius Set Celsius as preferred temperature unit
::: -f, fahrenheit Set Fahrenheit temperature unit -f, fahrenheit Set Fahrenheit as preferred temperature unit
::: -k, kelvin Set Kelvin temperature unit -k, kelvin Set Kelvin as preferred temperature unit
::: -h, --help Show this help dialog -h, --help Show this help dialog
::: -i, interface Setup interface listening behavior of dnsmasq -i, interface Specify dnsmasq's interface listening behavior
::: pihole -a -i local : Listen on all interfaces, but allow only queries from Add '-h' for more info on interface usage"
::: devices that are at most one hop away (local devices)
::: pihole -a -i single : Listen only on one interface (see PIHOLE_INTERFACE)
::: pihole -a -i all : Listen on all interfaces, permit all origins
EOM
exit 0 exit 0
} }
@ -61,21 +56,18 @@ delete_dnsmasq_setting() {
sed -i "/${1}/d" "${dnsmasqconfig}" sed -i "/${1}/d" "${dnsmasqconfig}"
} }
SetTemperatureUnit(){ SetTemperatureUnit() {
change_setting "TEMPERATUREUNIT" "${unit}" change_setting "TEMPERATUREUNIT" "${unit}"
} }
HashPassword(){ HashPassword() {
# Compute password hash twice to avoid rainbow table vulnerability # Compute password hash twice to avoid rainbow table vulnerability
return=$(echo -n ${1} | sha256sum | sed 's/\s.*$//') return=$(echo -n ${1} | sha256sum | sed 's/\s.*$//')
return=$(echo -n ${return} | sha256sum | sed 's/\s.*$//') return=$(echo -n ${return} | sha256sum | sed 's/\s.*$//')
echo ${return} echo ${return}
} }
SetWebPassword(){ SetWebPassword() {
if [ "${SUDO_USER}" == "www-data" ]; then if [ "${SUDO_USER}" == "www-data" ]; then
echo "Security measure: user www-data is not allowed to change webUI password!" echo "Security measure: user www-data is not allowed to change webUI password!"
echo "Exiting" echo "Exiting"
@ -175,8 +167,7 @@ trust-anchor=.,19036,8,2,49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE3
} }
SetDNSServers(){ SetDNSServers() {
# Save setting to file # Save setting to file
delete_setting "PIHOLE_DNS" delete_setting "PIHOLE_DNS"
IFS=',' read -r -a array <<< "${args[2]}" IFS=',' read -r -a array <<< "${args[2]}"
@ -207,72 +198,59 @@ SetDNSServers(){
# Restart dnsmasq to load new configuration # Restart dnsmasq to load new configuration
RestartDNS RestartDNS
} }
SetExcludeDomains(){ SetExcludeDomains() {
change_setting "API_EXCLUDE_DOMAINS" "${args[2]}" change_setting "API_EXCLUDE_DOMAINS" "${args[2]}"
} }
SetExcludeClients(){ SetExcludeClients() {
change_setting "API_EXCLUDE_CLIENTS" "${args[2]}" change_setting "API_EXCLUDE_CLIENTS" "${args[2]}"
} }
Reboot(){ Reboot() {
nohup bash -c "sleep 5; reboot" &> /dev/null </dev/null & nohup bash -c "sleep 5; reboot" &> /dev/null </dev/null &
} }
RestartDNS(){ RestartDNS() {
if [ -x "$(command -v systemctl)" ]; then if [ -x "$(command -v systemctl)" ]; then
systemctl restart dnsmasq &> /dev/null systemctl restart dnsmasq &> /dev/null
else else
service dnsmasq restart &> /dev/null service dnsmasq restart &> /dev/null
fi fi
} }
SetQueryLogOptions(){ SetQueryLogOptions() {
change_setting "API_QUERY_LOG_SHOW" "${args[2]}" change_setting "API_QUERY_LOG_SHOW" "${args[2]}"
} }
ProcessDHCPSettings() { ProcessDHCPSettings() {
source "${setupVars}" source "${setupVars}"
if [[ "${DHCP_ACTIVE}" == "true" ]]; then if [[ "${DHCP_ACTIVE}" == "true" ]]; then
interface=$(grep 'PIHOLE_INTERFACE=' /etc/pihole/setupVars.conf | sed "s/.*=//")
interface=$(grep 'PIHOLE_INTERFACE=' /etc/pihole/setupVars.conf | sed "s/.*=//") # Use eth0 as fallback interface
if [ -z ${interface} ]; then
# Use eth0 as fallback interface interface="eth0"
if [ -z ${interface} ]; then fi
interface="eth0"
fi
if [[ "${PIHOLE_DOMAIN}" == "" ]]; then if [[ "${PIHOLE_DOMAIN}" == "" ]]; then
PIHOLE_DOMAIN="local" PIHOLE_DOMAIN="local"
change_setting "PIHOLE_DOMAIN" "${PIHOLE_DOMAIN}" change_setting "PIHOLE_DOMAIN" "${PIHOLE_DOMAIN}"
fi fi
if [[ "${DHCP_LEASETIME}" == "0" ]]; then if [[ "${DHCP_LEASETIME}" == "0" ]]; then
leasetime="infinite" leasetime="infinite"
elif [[ "${DHCP_LEASETIME}" == "" ]]; then elif [[ "${DHCP_LEASETIME}" == "" ]]; then
leasetime="24h" leasetime="24h"
change_setting "DHCP_LEASETIME" "${leasetime}" change_setting "DHCP_LEASETIME" "${leasetime}"
else else
leasetime="${DHCP_LEASETIME}h" leasetime="${DHCP_LEASETIME}h"
fi fi
# Write settings to file # Write settings to file
echo "############################################################################### echo "###############################################################################
# DHCP SERVER CONFIG FILE AUTOMATICALLY POPULATED BY PI-HOLE WEB INTERFACE. # # DHCP SERVER CONFIG FILE AUTOMATICALLY POPULATED BY PI-HOLE WEB INTERFACE. #
# ANY CHANGES MADE TO THIS FILE WILL BE LOST ON CHANGE # # ANY CHANGES MADE TO THIS FILE WILL BE LOST ON CHANGE #
############################################################################### ###############################################################################
@ -283,26 +261,25 @@ dhcp-leasefile=/etc/pihole/dhcp.leases
#quiet-dhcp #quiet-dhcp
" > "${dhcpconfig}" " > "${dhcpconfig}"
if [[ "${PIHOLE_DOMAIN}" != "none" ]]; then if [[ "${PIHOLE_DOMAIN}" != "none" ]]; then
echo "domain=${PIHOLE_DOMAIN}" >> "${dhcpconfig}" echo "domain=${PIHOLE_DOMAIN}" >> "${dhcpconfig}"
fi fi
if [[ "${DHCP_IPv6}" == "true" ]]; then if [[ "${DHCP_IPv6}" == "true" ]]; then
echo "#quiet-dhcp6 echo "#quiet-dhcp6
#enable-ra #enable-ra
dhcp-option=option6:dns-server,[::] dhcp-option=option6:dns-server,[::]
dhcp-range=::100,::1ff,constructor:${interface},ra-names,slaac,${leasetime} dhcp-range=::100,::1ff,constructor:${interface},ra-names,slaac,${leasetime}
ra-param=*,0,0 ra-param=*,0,0
" >> "${dhcpconfig}" " >> "${dhcpconfig}"
fi fi
else else
rm "${dhcpconfig}" &> /dev/null rm "${dhcpconfig}" &> /dev/null
fi fi
} }
EnableDHCP(){ EnableDHCP() {
change_setting "DHCP_ACTIVE" "true" change_setting "DHCP_ACTIVE" "true"
change_setting "DHCP_START" "${args[2]}" change_setting "DHCP_START" "${args[2]}"
change_setting "DHCP_END" "${args[3]}" change_setting "DHCP_END" "${args[3]}"
@ -320,8 +297,7 @@ EnableDHCP(){
RestartDNS RestartDNS
} }
DisableDHCP(){ DisableDHCP() {
change_setting "DHCP_ACTIVE" "false" change_setting "DHCP_ACTIVE" "false"
# Remove possible old setting from file # Remove possible old setting from file
@ -333,23 +309,20 @@ DisableDHCP(){
RestartDNS RestartDNS
} }
SetWebUILayout(){ SetWebUILayout() {
change_setting "WEBUIBOXEDLAYOUT" "${args[2]}" change_setting "WEBUIBOXEDLAYOUT" "${args[2]}"
} }
CustomizeAdLists() { CustomizeAdLists() {
list="/etc/pihole/adlists.list" list="/etc/pihole/adlists.list"
if [[ "${args[2]}" == "enable" ]] ; then if [[ "${args[2]}" == "enable" ]]; then
sed -i "\\@${args[3]}@s/^#http/http/g" "${list}" sed -i "\\@${args[3]}@s/^#http/http/g" "${list}"
elif [[ "${args[2]}" == "disable" ]] ; then elif [[ "${args[2]}" == "disable" ]]; then
sed -i "\\@${args[3]}@s/^http/#http/g" "${list}" sed -i "\\@${args[3]}@s/^http/#http/g" "${list}"
elif [[ "${args[2]}" == "add" ]] ; then elif [[ "${args[2]}" == "add" ]]; then
echo "${args[3]}" >> ${list} echo "${args[3]}" >> ${list}
elif [[ "${args[2]}" == "del" ]] ; then elif [[ "${args[2]}" == "del" ]]; then
var=$(echo "${args[3]}" | sed 's/\//\\\//g') var=$(echo "${args[3]}" | sed 's/\//\\\//g')
sed -i "/${var}/Id" "${list}" sed -i "/${var}/Id" "${list}"
else else
@ -358,18 +331,15 @@ CustomizeAdLists() {
fi fi
} }
SetPrivacyMode(){ SetPrivacyMode() {
if [[ "${args[2]}" == "true" ]]; then
if [[ "${args[2]}" == "true" ]] ; then
change_setting "API_PRIVACY_MODE" "true" change_setting "API_PRIVACY_MODE" "true"
else else
change_setting "API_PRIVACY_MODE" "false" change_setting "API_PRIVACY_MODE" "false"
fi fi
} }
ResolutionSettings() { ResolutionSettings() {
typ="${args[2]}" typ="${args[2]}"
state="${args[3]}" state="${args[3]}"
@ -378,11 +348,9 @@ ResolutionSettings() {
elif [[ "${typ}" == "clients" ]]; then elif [[ "${typ}" == "clients" ]]; then
change_setting "API_GET_CLIENT_HOSTNAME" "${state}" change_setting "API_GET_CLIENT_HOSTNAME" "${state}"
fi fi
} }
AddDHCPStaticAddress() { AddDHCPStaticAddress() {
mac="${args[2]}" mac="${args[2]}"
ip="${args[3]}" ip="${args[3]}"
host="${args[4]}" host="${args[4]}"
@ -397,18 +365,14 @@ AddDHCPStaticAddress() {
# Full info given # Full info given
echo "dhcp-host=${mac},${ip},${host}" >> "${dhcpstaticconfig}" echo "dhcp-host=${mac},${ip},${host}" >> "${dhcpstaticconfig}"
fi fi
} }
RemoveDHCPStaticAddress() { RemoveDHCPStaticAddress() {
mac="${args[2]}" mac="${args[2]}"
sed -i "/dhcp-host=${mac}.*/d" "${dhcpstaticconfig}" sed -i "/dhcp-host=${mac}.*/d" "${dhcpstaticconfig}"
} }
SetHostRecord(){ SetHostRecord() {
if [ -n "${args[3]}" ]; then if [ -n "${args[3]}" ]; then
change_setting "HOSTRECORD" "${args[2]},${args[3]}" change_setting "HOSTRECORD" "${args[2]},${args[3]}"
echo "Setting host record for ${args[2]} -> ${args[3]}" echo "Setting host record for ${args[2]} -> ${args[3]}"
@ -421,17 +385,28 @@ SetHostRecord(){
# Restart dnsmasq to load new configuration # Restart dnsmasq to load new configuration
RestartDNS RestartDNS
} }
SetListeningMode(){ SetListeningMode() {
source "${setupVars}" source "${setupVars}"
if [[ "${args[2]}" == "all" ]] ; then if [[ "$3" == "-h" ]]; then
echo "Usage: pihole -a -i [interface]
Example: 'pihole -a -i local'
Specify dnsmasq's network interface listening behavior
Interfaces:
local Listen on all interfaces, but only allow queries from
devices that are at most one hop away (local devices)
single Listen only on ${PIHOLE_INTERFACE} interface
all Listen on all interfaces, permit all origins"
exit 0
fi
if [[ "${args[2]}" == "all" ]]; then
echo "Listening on all interfaces, permiting all origins, hope you have a firewall!" echo "Listening on all interfaces, permiting all origins, hope you have a firewall!"
change_setting "DNSMASQ_LISTENING" "all" change_setting "DNSMASQ_LISTENING" "all"
elif [[ "${args[2]}" == "local" ]] ; then elif [[ "${args[2]}" == "local" ]]; then
echo "Listening on all interfaces, permitting only origins that are at most one hop away (local devices)" echo "Listening on all interfaces, permitting only origins that are at most one hop away (local devices)"
change_setting "DNSMASQ_LISTENING" "local" change_setting "DNSMASQ_LISTENING" "local"
else else
@ -446,17 +421,14 @@ SetListeningMode(){
# Restart dnsmasq to load new configuration # Restart dnsmasq to load new configuration
RestartDNS RestartDNS
fi fi
} }
Teleporter() Teleporter() {
{
local datetimestamp=$(date "+%Y-%m-%d_%H-%M-%S") local datetimestamp=$(date "+%Y-%m-%d_%H-%M-%S")
php /var/www/html/admin/scripts/pi-hole/php/teleporter.php > "pi-hole-teleporter_${datetimestamp}.zip" php /var/www/html/admin/scripts/pi-hole/php/teleporter.php > "pi-hole-teleporter_${datetimestamp}.zip"
} }
main() { main() {
args=("$@") args=("$@")
case "${args[1]}" in case "${args[1]}" in
@ -479,7 +451,7 @@ main() {
"addstaticdhcp" ) AddDHCPStaticAddress;; "addstaticdhcp" ) AddDHCPStaticAddress;;
"removestaticdhcp" ) RemoveDHCPStaticAddress;; "removestaticdhcp" ) RemoveDHCPStaticAddress;;
"hostrecord" ) SetHostRecord;; "hostrecord" ) SetHostRecord;;
"-i" | "interface" ) SetListeningMode;; "-i" | "interface" ) SetListeningMode "$@";;
"-t" | "teleporter" ) Teleporter;; "-t" | "teleporter" ) Teleporter;;
"adlist" ) CustomizeAdLists;; "adlist" ) CustomizeAdLists;;
* ) helpFunc;; * ) helpFunc;;
@ -490,5 +462,4 @@ main() {
if [[ $# = 0 ]]; then if [[ $# = 0 ]]; then
helpFunc helpFunc
fi fi
} }

250
pihole

@ -9,11 +9,11 @@
# Please see LICENSE file for your rights under this license. # Please see LICENSE file for your rights under this license.
readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" readonly PI_HOLE_SCRIPT_DIR="/opt/pihole"
readonly wildcardlist="/etc/dnsmasq.d/03-pihole-wildcard.conf" readonly wildcardlist="/etc/dnsmasq.d/03-pihole-wildcard.conf"
# Must be root to use this tool # Must be root to use this tool
if [[ ! $EUID -eq 0 ]];then if [[ ! $EUID -eq 0 ]];then
if [ -x "$(command -v sudo)" ];then if [[ -x "$(command -v sudo)" ]]; then
exec sudo bash "$0" "$@" exec sudo bash "$0" "$@"
exit $? exit $?
else else
@ -80,66 +80,49 @@ updateGravityFunc() {
exit 0 exit 0
} }
scanList(){ scanList() {
domain="${1}" domain="${1}"
list="${2}" list="${2}"
method="${3}" method="${3}"
if [[ ${method} == "-exact" ]] ; then
grep -i -E "(^|\s)${domain}($|\s)" "${list}" if [[ "${method}" == "-exact" ]]; then
grep -i -E -l "(^|\s|\/)${domain}($|\s|\/)" ${list}
else else
grep -i "${domain}" "${list}" grep -i "${domain}" ${list}
fi fi
} }
processWildcards() {
IFS="." read -r -a array <<< "${1}"
for (( i=${#array[@]}-1; i>=0; i-- )); do
ar=""
for (( j=${#array[@]}-1; j>${#array[@]}-i-2; j-- )); do
if [[ $j == $((${#array[@]}-1)) ]]; then
ar="${array[$j]}"
else
ar="${array[$j]}.${ar}"
fi
done
echo "${ar}"
done
}
queryFunc() { queryFunc() {
domain="${2}"
method="${3}" method="${3}"
lists=( /etc/pihole/list.* /etc/pihole/blacklist.txt)
for list in ${lists[@]}; do # If domain contains non ASCII characters, convert domain to punycode if python exists
if [ -e "${list}" ]; then # Cr: https://serverfault.com/a/335079
result=$(scanList ${domain} ${list} ${method}) if [[ -z "${2}" ]]; then
# Remove empty lines before couting number of results echo "::: No domain specified"
count=$(sed '/^\s*$/d' <<< "$result" | wc -l) exit 1
echo "::: ${list} (${count} results)" elif [[ "${2}" = *[![:ascii:]]* ]]; then
if [[ ${count} > 0 ]]; then [[ "$(which python)" ]] && domain=$(python -c 'import sys;print sys.argv[1].decode("utf-8").encode("idna")' "${2}")
echo "${result}" else
fi domain="${2}"
echo "" fi
else
echo "::: ${list} does not exist" # Scan Whitelist, Blacklist and Wildcards
echo "" lists="/etc/pihole/whitelist.txt /etc/pihole/blacklist.txt $wildcardlist"
fi result=$(scanList ${domain} "${lists}" ${method})
done if [[ -n "$result" ]]; then
echo "$result"
# Scan for possible wildcard matches [[ ! -t 1 ]] && exit 0
if [ -e "${wildcardlist}" ]; then fi
local wildcards=($(processWildcards "${domain}"))
for domain in ${wildcards[@]}; do # Scan Domains lists
result=$(scanList "\/${domain}\/" ${wildcardlist}) result=$(scanList ${domain} "/etc/pihole/*.domains" ${method})
# Remove empty lines before couting number of results if [[ -n "$result" ]]; then
count=$(sed '/^\s*$/d' <<< "$result" | wc -l) sort -t . -k 2 -g <<< "$result"
if [[ ${count} > 0 ]]; then else
echo "::: Wildcard blocking ${domain} (${count} results)" [ -n "$method" ] && exact="exact "
echo "${result}" echo "::: No ${exact}results found for ${domain}"
echo ""
fi
done
fi fi
exit 0 exit 0
} }
@ -163,16 +146,16 @@ versionFunc() {
restartDNS() { restartDNS() {
dnsmasqPid=$(pidof dnsmasq) dnsmasqPid=$(pidof dnsmasq)
if [[ ${dnsmasqPid} ]]; then if [[ "${dnsmasqPid}" ]]; then
# service already running - reload config # Service already running - reload config
if [ -x "$(command -v systemctl)" ]; then if [[ -x "$(command -v systemctl)" ]]; then
systemctl restart dnsmasq systemctl restart dnsmasq
else else
service dnsmasq restart service dnsmasq restart
fi fi
else else
# service not running, start it up # Service not running, start it up
if [ -x "$(command -v systemctl)" ]; then if [[ -x "$(command -v systemctl)" ]]; then
systemctl start dnsmasq systemctl start dnsmasq
else else
service dnsmasq start service dnsmasq start
@ -181,16 +164,25 @@ restartDNS() {
} }
piholeEnable() { piholeEnable() {
if [[ "${1}" == "0" ]] ; then if [[ "${2}" == "-h" ]]; then
#Disable Pihole echo "Usage: pihole disable [time]
Example: 'pihole disable', or 'pihole disable 5m'
Disable Pi-hole subsystems
Time:
#s Disable Pi-hole functionality for # second(s)
#m Disable Pi-hole functionality for # minute(s)"
exit 0
elif [[ "${1}" == "0" ]]; then
# Disable Pi-hole
sed -i 's/^addn-hosts=\/etc\/pihole\/gravity.list/#addn-hosts=\/etc\/pihole\/gravity.list/' /etc/dnsmasq.d/01-pihole.conf sed -i 's/^addn-hosts=\/etc\/pihole\/gravity.list/#addn-hosts=\/etc\/pihole\/gravity.list/' /etc/dnsmasq.d/01-pihole.conf
echo "::: Blocking has been disabled!" echo "::: Blocking has been disabled!"
if [[ $# > 1 ]] ; then if [[ $# > 1 ]]; then
if [[ ${2} == *"s"* ]] ; then if [[ "${2}" == *"s"* ]]; then
tt=${2%"s"} tt=${2%"s"}
echo "::: Blocking will be re-enabled in ${tt} seconds" echo "::: Blocking will be re-enabled in ${tt} seconds"
nohup bash -c "sleep ${tt}; pihole enable" </dev/null &>/dev/null & nohup bash -c "sleep ${tt}; pihole enable" </dev/null &>/dev/null &
elif [[ ${2} == *"m"* ]] ; then elif [[ "${2}" == *"m"* ]]; then
tt=${2%"m"} tt=${2%"m"}
echo "::: Blocking will be re-enabled in ${tt} minutes" echo "::: Blocking will be re-enabled in ${tt} minutes"
tt=$((${tt}*60)) tt=$((${tt}*60))
@ -204,7 +196,7 @@ piholeEnable() {
fi fi
fi fi
else else
#Enable pihole # Enable Pi-hole
echo "::: Blocking has been enabled!" echo "::: Blocking has been enabled!"
sed -i 's/^#addn-hosts/addn-hosts/' /etc/dnsmasq.d/01-pihole.conf sed -i 's/^#addn-hosts/addn-hosts/' /etc/dnsmasq.d/01-pihole.conf
fi fi
@ -213,15 +205,23 @@ piholeEnable() {
piholeLogging() { piholeLogging() {
shift shift
if [[ "${1}" == "-h" ]]; then
if [[ "${1}" == "off" ]] ; then echo "Usage: pihole logging [options]
#Disable Logging Example: 'pihole logging on'
Specify whether the Pi-hole log should be used
Options:
on Enable the Pi-hole log at /var/log/pihole.log
off Disable the Pi-hole log at /var/log/pihole.log"
exit 0
elif [[ "${1}" == "off" ]]; then
# Disable logging
sed -i 's/^log-queries/#log-queries/' /etc/dnsmasq.d/01-pihole.conf sed -i 's/^log-queries/#log-queries/' /etc/dnsmasq.d/01-pihole.conf
sed -i 's/^QUERY_LOGGING=true/QUERY_LOGGING=false/' /etc/pihole/setupVars.conf sed -i 's/^QUERY_LOGGING=true/QUERY_LOGGING=false/' /etc/pihole/setupVars.conf
pihole -f pihole -f
echo "::: Logging has been disabled!" echo "::: Logging has been disabled!"
elif [[ "${1}" == "on" ]] ; then elif [[ "${1}" == "on" ]]; then
#Enable logging # Enable logging
sed -i 's/^#log-queries/log-queries/' /etc/dnsmasq.d/01-pihole.conf sed -i 's/^#log-queries/log-queries/' /etc/dnsmasq.d/01-pihole.conf
sed -i 's/^QUERY_LOGGING=false/QUERY_LOGGING=true/' /etc/pihole/setupVars.conf sed -i 's/^QUERY_LOGGING=false/QUERY_LOGGING=true/' /etc/pihole/setupVars.conf
echo "::: Logging has been enabled!" echo "::: Logging has been enabled!"
@ -233,12 +233,12 @@ piholeLogging() {
} }
piholeStatus() { piholeStatus() {
if [[ $(netstat -plnt | grep -c ':53 ') > 0 ]]; then if [[ "$(netstat -plnt | grep -c ':53 ')" -gt "0" ]]; then
if [[ "${1}" != "web" ]] ; then if [[ "${1}" != "web" ]]; then
echo "::: DNS service is running" echo "::: DNS service is running"
fi fi
else else
if [[ "${1}" == "web" ]] ; then if [[ "${1}" == "web" ]]; then
echo "-1"; echo "-1";
else else
echo "::: DNS service is NOT running" echo "::: DNS service is NOT running"
@ -246,28 +246,28 @@ piholeStatus() {
return return
fi fi
if [[ $(grep -i "^#addn-hosts=/" /etc/dnsmasq.d/01-pihole.conf) ]] ; then if [[ "$(grep -i "^#addn-hosts=/" /etc/dnsmasq.d/01-pihole.conf)" ]]; then
#list is commented out # List is commented out
if [[ "${1}" == "web" ]] ; then if [[ "${1}" == "web" ]]; then
echo 0; echo 0;
else else
echo "::: Pi-hole blocking is Disabled"; echo "::: Pi-hole blocking is Disabled";
fi fi
elif [[ $(grep -i "^addn-hosts=/" /etc/dnsmasq.d/01-pihole.conf) ]] ; then elif [[ "$(grep -i "^addn-hosts=/" /etc/dnsmasq.d/01-pihole.conf)" ]]; then
#list set # List set
if [[ "${1}" == "web" ]] ; then if [[ "${1}" == "web" ]]; then
echo 1; echo 1;
else else
echo "::: Pi-hole blocking is Enabled"; echo "::: Pi-hole blocking is Enabled";
fi fi
else else
#addn-host not found # Addn-host not found
if [[ "${1}" == "web" ]] ; then if [[ "${1}" == "web" ]]; then
echo 99 echo 99
else else
echo "::: No hosts file linked to dnsmasq, adding it in enabled state" echo "::: No hosts file linked to dnsmasq, adding it in enabled state"
fi fi
#add addn-host= to dnsmasq # Add addn-host= to dnsmasq
echo "addn-hosts=/etc/pihole/gravity.list" >> /etc/dnsmasq.d/01-pihole.conf echo "addn-hosts=/etc/pihole/gravity.list" >> /etc/dnsmasq.d/01-pihole.conf
restartDNS restartDNS
fi fi
@ -280,46 +280,66 @@ tailFunc() {
} }
piholeCheckoutFunc() { piholeCheckoutFunc() {
if [[ "$2" == "-h" ]]; then
echo "Usage: pihole checkout [repo] [branch]
Example: 'pihole checkout master' or 'pihole checkout core dev'
Switch Pi-hole subsystems to a different Github branch
Repositories:
core [branch] Change the branch of Pi-hole's core subsystem
web [branch] Change the branch of Admin Console subsystem
Branches:
master Update subsystems to the latest stable release
dev Update subsystems to the latest development release"
exit 0
fi
source "${PI_HOLE_SCRIPT_DIR}"/piholeCheckout.sh source "${PI_HOLE_SCRIPT_DIR}"/piholeCheckout.sh
shift shift
checkout "$@" checkout "$@"
} }
helpFunc() { helpFunc() {
cat << EOM echo "Usage: pihole [options]
::: Control all Pi-hole specific functions Example: 'pihole -w -h'
::: Add '-h' after specific commands for more information on usage
::: Usage: pihole [options]
::: Add -h after -w (whitelist), -b (blacklist), -c (chronometer), or -a (admin) for more information on usage Whitelist/Blacklist Options:
::: -w, whitelist Whitelist domain(s)
::: Options: -b, blacklist Blacklist domain(s)
::: -w, whitelist Whitelist domain(s) -wild, wildcard Blacklist domain(s), and all its subdomains
::: -b, blacklist Blacklist domain(s) (exact match) Add '-h' for more info on whitelist/blacklist usage
::: -wild, wildcard Blacklist whole domain(s) (wildcard)
::: -d, debug Start a debugging session Debugging Options:
::: Automated debugging can be enabled with '-a'. -d, debug Start a debugging session
::: 'pihole -d -a' Add '-a' to enable automated debugging
::: -f, flush Flush the 'pihole.log' file -f, flush Flush the Pi-hole log
::: -t, tail Output the last lines of the 'pihole.log' file. Lines are appended as the file grows -r, reconfigure Reconfigure or Repair Pi-hole subsystems
::: -up, updatePihole Update Pi-hole components -t, tail View the live output of the Pi-hole log
::: -r, reconfigure Reconfigure or Repair Pi-hole
::: -g, updateGravity Update the list of ad-serving domains Options:
::: -c, chronometer Calculates stats and displays to an LCD -a, admin Admin Console options
::: -h, help Show this help dialog Add '-h' for more info on admin console usage
::: -v, version Show installed versions of Pi-hole and Web-Admin -c, chronometer Calculates stats and displays to an LCD
::: -q, query Query the adlists for a specific domain Add '-h' for more info on chronometer usage
::: 'pihole -q domain -exact' shows exact matches only -g, updateGravity Update the list of ad-serving domains
::: -l, logging Enable or Disable logging (pass 'on' or 'off') -h, --help, help Show this help dialog
::: -a, admin Admin webpage options -l, logging Specify whether the Pi-hole log should be used
::: uninstall Uninstall Pi-hole from your system! :( Add '-h' for more info on logging usage
::: status Display if Pi-hole is Enabled or Disabled -q, query Query the adlists for a specified domain
::: enable Enable Pi-hole DNS Blocking Add '-exact' AFTER a specified domain for exact match
::: disable Disable Pi-hole DNS Blocking -up, updatePihole Update Pi-hole subsystems
::: Blocking can also be disabled only temporarily, e.g., -v, version Show installed versions of Pi-hole, Admin Console & FTL
::: 'pihole disable 5m' - will disable blocking for 5 minutes Add '-h' for more info on version usage
::: restartdns Restart dnsmasq uninstall Uninstall Pi-hole from your system
::: checkout Check out different branches status Display the running status of Pi-hole subsystems
EOM enable Enable Pi-hole subsystems
disable Disable Pi-hole subsystems
Add '-h' for more info on disable usage
restartdns Restart Pi-hole subsystems
checkout Switch Pi-hole subsystems to a different Github branch
Add '-h' for more info on checkout usage";
exit 0 exit 0
} }
@ -344,7 +364,7 @@ case "${1}" in
"-l" | "logging" ) piholeLogging "$@";; "-l" | "logging" ) piholeLogging "$@";;
"uninstall" ) uninstallFunc;; "uninstall" ) uninstallFunc;;
"enable" ) piholeEnable 1;; "enable" ) piholeEnable 1;;
"disable" ) piholeEnable 0 $2;; "disable" ) piholeEnable 0 "$2";;
"status" ) piholeStatus "$2";; "status" ) piholeStatus "$2";;
"restartdns" ) restartDNS;; "restartdns" ) restartDNS;;
"-a" | "admin" ) webpageFunc "$@";; "-a" | "admin" ) webpageFunc "$@";;

Loading…
Cancel
Save