diff --git a/.pullapprove.yml b/.pullapprove.yml
index 8bd8f0a2b..8bd890cba 100644
--- a/.pullapprove.yml
+++ b/.pullapprove.yml
@@ -33,6 +33,6 @@ groups:
conditions:
branches:
- master
- required: -1
+ required: 4
teams:
- admin
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 64e702f86..bfb67b776 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -7,3 +7,4 @@ This is a basic checklist for now, We will update it in the future.
* Submit Pull Requests to the development branch only.
* Before Submitting your Pull Request, merge `devel` with your new branch and fix any conflicts. (Make sure you don't break anything in development!)
* Be patient. We will review all submitted pull requests, but our focus is on stability.. please don't be offended if we reject your PR, or it appears we're doing nothing with it! We'll get around to it..
+* Please use the Pi-hole brand: **Pi-hole** (Take a special look at the capitalized 'P' and a low 'h' with a hyphen)
diff --git a/README.md b/README.md
index 12769874c..e3f3b257a 100644
--- a/README.md
+++ b/README.md
@@ -22,8 +22,10 @@ A read-only API can be accessed at `/admin/api.php`. With either no parameters o
}
```
-There are many more parameters, such as `summaryRaw`, `overTimeData10mins`, ` topClients` or `getQuerySources`, `getQueryTypes`, `getForwardDestinations`, and `getAllQueries`.
-Together with a token it is also possible to enable and disable (also with a set timeout) blocking via the API.
+There are many more parameters, such as `summaryRaw`, `overTimeData10mins`, `topItems`, ` topClients` or `getQuerySources`, `getQueryTypes`, `getForwardDestinations`, and finally `getAllQueries`.
+Together with a token it is also possible to enable and disable (also with a set timeout) blocking via the API
+
+The API returns more information (in a slighly different format if `FTL` is running) - it supports a fall-back to the "old" PHP API if `FTL` is not running. Test the type and/or version of the API by using the parameter `type` and `version`.
Summary: A summary of statistics showing how many total DNS queries have been blocked today, what percentage of DNS queries have been blocked, and how many domains are in the compiled ad list. This summary is updated every 10 seconds.
Queries over time: Graph showing DNS queries (total and blocked) over 10 minute time intervals. More information can be acquired by hovering over the lines. This graph is updated every 10 minutes.
-
Query Types: Identifies the types of processed queries:
-
-
A: address lookup (most commonly used to map hostnames to an IPv4 address of the host)
-
AAAA: address lookup (most commonly used to map hostnames to an IPv6 address of the host)
-
PTR: most common use is for implementing reverse DNS lookups
-
SRV: Service locator (often used by XMPP, SIP, and LDAP)
-
and others
-
-
+
Query Types: Identifies the types of processed queries
Forward Destinations: Shows to which upstream DNS the permitted requests have been forwarded to.
Top Domains: Ranking of requested sites by number of DNS lookups.
Top Advertisers: Ranking of requested advertisements by number of DNS lookups.
Top Clients: Ranking of how many DNS requests each client has made on the local network.
+
The Top Domains and Top Advertisers lists may be hidden depending on the privacy Settings on the settings page
Note that the login session does not expire on the dashboard, as the summary is updated every 10 seconds which refreshes the session.
@@ -70,7 +63,7 @@
Query Log
-
Shows the recent queries by parsing Pi-hole's log. It is possible to search through the whole list by using the "Search" input field. If the status is reported as "OK", then the DNS request has been permitted. Otherwise ("Pi-holed") it has been blocked. By clicking on the buttons under "Action" the corresponding domains can quickly be added to the white-/blacklist. The status of the action will be reported on this page.
+
Shows the recent queries by parsing Pi-hole's log. It is possible to search through the whole list by using the "Search" input field. If the status is reported as "OK", then the DNS request has been permitted. Otherwise ("Pi-holed") it has been blocked. By clicking on the buttons under "Action" the corresponding domains can quickly be added to the white-/blacklist. The status of the action will be reported on this page. By default, only the recent 10 minutes are shown to enhance the loading speed of the query log page. All domains can be requested by clicking on the corresponding link in the header of the page. Note that the result heavily depends on your privacy settings (see Settings page).
@@ -84,7 +77,7 @@
Disable / Enable
- Disables/enables Pi-Hole blocking completely. You may have to wait a few minutes for the changes to reach all of your devices. The change will be reflected by a changed status (top left)
+ Disables/enables Pi-hole blocking completely. You may have to wait a few minutes for the changes to reach all of your devices. The change will be reflected by a changed status (top left)
@@ -108,18 +101,22 @@
Settings
- Change settings for the Pi-Hole
+ Change settings for the Pi-hole
Networking
- Displays information about the interfaces of the Pi-Hole. No changes possible.
-
Pi-Hole DHCP Server
- Using this setting you can enable/disable the DHCP server of the Pi-Hole. Note that you should disable any other DHCP server on your network to avoid IP addresses being used more than once. You have to give the range of IPs that DHCP will serve and the IP of the local router (gateway). If the DHCP server is active, the current leases are shown on the settings page. IPv4 DHCP will always be activated, IPv6 (stateless + statefull) can be enabled.
+ Displays information about the interfaces of the Pi-hole. No changes possible.
+
Pi-hole DHCP Server
+ Using this setting you can enable/disable the DHCP server of the Pi-hole. Note that you should disable any other DHCP server on your network to avoid IP addresses being used more than once. You have to give the range of IPs that DHCP will serve and the IP of the local router (gateway). If the DHCP server is active, the current leases are shown on the settings page. IPv4 DHCP will always be activated, IPv6 (stateless + statefull) can be enabled.
Upstream DNS Servers
Customize used upstream DNS servers + advanced settings for DNS servers. Note that any number of DNS servers may be enabled at a time.
Query Logging
Enabled/disable query logging on your Pi-hole + provide option to flush the log
API
- Change settings which apply to the API as well as the web UI
- Note that Top Clients have to be given as IP addresses
+ Change settings which apply to the API as well as the web UI
+
+
Show permitted domain entries: Toogle permitted queries in Query Log + Top Domains on Main Page
+
Show blockes domain entries: Toogle blocked queries in Query Log + Top Ads on Main Page
+
Privacy mode: Replace IPs in query log with "hidden"
+
Web User Interface
Other settings which affect the webUI but not the API of Pi-hole
System Administration
@@ -129,7 +126,7 @@
Authentication system (currently enableddisabled)
-
Using the command
sudo pihole -a -p pa22w0rd
where pa22w0rd is the password to be set in this example, one can enable the authentication system of this web interface. Thereafter, a login is required for most pages (the dashboard will show a limited amount of statistics). Note that the authentication system may be disabled again, by setting an empty password using the command shown above. The Help center will show more details concerning the authentication system only if it is enabled
+
Using the command
sudo pihole -a -p
and entering a password to be set, one can enable the authentication system of this web interface. Thereafter, a login is required for most pages (the dashboard will show a limited amount of statistics). Note that the authentication system may be disabled again, by setting an empty password using the command shown above. The Help center will show more details concerning the authentication system only if it is enabled
Note that the ad list domains are automatically added to the whitelist so that a list can never get blocked by another list.
@@ -46,6 +47,7 @@ function getFullName() {
Note: Whitelisting a subdomain of a wildcard blocked domain is not possible.
+
Some of the domains shown below are domains of the adlists sources, which are automatically added in order to prevent adlists being able to blacklist each other. See here for the default set of adlists.
@@ -62,6 +64,7 @@ function getFullName() {
Failure! Something went wrong.
+
Exact blocking
diff --git a/queries.php b/queries.php
index 61e243083..acc50db5e 100644
--- a/queries.php
+++ b/queries.php
@@ -1,10 +1,10 @@
-
-show all";
+}
if(isset($setupVars["API_PRIVACY_MODE"]))
{
if($setupVars["API_PRIVACY_MODE"])
{
// Overwrite string from above
- $showing = "(privacy mode enabled)";
+ $showing .= ", privacy mode enabled";
}
}
+
+if(strlen($showing) > 0)
+{
+ $showing = "(".$showing.")";
+}
?>
@@ -114,6 +146,5 @@
require "scripts/pi-hole/php/footer.php";
?>
-
-
+
diff --git a/queryads.php b/queryads.php
index 272fe34b7..14bec1dd4 100644
--- a/queryads.php
+++ b/queryads.php
@@ -1,10 +1,10 @@
-
-
diff --git a/scripts/pi-hole/js/debug.js b/scripts/pi-hole/js/debug.js
index c0db2ce01..0a6b3ab1b 100644
--- a/scripts/pi-hole/js/debug.js
+++ b/scripts/pi-hole/js/debug.js
@@ -29,20 +29,21 @@ function eventsource() {
var ta = $("#output");
var upload = $( "#upload" );
var checked = "";
+ var token = encodeURIComponent($("#token").html());
if(upload.prop("checked"))
{
- checked = "upload";
+ checked = "upload";
}
// IE does not support EventSource - load whole content at once
if (typeof EventSource !== "function") {
- httpGet(ta,"/admin/scripts/pi-hole/php/debug.php?IE&"+checked);
+ httpGet(ta,"/admin/scripts/pi-hole/php/debug.php?IE&token="+token+"&"+checked);
return;
}
var host = window.location.host;
- var source = new EventSource("/admin/scripts/pi-hole/php/debug.php?"+checked);
+ var source = new EventSource("/admin/scripts/pi-hole/php/debug.php?&token="+token+"&"+checked);
// Reset and show field
ta.empty();
diff --git a/scripts/pi-hole/js/footer.js b/scripts/pi-hole/js/footer.js
index 20866b850..e6c3c1574 100644
--- a/scripts/pi-hole/js/footer.js
+++ b/scripts/pi-hole/js/footer.js
@@ -144,6 +144,7 @@ $("#pihole-disable-custom").on("click", function(e){
var piholeVersion = $("#piholeVersion").html();
var webVersion = $("#webVersion").html();
+var FTLVersion = $("#FTLVersion").html();
// Credit for following function: https://gist.github.com/alexey-bass/1115557
// Modified to discard any possible "v" in the string
@@ -183,17 +184,24 @@ function versionCompare(left, right) {
$.getJSON("https://api.github.com/repos/pi-hole/pi-hole/releases/latest", function(json) {
if(versionCompare(piholeVersion, json.tag_name.slice(1)) < 0) {
// Alert user
- $("#piholeVersion").html($("#piholeVersion").text() + "(Update available!)");
+ $("#piholeVersion").html($("#piholeVersion").text() + " (Update available!)");
$("#alPiholeUpdate").show();
}
});
$.getJSON("https://api.github.com/repos/pi-hole/AdminLTE/releases/latest", function(json) {
if(versionCompare(webVersion, json.tag_name.slice(1)) < 0) {
// Alert user
- $("#webVersion").html($("#webVersion").text() + "(Update available!)");
+ $("#webVersion").html($("#webVersion").text() + " (Update available!)");
$("#alWebUpdate").show();
}
});
+$.getJSON("https://api.github.com/repos/pi-hole/FTL/releases/latest", function(json) {
+ if(versionCompare(FTLVersion, json.tag_name.slice(1)) < 0) {
+ // Alert user
+ $("#FTLVersion").html($("#FTLVersion").text() + " (Update available!)");
+ $("#alFTLUpdate").show();
+ }
+});
/*
* Make sure that Pi-hole is updated to at least v2.7, since that is needed to use the sudo
diff --git a/scripts/pi-hole/js/gravity.js b/scripts/pi-hole/js/gravity.js
index 20cf9fcd5..84b26b73e 100644
--- a/scripts/pi-hole/js/gravity.js
+++ b/scripts/pi-hole/js/gravity.js
@@ -45,9 +45,23 @@ $("#gravityBtn").on("click", function(){
eventsource();
});
+$("#gravityBtn").on("click", () => {
+ $("#gravityBtn").attr("disabled", true);
+ eventsource();
+});
+
// Handle hiding of alerts
$(function(){
$("[data-hide]").on("click", function(){
$(this).closest("." + $(this).attr("data-hide")).hide();
});
+
+ // Do we want to start updating immediately?
+ // gravity.php?go
+ var searchString = window.location.search.substring(1);
+ if(searchString.indexOf("go") !== -1)
+ {
+ $("#gravityBtn").attr("disabled", true);
+ eventsource();
+ }
});
diff --git a/scripts/pi-hole/js/index.js b/scripts/pi-hole/js/index.js
index 537188fbd..6aabe866f 100644
--- a/scripts/pi-hole/js/index.js
+++ b/scripts/pi-hole/js/index.js
@@ -29,39 +29,15 @@ function objectToArray(p){
// Functions to update data in page
-
-function updateSummaryData(runOnce) {
- var setTimer = function(timeInSeconds) {
- if (!runOnce) {
- setTimeout(updateSummaryData, timeInSeconds * 1000);
- }
- };
- $.getJSON("api.php?summary", function LoadSummaryData(data) {
-
- ["ads_blocked_today", "dns_queries_today", "ads_percentage_today"].forEach(function(today) {
- var todayElement = $("h3#" + today);
- todayElement.text() !== data[today] && todayElement.addClass("glow");
- });
-
- window.setTimeout(function() {
- ["ads_blocked_today", "dns_queries_today", "domains_being_blocked", "ads_percentage_today"].forEach(function(header, idx) {
- var textData = idx === 3 ? data[header] + "%" : data[header];
- $("h3#" + header).text(textData);
- });
- $("h3.statistic.glow").removeClass("glow");
- }, 500);
-
- updateSessionTimer();
- }).done(function() {
- setTimer(10);
- }).fail(function() {
- setTimer(300);
- });
-}
-
var failures = 0;
function updateQueriesOverTime() {
$.getJSON("api.php?overTimeData10mins", function(data) {
+
+ if("FTLnotrunning" in data)
+ {
+ return;
+ }
+
// convert received objects to arrays
data.domains_over_time = objectToArray(data.domains_over_time);
data.ads_over_time = objectToArray(data.ads_over_time);
@@ -71,18 +47,29 @@ function updateQueriesOverTime() {
timeLineChart.data.labels = [];
timeLineChart.data.datasets[0].data = [];
timeLineChart.data.datasets[1].data = [];
- // Add data for each hour that is available
+
+ // Add data for each hour that is available
for (var hour in data.ads_over_time[0]) {
if ({}.hasOwnProperty.call(data.ads_over_time[0], hour)) {
- var h = parseInt(data.domains_over_time[0][hour]);
- var d = new Date().setHours(Math.floor(h / 6), 10 * (h % 6), 0, 0);
+ var d,h;
+ h = parseInt(data.domains_over_time[0][hour]);
+ if(parseInt(data.ads_over_time[0][0]) < 1200)
+ {
+ // Fallback - old style
+ d = new Date().setHours(Math.floor(h / 6), 10 * (h % 6), 0, 0);
+ }
+ else
+ {
+ // New style: Get Unix timestamps
+ d = new Date(1000*h);
+ }
timeLineChart.data.labels.push(d);
timeLineChart.data.datasets[0].data.push(data.domains_over_time[1][hour]);
timeLineChart.data.datasets[1].data.push(data.ads_over_time[1][hour]);
}
}
- $("#queries-over-time .overlay").remove();
+ $("#queries-over-time .overlay").hide();
timeLineChart.update();
}).done(function() {
// Reload graph after 10 minutes
@@ -99,26 +86,148 @@ function updateQueriesOverTime() {
});
}
-function updateQueryTypes() {
- $.getJSON("api.php?getQueryTypes", function(data) {
+function updateQueryTypesOverTime() {
+ $.getJSON("api.php?overTimeDataQueryTypes", function(data) {
+
+ if("FTLnotrunning" in data)
+ {
+ return;
+ }
+
+ // convert received objects to arrays
+ data.over_time = objectToArray(data.over_time);
+ var timestamps = data.over_time[0];
+ var plotdata = data.over_time[1];
+ // Remove possibly already existing data
+ queryTypeChart.data.labels = [];
+ queryTypeChart.data.datasets[0].data = [];
+ queryTypeChart.data.datasets[1].data = [];
+
var colors = [];
- // Get colors from AdminLTE
$.each($.AdminLTE.options.colors, function(key, value) { colors.push(value); });
- var v = [], c = [];
- // Collect values and colors, immediately push individual labels
- $.each(data, function(key , value) {
- v.push(value);
- c.push(colors.shift());
- queryTypeChart.data.labels.push(key.substr(6,key.length - 7));
- });
- // Build a single dataset with the data to be pushed
- var dd = {data: v, backgroundColor: c};
- // and push it at once
- queryTypeChart.data.datasets.push(dd);
- $("#query-types .overlay").remove();
- queryTypeChart.update();
- queryTypeChart.chart.config.options.cutoutPercentage=30;
+ queryTypeChart.data.datasets[0].backgroundColor = colors[0];
+ queryTypeChart.data.datasets[1].backgroundColor = colors[1];
+
+ // Add data for each hour that is available
+ for (var j in timestamps) {
+ if ({}.hasOwnProperty.call(timestamps, j)) {
+ var d,h;
+ h = parseInt(timestamps[j]);
+ // New style: Get Unix timestamps
+ d = new Date(1000*h);
+
+ var sum = plotdata[j][0] + plotdata[j][1];
+ var A = 0, AAAA = 0;
+ if(sum > 0)
+ {
+ A = plotdata[j][0]/sum;
+ AAAA = plotdata[j][1]/sum;
+ }
+
+ queryTypeChart.data.labels.push(d);
+ queryTypeChart.data.datasets[0].data.push(A);
+ queryTypeChart.data.datasets[1].data.push(AAAA);
+ }
+ }
+ $("#query-types .overlay").hide();
queryTypeChart.update();
+ }).done(function() {
+ // Reload graph after 10 minutes
+ failures = 0;
+ setTimeout(updateQueryTypesOverTime, 600000);
+ }).fail(function() {
+ failures++;
+ if(failures < 5)
+ {
+ // Try again after 1 minute only if this has not failed more
+ // than five times in a row
+ setTimeout(updateQueryTypesOverTime, 60000);
+ }
+ });
+}
+
+function updateForwardedOverTime() {
+ $.getJSON("api.php?overTimeDataForwards&getForwardDestinationNames", function(data) {
+
+ if("FTLnotrunning" in data)
+ {
+ return;
+ }
+
+ // convert received objects to arrays
+ data.over_time = objectToArray(data.over_time);
+ var timestamps = data.over_time[0];
+ var plotdata = data.over_time[1];
+ var labels = [];
+ var key, i, j;
+ for (key in data.forward_destinations)
+ {
+ if (!{}.hasOwnProperty.call(data.forward_destinations, key)) continue;
+ if(key.indexOf("|") > -1)
+ {
+ var idx = key.indexOf("|");
+ key = key.substr(0, idx);
+ }
+ labels.push(key);
+ }
+ // Get colors from AdminLTE
+ var colors = [];
+ $.each($.AdminLTE.options.colors, function(key, value) { colors.push(value); });
+ var v = [], c = [], k = [];
+
+ // Remove possibly already existing data
+ forwardDestinationChart.data.labels = [];
+ forwardDestinationChart.data.datasets[0].data = [];
+ for (i = 1; i < forwardDestinationChart.data.datasets.length; i++)
+ {
+ forwardDestinationChart.data.datasets[i].data = [];
+ }
+
+ // Collect values and colors, and labels
+ forwardDestinationChart.data.datasets[0].backgroundColor = colors[0];
+ forwardDestinationChart.data.datasets[0].pointRadius = 0;
+ forwardDestinationChart.data.datasets[0].label = labels[0];
+
+ for (i = forwardDestinationChart.data.datasets.length; i < plotdata[0].length; i++)
+ {
+ forwardDestinationChart.data.datasets.push({data: [], backgroundColor: colors[i], pointRadius: 0, label: labels[i]});
+ }
+
+ // Add data for each dataset that is available
+ for (j in timestamps)
+ {
+ if (!{}.hasOwnProperty.call(timestamps, j)) continue;
+ var sum = 0.0;
+ for (key in plotdata[j])
+ {
+ if (!{}.hasOwnProperty.call(plotdata[j], key)) continue;
+ sum += plotdata[j][key];
+ }
+ var dd = [];
+ for (key in plotdata[j])
+ {
+ if (!{}.hasOwnProperty.call(plotdata[j], key)) continue;
+ var singlepoint = plotdata[j][key];
+ forwardDestinationChart.data.datasets[key].data.push(singlepoint/sum);
+ }
+
+ var d = new Date(1000*parseInt(timestamps[j]));
+ forwardDestinationChart.data.labels.push(d);
+ }
+ $("#forward-destinations .overlay").hide();
+ forwardDestinationChart.update();
+ }).done(function() {
+ // Reload graph after 10 minutes
+ failures = 0;
+ setTimeout(updateForwardedOverTime, 600000);
+ }).fail(function() {
+ failures++;
+ if(failures < 5)
+ {
+ // Try again after 1 minute only if this has not failed more
+ // than five times in a row
+ setTimeout(updateForwardedOverTime, 60000);
+ }
});
}
@@ -137,68 +246,59 @@ function escapeHtml(text) {
function updateTopClientsChart() {
$.getJSON("api.php?summaryRaw&getQuerySources", function(data) {
+
+ if("FTLnotrunning" in data)
+ {
+ return;
+ }
+
+ // Clear tables before filling them with data
+ $("#client-frequency td").parent().remove();
var clienttable = $("#client-frequency").find("tbody:last");
- var domain, percentage, domainname, domainip;
- for (domain in data.top_sources) {
+ var client, percentage, clientname, clientip;
+ for (client in data.top_sources) {
- if ({}.hasOwnProperty.call(data.top_sources, domain)){
- // Sanitize domain
- domain = escapeHtml(domain);
- if(domain.indexOf("|") > -1)
+ if ({}.hasOwnProperty.call(data.top_sources, client)){
+ // Sanitize client
+ client = escapeHtml(client);
+ if(client.indexOf("|") > -1)
{
- var idx = domain.indexOf("|");
- domainname = domain.substr(0, idx);
- domainip = domain.substr(idx+1, domain.length-idx);
+ var idx = client.indexOf("|");
+ clientname = client.substr(0, idx);
+ clientip = client.substr(idx+1, client.length-idx);
}
else
{
- domainname = domain;
- domainip = domain;
+ clientname = client;
+ clientip = client;
}
- var url = ""+domainname+"";
- percentage = data.top_sources[domain] / data.dns_queries_today * 100;
+ var url = ""+clientname+"";
+ percentage = data.top_sources[client] / data.dns_queries_today * 100;
clienttable.append("
" + url +
- "
" + data.top_sources[domain] + "
" + data.top_sources[client] + "
");
}
}
- $("#client-frequency .overlay").remove();
- });
-}
-
-function updateForwardDestinations() {
- $.getJSON("api.php?getForwardDestinations", function(data) {
- var colors = [];
- // Get colors from AdminLTE
- $.each($.AdminLTE.options.colors, function(key, value) { colors.push(value); });
- var v = [], c = [];
- // Collect values and colors, immediately push individual labels
- $.each(data, function(key , value) {
- v.push(value);
- c.push(colors.shift());
- if(key.indexOf("|") > -1)
- {
- var idx = key.indexOf("|");
- key = key.substr(0, idx)+" ("+key.substr(idx+1, key.length-idx)+")";
- }
- forwardDestinationChart.data.labels.push(key);
- });
- // Build a single dataset with the data to be pushed
- var dd = {data: v, backgroundColor: c};
- // and push it at once
- forwardDestinationChart.data.datasets.push(dd);
- $("#forward-destinations .overlay").remove();
- forwardDestinationChart.update();
- forwardDestinationChart.chart.config.options.cutoutPercentage=30;
- forwardDestinationChart.update();
+ $("#client-frequency .overlay").hide();
+ // Update top clients list data every ten seconds
+ setTimeout(updateTopClientsChart, 10000);
});
}
function updateTopLists() {
$.getJSON("api.php?summaryRaw&topItems", function(data) {
+
+ if("FTLnotrunning" in data)
+ {
+ return;
+ }
+
+ // Clear tables before filling them with data
+ $("#domain-frequency td").parent().remove();
+ $("#ad-frequency td").parent().remove();
var domaintable = $("#domain-frequency").find("tbody:last");
var adtable = $("#ad-frequency").find("tbody:last");
var url, domain, percentage;
@@ -206,17 +306,10 @@ function updateTopLists() {
if ({}.hasOwnProperty.call(data.top_queries,domain)){
// Sanitize domain
domain = escapeHtml(domain);
- if(domain !== "pi.hole")
- {
- url = ""+domain+"";
- }
- else
- {
- url = domain;
- }
+ url = ""+domain+"";
percentage = data.top_queries[domain] / data.dns_queries_today * 100;
domaintable.append("
@@ -378,56 +391,55 @@ function convertseconds($argument) {
-
Specifying the MAC address is mandatory and only one entry per MAC address is allowed. If the IP address is omitted and a host name is given, the IP address will still be generated dynamically and the specified host name will be used. If the host name is omitted, only a static release will be added.
+
Specifying the MAC address is mandatory and only one entry per MAC address is allowed. If the IP address is omitted and a host name is given, the IP address will still be generated dynamically and the specified host name will be used. If the host name is omitted, only a static lease will be added.
-
-
+
+
+
IPv4
+
IPv6
+
Name
+
$value) { ?>
-
-
-
-
+
+
+
">" value="true" checked >
+
+
">" value="true" checked >
+
+
">" value="true" checked disabled >
+
+
">" value="true" checked disabled >
+
+
+
+
@@ -545,7 +570,7 @@ function convertseconds($argument) {
-
Note that enabling these two options may increase your privacy slightly, but may also prevent you from being able to access local hostnames if the Pi-Hole is not used as DHCP server
+
Note that enabling these two options may increase your privacy slightly, but may also prevent you from being able to access local hostnames if the Pi-hole is not used as DHCP server
@@ -571,6 +596,7 @@ function convertseconds($argument) {
@@ -612,6 +638,7 @@ function convertseconds($argument) {
@@ -808,15 +844,45 @@ function convertseconds($argument) {
+
+
+
+
+
+
+
Pi-hole FTL (RunningNot running)
+
+
+
+ FTL version:
+ Process identifier (PID):
+ Time FTL started:
+ User / Group: /
+ Total CPU utilization: %
+ Memory utilization: %
+ Used memory:
+
+
+
Pi-hole Teleporter
@@ -825,6 +891,7 @@ function convertseconds($argument) {
+
Export your Pi-hole lists as downloadable ZIP file
@@ -854,7 +921,7 @@ function convertseconds($argument) {
-
The PHP extension zip is not loaded. Please ensure it is installed and loaded if you want to use the Pi-hole teleporter.
+
The PHP extension zip is not loaded. Please ensure it is installed and loaded if you want to use the Pi-hole teleporter.