From 595ab259ca671d7f32bd1cedd6679da7ada729e4 Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Wed, 3 Jan 2018 20:16:50 -0500 Subject: [PATCH] Remove HTTP API specific code so it can be replaced with a new protocol Adjusted tests to fit the current lack of output on the unix socket. Added TELNET enum and used it in place of the old SOCKET to better fit with the rest of the code base. Signed-off-by: Mcat12 --- FTL.h | 4 +- Makefile | 4 +- api.c | 175 ----------------------- api.h | 33 ++--- api_dns.c | 40 +++--- api_stats.c | 346 ++++++++++++++++++++++----------------------- main.c | 9 -- request.c | 156 +------------------- routines.h | 5 +- socket.c | 192 ++----------------------- structs.c | 10 -- test/run.sh | 2 +- test/test_suite.sh | 68 ++------- 13 files changed, 228 insertions(+), 816 deletions(-) diff --git a/FTL.h b/FTL.h index beb327a4..348e012d 100644 --- a/FTL.h +++ b/FTL.h @@ -203,8 +203,8 @@ typedef struct { int querytypedata; } memoryStruct; -enum { QUERIES, FORWARDED, CLIENTS, DOMAINS, OVERTIME, WILDCARD, AUTHDATA }; -enum { SOCKET, API, APIH }; +enum { QUERIES, FORWARDED, CLIENTS, DOMAINS, OVERTIME, WILDCARD }; +enum { TELNET, SOCKET }; enum { WHITELIST, BLACKLIST, WILDLIST }; enum { DNSSEC_UNSPECIFIED, DNSSEC_SECURE, DNSSEC_INSECURE, DNSSEC_BOGUS, DNSSEC_ABANDONED, DNSSEC_UNKNOWN }; diff --git a/Makefile b/Makefile index 801fbf0c..efbb725f 100644 --- a/Makefile +++ b/Makefile @@ -8,8 +8,8 @@ # This file is copyright under the latest version of the EUPL. # Please see LICENSE file for your rights under this license. -DEPS = FTL.h routines.h api.h version.h cJSON.h -OBJ = main.o structs.o log.o daemon.o parser.o signals.o socket.o request.o grep.o setupVars.o args.o flush.o threads.o gc.o config.o database.o api.o api_stats.o api_dns.o cJSON.o +DEPS = FTL.h routines.h api.h version.h +OBJ = main.o structs.o log.o daemon.o parser.o signals.o socket.o request.o grep.o setupVars.o args.o flush.o threads.o gc.o config.o database.o api.o api_stats.o api_dns.o # Get git commit version and date GIT_BRANCH := $(shell git branch | sed -n 's/^\* //p') diff --git a/api.c b/api.c index f9bd4cc0..a14b1a53 100644 --- a/api.c +++ b/api.c @@ -10,181 +10,6 @@ #include "FTL.h" #include "api.h" -#include "cJSON.h" - -void sendAPIResponse(int sock, char type, char http_code) { - sendAPIResponseWithCookie(sock, type, http_code, NULL); -} - -void sendAPIResponseWithCookie(int sock, char type, char http_code, const long *session) { - char *http_status; - - switch(http_code) { - default: - case OK: - http_status = "200 OK"; - break; - case BAD_REQUEST: - http_status = "400 Bad Request"; - break; - case INTERNAL_ERROR: - http_status = "500 Internal Server Error"; - break; - case NOT_FOUND: - http_status = "404 Not Found"; - break; - case UNAUTHORIZED: - http_status = "401 Unauthorized"; - break; - } - - // Send header only for full HTTP requests - if(type == APIH) - { - if(session == NULL) { - // No cookie to send - ssend(sock, - "HTTP/1.0 %s\nServer: FTL\nCache-Control: no-cache\nAccess-Control-Allow-Origin: *\n" - "Content-Type: application/json\n\n{", http_status); - } - else { - // Send cookie - ssend(sock, - "HTTP/1.0 %s\nServer: FTL\nCache-Control: no-cache\nAccess-Control-Allow-Origin: *\n" - "Set-Cookie: FTL_SESSION=%ld\nContent-Type: application/json\n\n{", http_status, *session); - } - } -} - -// session will have the client's valid session written to, if it's not unauthorized -enum Auth authenticate(char *with_headers, char *payload, long *session, int sock) { - // First figure out if the client has authenticated before. - char *sessionStr; - AuthData *auth = NULL; - - // Find the cookie header (will contain a long int value) - if(strstr(with_headers, "Cookie: ") != NULL && (sessionStr = strstr(with_headers, "FTL_SESSION=")) != NULL) { - // Find the start of the cookie (strtol will stop once it gets to a non-numeric character) - sessionStr += 12; - - // Convert to int - *session = strtol(sessionStr, NULL, 10); - - if(errno == ERANGE) { - logg("Failed to decode the authentication cookie"); - return AUTH_UNAUTHORIZED; - } - - int i; - for(i = 0; i < authLength; i++) { - // Check if the authentication is still valid, has the same session token, and is coming from the same IP - if(authData[i].valid && authData[i].session == *session && strcmp(clientip[sock], authData[i].ip) == 0) { - auth = &authData[i]; - time_t currentTime = time(NULL); - - // Check to see if the session had expired (24 minutes) - if(currentTime > auth->lastQueryTime + 1440) { - authData[i].valid = false; - return AUTH_UNAUTHORIZED; - } - - auth->lastQueryTime = currentTime; - } - } - - // auth will be null if we didn't find a matching session - if(auth == NULL) - return AUTH_UNAUTHORIZED; - return AUTH_PREVIOUS; - } - - // Otherwise, check if they are trying to authenticate - cJSON *input_root = cJSON_Parse(payload); - cJSON *password_json = cJSON_GetObjectItemCaseSensitive(input_root, "password"); - - if(!cJSON_IsString(password_json)) { - cJSON_Delete(input_root); - return AUTH_UNAUTHORIZED; - } - - char *password = password_json->valuestring; - - // todo: use real password - if(strcmp(password, "password") == 0) { - auth = malloc(sizeof(AuthData)); - - auth->lastQueryTime = time(NULL); - auth->ip = strdup(clientip[sock]); - - // Find a unique session number - while(true) { - auth->session = random(); - - bool unique = true; - int i; - for(i = 0; i < authLength; i++) { - if(authData[i].session == auth->session) { - unique = false; - break; - } - } - - // Found a unique session number - if(unique) - break; - } - - auth->valid = true; - - // Add to auth storage - bool found = false; - int i; - for(i = 0; i < authLength; i++) { - if(!authData[i].valid) { - // Found an invalid auth we can reuse - found = true; - free(authData[i].ip); - authData[i] = *auth; - break; - } - } - - if(!found) { - // Couldn't reuse any existing auth structures - memory_check(AUTHDATA); - authData[authLength] = *auth; - authLength++; - } - - *session = auth->session; - free(auth); - cJSON_Delete(input_root); - - return AUTH_NEW; - } - - cJSON_Delete(input_root); - - return AUTH_UNAUTHORIZED; -} - -char* getPayload(char *http_message) { - char *data_start; - char *unix_newline = strstr(http_message, "\n\n"); - char *win_newline = strstr(http_message, "\r\n\r\n"); - - if(unix_newline != NULL) - data_start = unix_newline + 2; - else if(win_newline != NULL) - data_start = win_newline + 4; - else - return NULL; - - if(strlen(data_start) == 0) - return NULL; - - return data_start; -} bool matchesRegex(char *regex_expression, char *input) { regex_t regex; diff --git a/api.h b/api.h index 7dc4b709..3266a2ed 100644 --- a/api.h +++ b/api.h @@ -8,50 +8,33 @@ * This file is copyright under the latest version of the EUPL. * Please see LICENSE file for your rights under this license. */ -// Endpoints under /stats/ +// Statistic methods void getStats(int *sock, char type); void getOverTime(int *sock, char type); void getTopDomains (char *client_message, int *sock, char type); void getTopClients(char *client_message, int *sock, char type); void getForwardDestinations(char *client_message, int *sock, char type); - void getQueryTypes(int *sock, char type); void getAllQueries(char *client_message, int *sock, char type); void getRecentBlocked(char *client_message, int *sock, char type); -void getMemoryUsage(int *sock, char type); void getForwardDestinationsOverTime(int *sock, char type); -void getClientID(int *sock, char type); void getQueryTypesOverTime(int *sock, char type); -void getVersion(int *sock, char type); -void getDBstats(int *sock, char type); void getClientsOverTime(int *sock); void getClientNames(int *sock); + +// FTL methods +void getMemoryUsage(int *sock, char type); +void getClientID(int *sock, char type); +void getVersion(int *sock, char type); +void getDBstats(int *sock, char type); void getUnknownQueries(int *sock); -// Endpoints under /dns/ +// DNS methods void getList(int *sock, char type, char list_type); void addList(int *sock, char type, char list_type, char *data); void removeList(int *sock, char type, char list_type, char *client_message); void getPiholeStatus(int *sock, char type); -// HTTP Response Codes -enum { OK, BAD_REQUEST, INTERNAL_ERROR, NOT_FOUND, UNAUTHORIZED }; - -// Authentication -typedef struct { - time_t lastQueryTime; - long session; - char *ip; - bool valid; -} AuthData; -AuthData *authData; -int authLength; -enum Auth { AUTH_UNAUTHORIZED, AUTH_PREVIOUS, AUTH_NEW }; - // General API commands -enum Auth authenticate(char *with_headers, char *payload, long *session, int sock); -char* getPayload(char *http_message); -void sendAPIResponse(int sock, char type, char http_code); -void sendAPIResponseWithCookie(int sock, char type, char http_code, const long *session); bool matchesRegex(char *regex_expression, char *input); bool isValidDomain(char *domain); diff --git a/api_dns.c b/api_dns.c index f7e93f65..6189958e 100644 --- a/api_dns.c +++ b/api_dns.c @@ -32,7 +32,7 @@ void getList(int *sock, char type, char list_type) { name = "wildlist"; } - sendAPIResponse(*sock, type, OK); +// sendAPIResponse(*sock, type, OK); ssend(*sock, "\"%s\":[", name); if((fp = fopen(file, "r")) != NULL) @@ -111,28 +111,28 @@ void getList(int *sock, char type, char list_type) { void getPiholeStatus(int *sock, char type) { int status = countlineswith("#addn-hosts=/etc/pihole/gravity.list", files.dnsmasqconf); - sendAPIResponse(*sock, type, OK); +// sendAPIResponse(*sock, type, OK); ssend(*sock, "\"status\":%i", status == 1 ? 0 : 1); } void addList(int *sock, char type, char list_type, char *data) { - cJSON *input_root = cJSON_Parse(data); - cJSON *domain_json = cJSON_GetObjectItemCaseSensitive(input_root, "domain"); +// cJSON *input_root = cJSON_Parse(data); +// cJSON *domain_json = cJSON_GetObjectItemCaseSensitive(input_root, "domain"); char *domain; // Validate domain - if(!cJSON_IsString(domain_json)) { - // No domain found - sendAPIResponse(*sock, type, BAD_REQUEST); - ssend(*sock, "\"status\":\"no_domain\""); - return; - } +// if(!cJSON_IsString(domain_json)) { +// // No domain found +// sendAPIResponse(*sock, type, BAD_REQUEST); +// ssend(*sock, "\"status\":\"no_domain\""); +// return; +// } - domain = domain_json->valuestring; +// domain = domain_json->valuestring; if(!isValidDomain(domain)) { // Invalid domain - sendAPIResponse(*sock, type, BAD_REQUEST); +// sendAPIResponse(*sock, type, BAD_REQUEST); ssend(*sock, "\"status\":\"invalid_domain\""); return; } @@ -160,16 +160,16 @@ void addList(int *sock, char type, char list_type, char *data) { if(return_code == 0) { // Successfully added to list - sendAPIResponse(*sock, type, OK); +// sendAPIResponse(*sock, type, OK); ssend(*sock, "\"status\":\"success\""); } else { // Failed to add to list - sendAPIResponse(*sock, type, INTERNAL_ERROR); +// sendAPIResponse(*sock, type, INTERNAL_ERROR); ssend(*sock, "\"status\":\"unknown_error\""); } - cJSON_Delete(input_root); +// cJSON_Delete(input_root); } void removeList(int *sock, char type, char list_type, char *client_message) { @@ -178,7 +178,7 @@ void removeList(int *sock, char type, char list_type, char *client_message) { // Validate domain if(domain == NULL) { // No domain found - sendAPIResponse(*sock, type, NOT_FOUND); +// sendAPIResponse(*sock, type, NOT_FOUND); ssend(*sock, "\"status\":\"not_found\""); return; } @@ -208,7 +208,7 @@ void removeList(int *sock, char type, char list_type, char *client_message) { if(!strstr(client_message, expected_route)) { // Invalid route free(expected_route); - sendAPIResponse(*sock, type, NOT_FOUND); +// sendAPIResponse(*sock, type, NOT_FOUND); ssend(*sock, "\"status\":\"not_found\""); return; } @@ -217,7 +217,7 @@ void removeList(int *sock, char type, char list_type, char *client_message) { if(!isValidDomain(domain)) { // Invalid domain - sendAPIResponse(*sock, type, BAD_REQUEST); +// sendAPIResponse(*sock, type, BAD_REQUEST); ssend(*sock, "\"status\":\"invalid_domain\""); return; } @@ -241,12 +241,12 @@ void removeList(int *sock, char type, char list_type, char *client_message) { if(return_code == 0) { // Successfully removed from list - sendAPIResponse(*sock, type, OK); +// sendAPIResponse(*sock, type, OK); ssend(*sock, "\"status\":\"success\""); } else { // Failed to remove from list - sendAPIResponse(*sock, type, INTERNAL_ERROR); +// sendAPIResponse(*sock, type, INTERNAL_ERROR); ssend(*sock, "\"status\":\"unknown_error\""); } } diff --git a/api_stats.c b/api_stats.c index ccc2c34f..497785ea 100644 --- a/api_stats.c +++ b/api_stats.c @@ -59,7 +59,7 @@ void getStats(int *sock, char type) switch(blockingstatus) { case 0: // Blocking disabled - if(type == SOCKET) + if(type == TELNET) strncpy(domains_blocked, "N/A", 4); else strncpy(domains_blocked, "\"N/A\"", 6); @@ -85,7 +85,7 @@ void getStats(int *sock, char type) activeclients++; } - if(type == SOCKET) { + if(type == TELNET) { ssend(*sock, "domains_being_blocked %s\ndns_queries_today %i\nads_blocked_today %i\nads_percentage_today %f\n", domains_blocked, total, blocked, percentage); ssend(*sock, "unique_domains %i\nqueries_forwarded %i\nqueries_cached %i\n", @@ -96,30 +96,30 @@ void getStats(int *sock, char type) } else { - sendAPIResponse(*sock, type, OK); - ssend( - *sock, - "\"domains_being_blocked\":%s," - "\"dns_queries_today\":%i," - "\"ads_blocked_today\":%i," - "\"ads_percentage_today\":%.4f," - "\"unique_domains\":%i," - "\"queries_forwarded\":%i," - "\"queries_cached\":%i," - "\"clients_ever_seen\":%i," - "\"unique_clients\":%i," - "\"status\":\"%s\"", - domains_blocked, - total, - blocked, - percentage, - counters.domains, - counters.forwardedqueries, - counters.cached, - counters.clients, - activeclients, - status - ); +// sendAPIResponse(*sock, type, OK); +// ssend( +// *sock, +// "\"domains_being_blocked\":%s," +// "\"dns_queries_today\":%i," +// "\"ads_blocked_today\":%i," +// "\"ads_percentage_today\":%.4f," +// "\"unique_domains\":%i," +// "\"queries_forwarded\":%i," +// "\"queries_cached\":%i," +// "\"clients_ever_seen\":%i," +// "\"unique_clients\":%i," +// "\"status\":\"%s\"", +// domains_blocked, +// total, +// blocked, +// percentage, +// counters.domains, +// counters.forwardedqueries, +// counters.cached, +// counters.clients, +// activeclients, +// status +// ); } if(debugclients) @@ -142,7 +142,7 @@ void getOverTime(int *sock, char type) } // Send data in socket format if requested - if(type == SOCKET) + if(type == TELNET) { for(i = j; i < counters.overTime; i++) { @@ -151,25 +151,25 @@ void getOverTime(int *sock, char type) } else { - // First send header with unspecified content-length outside of the for-loop - sendAPIResponse(*sock, type, OK); - ssend(*sock,"\"domains_over_time\":{"); - - // Send "domains_over_time" data - for(i = j; i < counters.overTime; i++) - { - if(i != j) ssend(*sock, ","); - ssend(*sock,"\"%i\":%i",overTime[i].timestamp,overTime[i].total); - } - ssend(*sock,"},\"ads_over_time\":{"); - - // Send "ads_over_time" data - for(i = j; i < counters.overTime; i++) - { - if(i != j) ssend(*sock, ","); - ssend(*sock,"\"%i\":%i",overTime[i].timestamp,overTime[i].blocked); - } - ssend(*sock,"}"); +// // First send header with unspecified content-length outside of the for-loop +// sendAPIResponse(*sock, type, OK); +// ssend(*sock,"\"domains_over_time\":{"); +// +// // Send "domains_over_time" data +// for(i = j; i < counters.overTime; i++) +// { +// if(i != j) ssend(*sock, ","); +// ssend(*sock,"\"%i\":%i",overTime[i].timestamp,overTime[i].total); +// } +// ssend(*sock,"},\"ads_over_time\":{"); +// +// // Send "ads_over_time" data +// for(i = j; i < counters.overTime; i++) +// { +// if(i != j) ssend(*sock, ","); +// ssend(*sock,"\"%i\":%i",overTime[i].timestamp,overTime[i].blocked); +// } +// ssend(*sock,"}"); } if(debugclients) @@ -181,7 +181,7 @@ void getTopDomains(char *client_message, int *sock, char type) int i, temparray[counters.domains][2], count=10, num; bool blocked, audit = false, desc = false; - if(type == SOCKET) + if(type == TELNET) blocked = command(client_message, ">top-ads"); else blocked = command(client_message, "/top_ads"); @@ -191,9 +191,9 @@ void getTopDomains(char *client_message, int *sock, char type) return; // Match both top-domains and top-ads - // SOCKET: >top-domains (15) + // TELNET: >top-domains (15) // API: /stats/top_domains?limit=15 - if(type == SOCKET) + if(type == TELNET) { if(sscanf(client_message, "%*[^(](%i)", &num) > 0) { @@ -215,19 +215,19 @@ void getTopDomains(char *client_message, int *sock, char type) } // Apply Audit Log filtering? - // SOCKET: >top-domains for audit + // TELNET: >top-domains for audit // API: /stats/top_domains?audit - if(type == SOCKET && command(client_message, " for audit")) + if(type == TELNET && command(client_message, " for audit")) audit = true; - else if(type != SOCKET && command(client_message, "audit")) + else if(type != TELNET && command(client_message, "audit")) audit = true; // Sort in descending order? - // SOCKET: >top-domains desc + // TELNET: >top-domains desc // API: /stats/top_domains?order=desc - if(type == SOCKET && command(client_message, " desc")) + if(type == TELNET && command(client_message, " desc")) desc = true; - else if(type != SOCKET && command(client_message, "order=desc")) + else if(type != TELNET && command(client_message, "order=desc")) desc = true; for(i=0; i < counters.domains; i++) @@ -279,15 +279,15 @@ void getTopDomains(char *client_message, int *sock, char type) } } - if(type != SOCKET) + if(type != TELNET) { - // First send header with unspecified content-length outside of the for-loop - sendAPIResponse(*sock, type, OK); - - if(blocked) - ssend(*sock, "\"top_ads\":{"); - else - ssend(*sock, "\"top_domains\":{"); +// // First send header with unspecified content-length outside of the for-loop +// sendAPIResponse(*sock, type, OK); +// +// if(blocked) +// ssend(*sock, "\"top_ads\":{"); +// else +// ssend(*sock, "\"top_domains\":{"); } int skip = 0; bool first = true; @@ -316,7 +316,7 @@ void getTopDomains(char *client_message, int *sock, char type) if(blocked && showblocked && domains[j].blockedcount > 0) { - if(type == SOCKET) + if(type == TELNET) { if(audit && domains[j].wildcard) ssend(*sock,"%i %i %s wildcard\n",i,domains[j].blockedcount,domains[j].domain); @@ -325,32 +325,32 @@ void getTopDomains(char *client_message, int *sock, char type) } else { - if(!first) ssend(*sock,","); - first = false; - ssend(*sock,"\"%s\":%i", domains[j].domain, domains[j].blockedcount); +// if(!first) ssend(*sock,","); +// first = false; +// ssend(*sock,"\"%s\":%i", domains[j].domain, domains[j].blockedcount); } } else if(!blocked && showpermitted && (domains[j].count - domains[j].blockedcount) > 0) { - if(type == SOCKET) + if(type == TELNET) { ssend(*sock,"%i %i %s\n",i,(domains[j].count - domains[j].blockedcount),domains[j].domain); } else { - if(!first) ssend(*sock,","); - first = false; - ssend(*sock,"\"%s\":%i", domains[j].domain, (domains[j].count - domains[j].blockedcount)); +// if(!first) ssend(*sock,","); +// first = false; +// ssend(*sock,"\"%s\":%i", domains[j].domain, (domains[j].count - domains[j].blockedcount)); } } } - if(type != SOCKET) + if(type != TELNET) { - if(blocked) - ssend(*sock,"},\"ads_blocked_today\":%i", counters.blocked); - else - ssend(*sock,"},\"dns_queries_today\":%i", (counters.queries - counters.invalidqueries)); +// if(blocked) +// ssend(*sock,"},\"ads_blocked_today\":%i", counters.blocked); +// else +// ssend(*sock,"},\"dns_queries_today\":%i", (counters.queries - counters.invalidqueries)); } if(excludedomains != NULL) @@ -370,9 +370,9 @@ void getTopClients(char *client_message, int *sock, char type) int i, temparray[counters.clients][2], count=10, num; // Match both top-domains and top-ads - // SOCKET: >top-clients (15) + // TELNET: >top-clients (15) // API: /stats/top_clients?limit=15 - if(type == SOCKET) + if(type == TELNET) { if(sscanf(client_message, "%*[^(](%i)", &num) > 0) { @@ -397,7 +397,7 @@ void getTopClients(char *client_message, int *sock, char type) // This option can be combined with existing options, // i.e. both >top-clients withzero" and ">top-clients withzero (123)" are valid bool includezeroclients = false; - if(type == SOCKET) { + if(type == TELNET) { if(command(client_message, " withzero")) { includezeroclients = true; } @@ -425,11 +425,11 @@ void getTopClients(char *client_message, int *sock, char type) logg("Excluding %i clients from being displayed", setupVarsElements); } - if(type != SOCKET) + if(type != TELNET) { - // First send header with unspecified content-length outside of the for-loop - sendAPIResponse(*sock, type, OK); - ssend(*sock, "\"top_clients\":{"); +// // First send header with unspecified content-length outside of the for-loop +// sendAPIResponse(*sock, type, OK); +// ssend(*sock, "\"top_clients\":{"); } int skip = 0; bool first = true; @@ -454,24 +454,24 @@ void getTopClients(char *client_message, int *sock, char type) // - "withzero" option is set, and/or // - the client made at least one query within the most recent 24 hours if(includezeroclients || clients[j].count > 0) { - if(type == SOCKET) + if(type == TELNET) { ssend(*sock,"%i %i %s %s\n",i,clients[j].count,clients[j].ip,clients[j].name); } else { - if(!first) ssend(*sock,","); - first = false; - if(strlen(clients[j].name) > 0) - ssend(*sock,"\"%s|%s\":%i", clients[j].name, clients[j].ip, clients[j].count); - else - ssend(*sock,"\"%s\":%i", clients[j].ip, clients[j].count); +// if(!first) ssend(*sock,","); +// first = false; +// if(strlen(clients[j].name) > 0) +// ssend(*sock,"\"%s|%s\":%i", clients[j].name, clients[j].ip, clients[j].count); +// else +// ssend(*sock,"\"%s\":%i", clients[j].ip, clients[j].count); } } } - if(type != SOCKET) - ssend(*sock,"},\"dns_queries_today\":%i", (counters.queries - counters.invalidqueries)); +// if(type != TELNET) +// ssend(*sock,"},\"dns_queries_today\":%i", (counters.queries - counters.invalidqueries)); if(excludeclients != NULL) clearSetupVarsArray(); @@ -486,7 +486,7 @@ void getForwardDestinations(char *client_message, int *sock, char type) bool allocated = false, first = true, sort = true; int i, temparray[counters.forwarded+1][2], forwardedsum = 0, totalqueries = 0; - if(type == SOCKET && command(client_message, "unsorted")) + if(type == TELNET && command(client_message, "unsorted")) sort = false; else if(strstr(client_message, "unsorted")) sort = false; @@ -516,11 +516,11 @@ void getForwardDestinations(char *client_message, int *sock, char type) totalqueries = counters.forwardedqueries + counters.cached + counters.blocked; // Send HTTP headers with unknown content length - sendAPIResponse(*sock, type, OK); +// sendAPIResponse(*sock, type, OK); // Send initial JSON output - if(type != SOCKET) - ssend(*sock, "\"forward_destinations\":{"); +// if(type != TELNET) +// ssend(*sock, "\"forward_destinations\":{"); // Loop over available forward destinations for(i=0; i < min(counters.forwarded+1, 10); i++) @@ -584,19 +584,19 @@ void getForwardDestinations(char *client_message, int *sock, char type) // Send data if count > 0 if(percentage > 0.0) { - if(type == SOCKET) + if(type == TELNET) { ssend(*sock, "%i %.2f %s %s\n", i, percentage, ip, name); } else { - if(!first) ssend(*sock, ","); - first = false; - - if(strlen(name) > 0) - ssend(*sock, "\"%s|%s\":%.2f", name, ip, percentage); - else - ssend(*sock, "\"%s\":%.2f", ip, percentage); +// if(!first) ssend(*sock, ","); +// first = false; +// +// if(strlen(name) > 0) +// ssend(*sock, "\"%s|%s\":%.2f", name, ip, percentage); +// else +// ssend(*sock, "\"%s\":%.2f", ip, percentage); } } @@ -608,8 +608,8 @@ void getForwardDestinations(char *client_message, int *sock, char type) } } - if(type != SOCKET) - ssend(*sock, "}"); +// if(type != TELNET) +// ssend(*sock, "}"); if(debugclients) logg("Sent forward destination data to client, ID: %i", *sock); @@ -627,11 +627,11 @@ void getQueryTypes(int *sock, char type) percentageIPv6 = 1e2*counters.IPv6/total; } - if(type == SOCKET) + if(type == TELNET) ssend(*sock,"A (IPv4): %.2f\nAAAA (IPv6): %.2f\n", percentageIPv4, percentageIPv6); else { - sendAPIResponse(*sock, type, OK); - ssend(*sock, "\"query_types\":{\"A (IPv4)\":%.2f,\"AAAA (IPv6)\":%.2f}", percentageIPv4, percentageIPv6); +// sendAPIResponse(*sock, type, OK); +// ssend(*sock, "\"query_types\":{\"A (IPv4)\":%.2f,\"AAAA (IPv6)\":%.2f}", percentageIPv4, percentageIPv6); } if(debugclients) @@ -655,7 +655,7 @@ void getAllQueries(char *client_message, int *sock, char type) char *clientname = NULL; bool filterclientname = false; - if(type == SOCKET) + if(type == TELNET) { // Time filtering? if(command(client_message, ">getallqueries-time")) @@ -724,7 +724,7 @@ void getAllQueries(char *client_message, int *sock, char type) int ibeg = 0, num; // Test for integer that specifies number of entries to be shown - if(type == SOCKET) + if(type == TELNET) { if(sscanf(client_message, "%*[^(](%i)", &num) > 0) { @@ -794,11 +794,11 @@ void getAllQueries(char *client_message, int *sock, char type) logg("Privacy mode enabled"); } - if(type != SOCKET) - { - sendAPIResponse(*sock, type, OK); - ssend(*sock, "\"history\":["); - } +// if(type != TELNET) +// { +// sendAPIResponse(*sock, type, OK); +// ssend(*sock, "\"history\":["); +// } int i; bool first = true; for(i=ibeg; i < counters.queries; i++) @@ -840,7 +840,7 @@ void getAllQueries(char *client_message, int *sock, char type) continue; } - if(type == SOCKET) + if(type == TELNET) { if(!privacymode) { @@ -854,24 +854,24 @@ void getAllQueries(char *client_message, int *sock, char type) } else { - // {"data":[["1497351662","IPv4","clients4.google.com","10.8.0.2",2,1], - if(!first) ssend(*sock, ","); - first = false; - - if(!privacymode) - { - if(strlen(clients[queries[i].clientID].name) > 0) - ssend(*sock,"[%i,\"%s\",\"%s\",\"%s\",%i,%i]",queries[i].timestamp,qtype,domains[queries[i].domainID].domain,clients[queries[i].clientID].name,queries[i].status,domains[queries[i].domainID].dnssec); - else - ssend(*sock,"[%i,\"%s\",\"%s\",\"%s\",%i,%i]",queries[i].timestamp,qtype,domains[queries[i].domainID].domain,clients[queries[i].clientID].ip,queries[i].status,domains[queries[i].domainID].dnssec); - } - else - ssend(*sock,"[%i,\"%s\",\"%s\",\"hidden\",%i,%i]",queries[i].timestamp,qtype,domains[queries[i].domainID].domain,queries[i].status,domains[queries[i].domainID].dnssec); +// // {"data":[["1497351662","IPv4","clients4.google.com","10.8.0.2",2,1], +// if(!first) ssend(*sock, ","); +// first = false; +// +// if(!privacymode) +// { +// if(strlen(clients[queries[i].clientID].name) > 0) +// ssend(*sock,"[%i,\"%s\",\"%s\",\"%s\",%i,%i]",queries[i].timestamp,qtype,domains[queries[i].domainID].domain,clients[queries[i].clientID].name,queries[i].status,domains[queries[i].domainID].dnssec); +// else +// ssend(*sock,"[%i,\"%s\",\"%s\",\"%s\",%i,%i]",queries[i].timestamp,qtype,domains[queries[i].domainID].domain,clients[queries[i].clientID].ip,queries[i].status,domains[queries[i].domainID].dnssec); +// } +// else +// ssend(*sock,"[%i,\"%s\",\"%s\",\"hidden\",%i,%i]",queries[i].timestamp,qtype,domains[queries[i].domainID].domain,queries[i].status,domains[queries[i].domainID].dnssec); } } - if(type != SOCKET) - ssend(*sock, "]"); +// if(type != TELNET) +// ssend(*sock, "]"); // Free allocated memory if(filterclientname) @@ -893,7 +893,7 @@ void getRecentBlocked(char *client_message, int *sock, char type) return; // Test for integer that specifies number of entries to be shown - if(type == SOCKET) + if(type == TELNET) { if(sscanf(client_message, "%*[^(](%i)", &num) > 0) { @@ -916,11 +916,11 @@ void getRecentBlocked(char *client_message, int *sock, char type) } } - if(type != SOCKET) - { - sendAPIResponse(*sock, type, OK); - ssend(*sock, "\"recent_blocked\":["); - } +// if(type != TELNET) +// { +// sendAPIResponse(*sock, type, OK); +// ssend(*sock, "\"recent_blocked\":["); +// } // Find most recent query with either status 1 (blocked) // or status 4 (wildcard blocked) @@ -934,15 +934,15 @@ void getRecentBlocked(char *client_message, int *sock, char type) if(queries[i].status == 1 || queries[i].status == 4) { found++; - if(type == SOCKET) + if(type == TELNET) { ssend(*sock,"%s\n", domains[queries[i].domainID].domain); } else { - if(!first) ssend(*sock, ","); - first = false; - ssend(*sock, "\"%s\"", domains[queries[i].domainID].domain); +// if(!first) ssend(*sock, ","); +// first = false; +// ssend(*sock, "\"%s\"", domains[queries[i].domainID].domain); } } @@ -950,11 +950,11 @@ void getRecentBlocked(char *client_message, int *sock, char type) break; } - if(type != SOCKET) - ssend(*sock, "]"); +// if(type != TELNET) +// ssend(*sock, "]"); } -// only available via SOCKET +// only available via TELNET void getMemoryUsage(int *sock, char type) { unsigned long int structbytes = sizeof(countersStruct) + sizeof(ConfigStruct) + counters.queries_MAX*sizeof(queriesDataStruct) + counters.forwarded_MAX*sizeof(forwardedDataStruct) + counters.clients_MAX*sizeof(clientsDataStruct) + counters.domains_MAX*sizeof(domainsDataStruct) + counters.overTime_MAX*sizeof(overTimeDataStruct) + (counters.wildcarddomains)*sizeof(*wildcarddomains); @@ -994,11 +994,11 @@ void getForwardDestinationsOverTime(int *sock, char type) } } - if(type != SOCKET) - { - sendAPIResponse(*sock, type, OK); - ssend(*sock,"\"over_time\":{"); - } +// if(type != TELNET) +// { +// sendAPIResponse(*sock, type, OK); +// ssend(*sock,"\"over_time\":{"); +// } if(sendit > -1) { @@ -1008,15 +1008,15 @@ void getForwardDestinationsOverTime(int *sock, char type) double percentage; validate_access("overTime", i, true, __LINE__, __FUNCTION__, __FILE__); - if(type == SOCKET) + if(type == TELNET) { ssend(*sock, "%i", overTime[i].timestamp); } else { - if(!first) ssend(*sock, ","); - first = false; - ssend(*sock, "\"%i\":[", overTime[i].timestamp); +// if(!first) ssend(*sock, ","); +// first = false; +// ssend(*sock, "\"%i\":[", overTime[i].timestamp); } int j, forwardedsum = 0; @@ -1067,7 +1067,7 @@ void getForwardDestinationsOverTime(int *sock, char type) else percentage = 0.0; - if(type == SOCKET) + if(type == TELNET) ssend(*sock, " %.2f", percentage); else ssend(*sock, "%.2f,", percentage); @@ -1080,19 +1080,19 @@ void getForwardDestinationsOverTime(int *sock, char type) else percentage = 0.0; - if(type == SOCKET) + if(type == TELNET) ssend(*sock, " %.2f\n", percentage); else ssend(*sock, "%.2f]", percentage); } } - if(type != SOCKET) - { - ssend(*sock,"},"); - // Manually set API -> Don't send header a second time - getForwardDestinations(">forward-dest unsorted", sock, API); - } +// if(type != TELNET) +// { +// ssend(*sock,"},"); +// // Manually set API -> Don't send header a second time +// getForwardDestinations(">forward-dest unsorted", sock, SOCKET); +// } if(debugclients) logg("Sent overTime forwarded data to client, ID: %i", *sock); @@ -1120,11 +1120,11 @@ void getQueryTypesOverTime(int *sock, char type) } } - if(type != SOCKET) - { - sendAPIResponse(*sock, type, OK); - ssend(*sock,"\"query_types\":{"); - } +// if(type != TELNET) +// { +// sendAPIResponse(*sock, type, OK); +// ssend(*sock,"\"query_types\":{"); +// } if(sendit > -1) { @@ -1141,18 +1141,18 @@ void getQueryTypesOverTime(int *sock, char type) percentageIPv6 = 1e2*overTime[i].querytypedata[1] / sum; } - if(type == SOCKET) + if(type == TELNET) ssend(*sock, "%i %.2f %.2f\n", overTime[i].timestamp, percentageIPv4, percentageIPv6); else { - if(!first) ssend(*sock, ","); - first = false; - ssend(*sock, "\"%i\":[%.2f,%.2f]", overTime[i].timestamp, percentageIPv4, percentageIPv6); +// if(!first) ssend(*sock, ","); +// first = false; +// ssend(*sock, "\"%i\":[%.2f,%.2f]", overTime[i].timestamp, percentageIPv4, percentageIPv6); } } } - if(type != SOCKET) - ssend(*sock,"}"); +// if(type != TELNET) +// ssend(*sock,"}"); if(debugclients) logg("Sent overTime query types data to client, ID: %i", *sock); diff --git a/main.c b/main.c index 70c92f36..39922238 100644 --- a/main.c +++ b/main.c @@ -89,14 +89,6 @@ int main (int argc, char* argv[]) { } sleepms(100); - // Start API thread - pthread_t api_listenthread; - if(pthread_create( &api_listenthread, &attr, api_listening_thread, NULL ) != 0) - { - logg("Unable to open API listening thread. Exiting..."); - killed = 1; - } - while(!killed) { sleepms(100); @@ -176,7 +168,6 @@ int main (int argc, char* argv[]) { pthread_cancel(socket_listenthread); close_telnet_socket(); close_unix_socket(); - close_api_socket(); removepid(); logg("########## FTL terminated! ##########"); return 1; diff --git a/request.c b/request.c index 959d066c..1f7d1e27 100644 --- a/request.c +++ b/request.c @@ -11,13 +11,12 @@ #include "FTL.h" #include "api.h" -void process_socket_request(char *client_message, int *sock) +void process_request(char *client_message, int *sock, char type) { char EOT[2]; EOT[0] = 0x04; EOT[1] = 0x00; bool processed = false; - char type = SOCKET; if(command(client_message, ">stats")) { @@ -149,159 +148,6 @@ void process_socket_request(char *client_message, int *sock) } } -void process_api_request(char *client_message, char *full_message, int *sock, bool header) -{ - char type; - if(header) - type = APIH; - else - type = API; - - char *data = getPayload(full_message); - long session; - - char authResult = authenticate(full_message, data, &session, *sock); - if(authResult == AUTH_UNAUTHORIZED && !matchesEndpoint(client_message, "GET /stats/summary") - && !matchesEndpoint(client_message, "GET /stats/overTime/graph") - && !matchesEndpoint(client_message, "GET /dns/status")) { - sendAPIResponse(*sock, type, UNAUTHORIZED); - ssend(*sock, "\"status\":\"unauthorized\"}"); - return; - } - - if(authResult == AUTH_NEW) { - sendAPIResponseWithCookie(*sock, type, OK, &session); - ssend(*sock, "\"status\":\"authorized\",\"session\":%ld}", session); - return; - } - - if(matchesEndpoint(client_message, "GET /stats/summary")) - { - getStats(sock, type); - } - else if(matchesEndpoint(client_message, "GET /stats/overTime/graph")) - { - getOverTime(sock, type); - } - else if(matchesEndpoint(client_message, "GET /stats/top_domains") || matchesEndpoint(client_message, "GET /stats/top_ads")) - { - getTopDomains(client_message, sock, type); - } - else if(matchesEndpoint(client_message, "GET /stats/top_clients")) - { - getTopClients(client_message, sock, type); - } - else if(matchesEndpoint(client_message, "GET /stats/forward_dest") || matchesEndpoint(client_message, "GET /stats/forward_destinations")) - { - getForwardDestinations(client_message, sock, type); - } - else if(matchesEndpoint(client_message, "GET /stats/dashboard")) - { - getStats(sock, type); - type = API; - ssend(*sock, ","); - getOverTime(sock, type); - ssend(*sock, ","); - getTopDomains(client_message, sock, type); - ssend(*sock, ","); - getTopClients(client_message, sock, type); - ssend(*sock, ","); - getForwardDestinations(client_message, sock, type); - } - else if(matchesEndpoint(client_message, "GET /stats/query_types")) - { - getQueryTypes(sock, type); - } - else if(matchesEndpoint(client_message, "GET /stats/history")) - { - getAllQueries(client_message, sock, type); - } - else if(matchesEndpoint(client_message, "GET /stats/recent_blocked")) - { - getRecentBlocked(client_message, sock, type); - } - else if(matchesEndpoint(client_message, "GET /stats/overTime/forward_dest")) - { - getForwardDestinationsOverTime(sock, type); - } - else if(matchesEndpoint(client_message, "GET /stats/overTime/query_types")) - { - getQueryTypesOverTime(sock, type); - } - else if(matchesEndpoint(client_message, "GET /dns/whitelist")) - { - getList(sock, type, WHITELIST); - } - else if(matchesEndpoint(client_message, "POST /dns/whitelist")) - { - addList(sock, type, WHITELIST, data); - } - else if(matchesRegex("DELETE \\/dns\\/whitelist\\/[^\\/]*$", client_message)) - { - removeList(sock, type, WHITELIST, client_message); - } - else if(matchesEndpoint(client_message, "GET /dns/blacklist")) - { - getList(sock, type, BLACKLIST); - } - else if(matchesEndpoint(client_message, "POST /dns/blacklist")) - { - addList(sock, type, BLACKLIST, data); - } - else if(matchesRegex("DELETE \\/dns\\/blacklist\\/[^\\/]*$", client_message)) - { - removeList(sock, type, BLACKLIST, client_message); - } - else if(matchesEndpoint(client_message, "GET /dns/wildlist")) - { - getList(sock, type, WILDLIST); - } - else if(matchesEndpoint(client_message, "POST /dns/wildlist")) - { - addList(sock, type, WILDLIST, data); - } - else if(matchesRegex("DELETE \\/dns\\/wildlist\\/[^\\/]*$", client_message)) - { - removeList(sock, type, WILDLIST, client_message); - } - else if(matchesEndpoint(client_message, "GET /dns/status")) - { - getPiholeStatus(sock, type); - } - else if(header) - { - sendAPIResponse(*sock, type, NOT_FOUND); - ssend(*sock, "\"status\":\"not_found\""); - } - - ssend(*sock, "}"); -} - bool command(char *client_message, const char* cmd) { return strstr(client_message, cmd) != NULL; } - -bool matchesEndpoint(char *client_message, const char *cmd) { - char *get_params_start = strstr(client_message, "?"); - bool result; - - // Check if there are GET parameters to ignore - if(get_params_start != NULL) { - char without_get_params[256]; - - // Check to make sure we don't overflow the buffer - if(strlen(cmd)+1 > sizeof(without_get_params) / sizeof(char)) - return false; - - size_t msg_len = get_params_start - client_message; - - strncpy(without_get_params, client_message, msg_len); - without_get_params[msg_len] = 0; - - result = strcmp(without_get_params, cmd) == 0; - } - else - result = strcmp(client_message, cmd) == 0; - - return result; -} diff --git a/routines.h b/routines.h index 88b53940..44db3760 100644 --- a/routines.h +++ b/routines.h @@ -40,15 +40,12 @@ void memory_check(int which); void close_telnet_socket(void); void close_unix_socket(void); -void close_api_socket(void); void seom(int sock); void ssend(int sock, const char *format, ...); void *telnet_listening_thread(void *args); void *socket_listening_thread(void *args); -void *api_listening_thread(void *args); -void process_socket_request(char *client_message, int *sock); -void process_api_request(char *client_message, char *full_message, int *sock, bool header); +void process_request(char *client_message, int *sock, char type); bool command(char *client_message, const char* cmd); bool matchesEndpoint(char *client_message, const char *cmd); diff --git a/socket.c b/socket.c index bea63b8d..a119efae 100644 --- a/socket.c +++ b/socket.c @@ -21,7 +21,7 @@ #define BACKLOG 5 // File descriptors -int telnetfd, socketfd, apifd; +int telnetfd, socketfd; void saveport(int port) { @@ -62,7 +62,7 @@ void bind_to_telnet_port(char type, int *socketdescriptor) memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; - if(config.socket_listenlocal && type == SOCKET) + if(config.socket_listenlocal) serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); else serv_addr.sin_addr.s_addr = INADDR_ANY; @@ -77,12 +77,9 @@ void bind_to_telnet_port(char type, int *socketdescriptor) switch(type) { - case SOCKET: + case TELNET: port_init = 4711; break; - case API: - port_init = 4747; - break; default: logg("Incompatible socket type %i", (int)type); exit(EXIT_FAILURE); @@ -110,7 +107,7 @@ void bind_to_telnet_port(char type, int *socketdescriptor) exit(EXIT_FAILURE); } - if(type == SOCKET) + if(type == TELNET) saveport(port); // The listen system call allows the process to listen on the socket for connections @@ -119,18 +116,8 @@ void bind_to_telnet_port(char type, int *socketdescriptor) logg("Error on listening"); exit(EXIT_FAILURE); } - switch(type) - { - case SOCKET: - logg("Listening on port %i for incoming socket connections", port); - break; - case API: - logg("Listening on port %i for incoming API connections", port); - break; - default: - /* That cannot happen */ - break; - } + + logg("Listening on port %i for incoming telnet connections", port); } @@ -243,11 +230,6 @@ void close_unix_socket(void) close(socketfd); } -void close_api_socket(void) -{ - close(apifd); -} - void *telnet_connection_handler_thread(void *socket_desc) { //Get the socket descriptor @@ -276,7 +258,7 @@ void *telnet_connection_handler_thread(void *socket_desc) // Requests should not be processed/answered when data is about to change enable_thread_lock(threadname); - process_socket_request(message, &sock); + process_request(message, &sock, TELNET); free(message); // Release thread lock @@ -334,7 +316,7 @@ void *socket_connection_handler_thread(void *socket_desc) // Requests should not be processed/answered when data is about to change enable_thread_lock(threadname); - process_socket_request(message, &sock); + process_request(message, &sock, SOCKET); free(message); // Release thread lock @@ -381,7 +363,7 @@ void *telnet_listening_thread(void *args) prctl(PR_SET_NAME,"telnet listener",0,0,0); // Initialize sockets only after initial log parsing in listenting_thread - bind_to_telnet_port(SOCKET, &telnetfd); + bind_to_telnet_port(TELNET, &telnetfd); // Listen as long as FTL is not killed while(!killed) @@ -443,159 +425,3 @@ void *socket_listening_thread(void *args) } return 0; } - - -void *api_connection_handler_thread(void *socket_desc) -{ - //Get the socket descriptor - int sock = *(int*)socket_desc; - // Store copy only for displaying the debug messages - int sockID = sock; - char client_message[SOCKETBUFFERLEN] = ""; - - // Set thread name - char threadname[16]; - sprintf(threadname,"api-%i",sockID); - prctl(PR_SET_NAME,threadname,0,0,0); - - //Receive from client - if(recv(sock, client_message, SOCKETBUFFERLEN-1, 0) > 0) - { - char *message = calloc(strlen(client_message)+1,sizeof(char)); - strcpy(message, client_message); - - // Clear client message receive buffer - memset(client_message, 0, sizeof client_message); - - if(debug) - logg("Received API request: \n%s", message); - - if(strncmp(message, "GET ", 4) == 0 || strncmp(message, "POST ", 5) == 0 || strncmp(message, "DELETE ", 7) == 0) - { - // HTTP requests can be simple or full. - // A simple request contains one line only, and looks like this: - // GET /index.html - // A full request can contain more than one line and may look like this: - // GET /index.html HTTP/1.1 - // User-Agent: Wget/1.16 (linux-gnueabihf) - // Accept: */* - // Host: 127.0.0.1:4747 - // Connection: Keep-Alive - bool header = false; - - // Extract requested URL including arguments - const char *p2; - if(strstr(message, "HTTP/") != NULL) - { - // Output HTTP response headers only if we have a full request - header = true; - // End of request = "HTTP/" - p2 = strstr(message, " HTTP/"); - } - else - { - // End of requst = end of first line - p2 = strstr(message, "\n"); - } - if(p2 != NULL) - { - size_t len = p2 - message; - char *request = calloc(len+1, sizeof(char)); - strncpy(request, message, len); - request[len] = '\0'; - - // Are we asked for a favicon? - if(strstr(request, "/favicon.ico") != NULL) - ssend(sock, "HTTP/1.0 404 Not Found\nServer: FTL\n\n"); - else - { - enable_thread_lock(threadname); - process_api_request(request, message, &sock, header); - disable_thread_lock(threadname); - } - - // Free allocated memory - free(request); - } - else - { - logg("API received malformated request: \"%s\"", message); - } - } - else if(strncmp(message, "OPTIONS ", 8) == 0) - { - // OPTIONS request: CORS preflight - ssend(sock, "HTTP/1.0 200 OK\nServer: FTL\nAccess-Control-Allow-Origin: *\n" - "Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS\n" - "Access-Control-Allow-Headers: Content-Type\n\n"); - } - else if(strncmp(message, "HEAD ", 5) == 0) - { - // HEAD request: We do not send any content at all - ssend(sock, "HTTP/1.0 200 OK\nServer: FTL\n\n"); - } - else - { - if(debug) - logg("API received something strange"); - } - - // Close connection to show that we reached the end of the transmission - close(sock); - sock = 0; - - // Free allocated memory - free(message); - } - - //Free the socket pointer - if(sock != 0) - close(sock); - free(socket_desc); - - if(clientip[sock] != NULL) { - free(clientip[sock]); - clientip[sock] = NULL; - } - - return 0; -} - -void *api_listening_thread(void *args) -{ - int *newsock; - // We will use the attributes object later to start all threads in detached mode - pthread_attr_t attr; - // Initialize thread attributes object with default attribute values - pthread_attr_init(&attr); - // When a detached thread terminates, its resources are automatically released back to - // the system without the need for another thread to join with the terminated thread - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - // Set thread name - prctl(PR_SET_NAME,"API listener",0,0,0); - - // Initialize sockets only after initial log parsing in listening_thread - bind_to_telnet_port(API, &apifd); - - // Listen as long as FTL is not killed - while(!killed) - { - // Look for new clients that want to connect - int csck = listener(apifd); - if(csck < 0) continue; - - // Allocate memory used to transport client socket ID to client listening thread - newsock = calloc(1,sizeof(int)); - *newsock = csck; - - pthread_t api_connection_thread; - // Create a new thread - if(pthread_create( &api_connection_thread, &attr, api_connection_handler_thread, (void*) newsock ) != 0) - { - // Log the error code description - logg("WARNING: Unable to open client API thread, error: %s", strerror(errno)); - } - } - return 0; -} diff --git a/structs.c b/structs.c index f01237e0..7524b058 100644 --- a/structs.c +++ b/structs.c @@ -9,7 +9,6 @@ * Please see LICENSE file for your rights under this license. */ #include "FTL.h" -#include "api.h" FTLFileNamesStruct FTLfiles = { "/etc/pihole/pihole-FTL.conf", @@ -120,15 +119,6 @@ void memory_check(int which) exit(EXIT_FAILURE); } break; - case AUTHDATA: - // Always called when we need one more entry, like wildcard - logg_struct_resize("authdata", authLength+1, 1); - authData = realloc(authData, (authLength+1) * sizeof(AuthData)); - - if(authData == NULL) { - logg("FATAL: Memory allocation failed! Exiting"); - exit(EXIT_FAILURE); - } default: /* That cannot happen */ break; diff --git a/test/run.sh b/test/run.sh index 5aaf2508..e03fc3f0 100755 --- a/test/run.sh +++ b/test/run.sh @@ -60,7 +60,7 @@ git submodule add https://github.com/ztombol/bats-support test/libs/bats-support # Block until FTL is ready, retry once per second for 45 seconds n=0 until [ $n -ge 45 ]; do - (nc -vv -z -w 30 127.0.0.1 4711 && nc -vv -z -w 30 127.0.0.1 4747) && break + nc -vv -z -w 30 127.0.0.1 4711 && break n=$[$n+1] echo "..." tail -n2 pihole-FTL.log diff --git a/test/test_suite.sh b/test/test_suite.sh index 3d033e83..cbf410db 100644 --- a/test/test_suite.sh +++ b/test/test_suite.sh @@ -183,52 +183,6 @@ load 'libs/bats-support/load' [[ "${lines[@]}" == *"INSERT INTO \"ftl\" VALUES(0,1);"* ]] } -@test "HTTP server: FTL responding correctly to HEAD request" { - run bash -c "curl --head -s 127.0.0.1:4747" - echo "output: ${lines[@]}" - echo "curl exit code: ${status}" - [[ ${lines[0]} == "HTTP/1.0 200 OK" ]] - [[ ${lines[1]} == "Server: FTL" ]] - [[ ${lines[2]} == "" ]] - [[ "${status}" -eq 0 ]] -} - -@test "HTTP server: FTL responding correctly to GET request" { - run bash -c "curl -s 127.0.0.1:4747" - echo "output: ${lines[@]}" - echo "curl exit code: ${status}" - [[ "${status}" -eq 0 ]] -} - -@test "API: Correct answer to summary request (including header check)" { - run bash -c "curl -si 127.0.0.1:4747/stats/summary" - echo "output: ${lines[@]}" - echo "curl exit code: ${status}" - [[ ${lines[0]} == "HTTP/1.0 200 OK" ]] - [[ ${lines[1]} == "Server: FTL" ]] - [[ ${lines[2]} == "Cache-Control: no-cache" ]] - [[ ${lines[3]} == "Access-Control-Allow-Origin: *" ]] - [[ ${lines[4]} == "Content-Type: application/json" ]] - [[ ${lines[5]} == "{\"domains_being_blocked\":-1,\"dns_queries_today\":7,\"ads_blocked_today\":2,\"ads_percentage_today\":28.5714,\"unique_domains\":6,\"queries_forwarded\":3,\"queries_cached\":2,\"clients_ever_seen\":3,\"unique_clients\":3,\"status\":\"unknown\"}" ]] - [[ "${status}" -eq 0 ]] -} - -#@test "API: Correct answer to top_domains request" { -# run bash -c "curl -s 127.0.0.1:4747/stats/top_domains" -# echo "output: ${lines[@]}" -# echo "curl exit code: ${status}" -# [[ ${lines[0]} == "{\"top_domains\":{\"play.google.com\":2,\"example.com\":1,\"checkip.dyndns.org\":1,\"raspberrypi\":1},\"dns_queries_today\":7}" ]] -# [[ "${status}" -eq 0 ]] -#} - -#@test "API: Correct answer to top_ads request" { -# run bash -c "curl -s 127.0.0.1:4747/stats/top_ads" -# echo "output: ${lines[@]}" -# echo "curl exit code: ${status}" -# [[ ${lines[0]} == "{\"top_ads\":{\"addomain.com\":1,\"blacklisted.com\":1},\"ads_blocked_today\":2}" ]] -# [[ "${status}" -eq 0 ]] -#} - @test "Arguments check: Invalid option" { run bash -c './pihole-FTL abc' echo "output: ${lines[@]}" @@ -247,17 +201,17 @@ load 'libs/bats-support/load' echo "output: ${lines[@]}" [[ ${lines[0]} == "Socket created" ]] [[ ${lines[1]} == "Connection established" ]] - [[ ${lines[2]} == "domains_being_blocked -1" ]] - [[ ${lines[3]} == "dns_queries_today 7" ]] - [[ ${lines[4]} == "ads_blocked_today 2" ]] - [[ ${lines[5]} == "ads_percentage_today 28.571428" ]] - [[ ${lines[6]} == "unique_domains 6" ]] - [[ ${lines[7]} == "queries_forwarded 3" ]] - [[ ${lines[8]} == "queries_cached 2" ]] - [[ ${lines[9]} == "clients_ever_seen 3" ]] - [[ ${lines[10]} == "unique_clients 3" ]] - [[ ${lines[11]} == "status unknown" ]] - [[ ${lines[12]} == "---EOM---" ]] +# [[ ${lines[2]} == "domains_being_blocked -1" ]] +# [[ ${lines[3]} == "dns_queries_today 7" ]] +# [[ ${lines[4]} == "ads_blocked_today 2" ]] +# [[ ${lines[5]} == "ads_percentage_today 28.571428" ]] +# [[ ${lines[6]} == "unique_domains 6" ]] +# [[ ${lines[7]} == "queries_forwarded 3" ]] +# [[ ${lines[8]} == "queries_cached 2" ]] +# [[ ${lines[9]} == "clients_ever_seen 3" ]] +# [[ ${lines[10]} == "unique_clients 3" ]] +# [[ ${lines[11]} == "status unknown" ]] + [[ ${lines[2]} == "---EOM---" ]] } @test "Final part of the tests: Killing pihole-FTL process" {