Add FIFO buffer endpoint at /admin/api/ftl/dnsmasq_log. This is a FIFO buffer collecting and returning up to 32 messages from memory (compile-time option). The API endpoint can be continuously polled with the last returned ID to only show new messages that can be appended to a log on the web interface.
Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
parent
50e2736ef3
commit
e4c7cec349
|
@ -139,4 +139,7 @@ extern pthread_t timerthread;
|
|||
// Intentionally ignore result of function declared warn_unused_result
|
||||
#define igr(x) {__typeof__(x) __attribute__((unused)) d=(x);}
|
||||
|
||||
#define max(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a > _b ? _a : _b; })
|
||||
#define min(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; })
|
||||
|
||||
#endif // FTL_H
|
||||
|
|
|
@ -11,12 +11,15 @@
|
|||
#include "FTL.h"
|
||||
#include "http-common.h"
|
||||
#include "routes.h"
|
||||
#include "ftl.h"
|
||||
#include "json_macros.h"
|
||||
#include "datastructure.h"
|
||||
// get_FTL_version()
|
||||
#include "log.h"
|
||||
// git constants
|
||||
#include "version.h"
|
||||
// config struct
|
||||
#include "config.h"
|
||||
|
||||
int api_ftl_clientIP(struct mg_connection *conn)
|
||||
{
|
||||
|
@ -25,3 +28,95 @@ int api_ftl_clientIP(struct mg_connection *conn)
|
|||
JSON_OBJ_REF_STR(json,"remote_addr", request->remote_addr);
|
||||
JSON_SEND_OBJECT(json);
|
||||
}
|
||||
|
||||
static char dnsmasq_log_messages[LOG_SIZE][MAX_MESSAGE] = { 0 };
|
||||
static time_t dnsmasq_log_stamps[LOG_SIZE] = { 0 };
|
||||
static int dnsmasq_next_id = 0;
|
||||
|
||||
int api_ftl_dnsmasq_log(struct mg_connection *conn)
|
||||
{
|
||||
// Verify requesting client is allowed to see this ressource
|
||||
if(check_client_auth(conn) < 0)
|
||||
{
|
||||
return send_json_unauthorized(conn, NULL);
|
||||
}
|
||||
|
||||
unsigned int start = 0u;
|
||||
const struct mg_request_info *request = mg_get_request_info(conn);
|
||||
if(request->query_string != NULL)
|
||||
{
|
||||
// Does the user request an ID to sent from?
|
||||
int num;
|
||||
if((num = get_int_var(request->query_string, "nextID")) > 0)
|
||||
{
|
||||
if(num >= dnsmasq_next_id)
|
||||
{
|
||||
// Do not return any data
|
||||
start = LOG_SIZE;
|
||||
}
|
||||
else if(num < max(dnsmasq_next_id - LOG_SIZE, 0))
|
||||
{
|
||||
// Requested an ID smaller than the lowest one we have
|
||||
// We return the entire buffer
|
||||
start = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reply with partial buffer
|
||||
start = LOG_SIZE - (dnsmasq_next_id - num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process data
|
||||
cJSON *json = JSON_NEW_OBJ();
|
||||
cJSON *log = JSON_NEW_ARRAY();
|
||||
unsigned int idx = 0u;
|
||||
for(unsigned int i = start; i < LOG_SIZE; i++)
|
||||
{
|
||||
// Reconstruct log message identification number
|
||||
if(dnsmasq_next_id < LOG_SIZE)
|
||||
{
|
||||
idx = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx = dnsmasq_next_id - LOG_SIZE + i;
|
||||
}
|
||||
|
||||
cJSON *entry = JSON_NEW_OBJ();
|
||||
JSON_OBJ_ADD_NUMBER(entry, "id", idx);
|
||||
JSON_OBJ_ADD_NUMBER(entry, "timestamp", dnsmasq_log_stamps[i]);
|
||||
JSON_OBJ_REF_STR(entry, "message", dnsmasq_log_messages[i]);
|
||||
JSON_ARRAY_ADD_ITEM(log, entry);
|
||||
}
|
||||
JSON_OBJ_ADD_ITEM(json, "log", log);
|
||||
JSON_OBJ_ADD_NUMBER(json, "nextID", dnsmasq_next_id);
|
||||
JSON_SEND_OBJECT(json);
|
||||
}
|
||||
|
||||
void add_to_dnsmasq_log_fifo_buffer(const char *payload, const int length)
|
||||
{
|
||||
unsigned int idx = dnsmasq_next_id++;
|
||||
if(idx >= LOG_SIZE)
|
||||
{
|
||||
// Log is full, move everything one slot forward to make space
|
||||
memmove(dnsmasq_log_messages[0], dnsmasq_log_messages[1], (LOG_SIZE - 1u) * MAX_MESSAGE);
|
||||
idx = LOG_SIZE - 1u;
|
||||
}
|
||||
// Copy relevant string into temporary buffer
|
||||
memcpy(dnsmasq_log_messages[idx], payload, length);
|
||||
|
||||
// Zero-terminate buffer, truncate newline if found
|
||||
if(dnsmasq_log_messages[idx][length - 1u] == '\n')
|
||||
{
|
||||
dnsmasq_log_messages[idx][length - 1u] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
dnsmasq_log_messages[idx][length] = '\0';
|
||||
}
|
||||
|
||||
// Set timestamp
|
||||
dnsmasq_log_stamps[idx] = time(NULL);
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2019 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* FTL Engine
|
||||
* API FTL prototypes
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
#ifndef API_FTL_H
|
||||
#define API_FTL_H
|
||||
|
||||
/* From RFC 3164 */
|
||||
#define MAX_MESSAGE 1024
|
||||
|
||||
// How many messages do we keep in memory (FIFO message buffer)?
|
||||
// The memory required is the set number in kilobytes
|
||||
// Defaults to 32 [uses 32 KB of memory]
|
||||
#define LOG_SIZE 32
|
||||
|
||||
void add_to_dnsmasq_log_fifo_buffer(const char *payload, const int length);
|
||||
|
||||
#endif // API_FTL_H
|
|
@ -44,6 +44,10 @@ int api_handler(struct mg_connection *conn, void *ignored)
|
|||
{
|
||||
return api_ftl_clientIP(conn);
|
||||
}
|
||||
else if(startsWith("/api/ftl/dnsmasq_log", request->local_uri))
|
||||
{
|
||||
return api_ftl_dnsmasq_log(conn);
|
||||
}
|
||||
/******************************** api/stats **************************/
|
||||
else if(startsWith("/api/stats/summary", request->local_uri))
|
||||
{
|
||||
|
|
|
@ -29,8 +29,7 @@ int api_stats_recentblocked(struct mg_connection *conn);
|
|||
|
||||
// FTL methods
|
||||
int api_ftl_clientIP(struct mg_connection *conn);
|
||||
int api_ftl_version(struct mg_connection *conn);
|
||||
int api_ftl_db(struct mg_connection *conn);
|
||||
int api_ftl_dnsmasq_log(struct mg_connection *conn);
|
||||
|
||||
// DNS methods
|
||||
int api_dns_status(struct mg_connection *conn);
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
// enum REGEX
|
||||
#include "regex_r.h"
|
||||
|
||||
#define min(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; })
|
||||
|
||||
/* qsort comparision function (count field), sort ASC
|
||||
static int __attribute__((pure)) cmpasc(const void *a, const void *b)
|
||||
{
|
||||
|
|
|
@ -300,8 +300,8 @@ void my_syslog(int priority, const char *format, ...)
|
|||
#endif
|
||||
|
||||
/*************************** Pi-hole specific logging **************************/
|
||||
va_start(ap, format);
|
||||
char buffer[MAX_MESSAGE + 1u];
|
||||
va_start(ap, format);
|
||||
len = vsnprintf(buffer, MAX_MESSAGE, format, ap) + 1u; /* include zero-terminator */
|
||||
va_end(ap);
|
||||
FTL_dnsmasq_log(buffer, len > MAX_MESSAGE ? MAX_MESSAGE : len);
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#include "args.h"
|
||||
// http_init()
|
||||
#include "api/http-common.h"
|
||||
// add_to_dnsmasq_log_buffer()
|
||||
#include "api/ftl.h"
|
||||
|
||||
static void print_flags(const unsigned int flags);
|
||||
static void save_reply_type(const unsigned int flags, const union all_addr *addr,
|
||||
|
@ -1813,24 +1815,5 @@ void FTL_TCP_worker_terminating(void)
|
|||
|
||||
void FTL_dnsmasq_log(const char *payload, const int length)
|
||||
{
|
||||
// Get temporary space for dnsmasq's log message
|
||||
char log_str[length + 1u];
|
||||
|
||||
// Copy relevant string into temporary buffer
|
||||
memcpy(log_str, payload, length);
|
||||
|
||||
// Zero-terminate buffer, truncate newline if found
|
||||
if(log_str[length - 1u] == '\n')
|
||||
{
|
||||
log_str[length - 1u] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
log_str[length] = '\0';
|
||||
}
|
||||
|
||||
if(config.debug & DEBUG_API)
|
||||
{
|
||||
logg("DNSMASQ LOG: \"%s\"", log_str);
|
||||
}
|
||||
}
|
||||
add_to_dnsmasq_log_fifo_buffer(payload, length);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue