Skip to content

Commit

Permalink
Use really bound-to IP addresses in CHAOS TXT local.api.ftl
Browse files Browse the repository at this point in the history
Signed-off-by: DL6ER <[email protected]>
  • Loading branch information
DL6ER committed Feb 22, 2025
1 parent 2dc36c0 commit 7dab630
Showing 1 changed file with 41 additions and 21 deletions.
62 changes: 41 additions & 21 deletions src/webserver/webserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,9 @@ static struct serverports
bool is_secure :1;
bool is_redirect :1;
bool is_optional :1;
unsigned char protocol; // 1 = IPv4, 2 = IPv4+IPv6, 3 = IPv6
in_port_t port;
char addr[INET6_ADDRSTRLEN + 2]; // +2 for square brackets around IPv6 address
int port;
int protocol; // 1 = IPv4, 3 = IPv6
} server_ports[MAXPORTS] = { 0 };
static in_port_t https_port = 0;
/**
Expand Down Expand Up @@ -252,20 +253,37 @@ static void get_server_ports(void)
server_ports[i].is_secure = mgports[i].is_ssl;
server_ports[i].is_redirect = mgports[i].is_redirect;
server_ports[i].is_optional = mgports[i].is_optional;
// 1 = IPv4, 3 = IPv6 (can also be a combo-socker serving both),
// the documentation in civetweb.h is wrong
server_ports[i].protocol = mgports[i].protocol;

// Convert listening address to string
if(server_ports[i].protocol == 1)
inet_ntop(AF_INET, &mgports[i].addr.sa4.sin_addr, server_ports[i].addr, INET_ADDRSTRLEN);
else if(server_ports[i].protocol == 3)
{
char tmp[INET6_ADDRSTRLEN] = { 0 };
inet_ntop(AF_INET6, &mgports[i].addr.sa6.sin6_addr, tmp, INET6_ADDRSTRLEN);
// Enclose IPv6 address in square brackets
snprintf(server_ports[i].addr, sizeof(server_ports[i].addr), "[%s]", tmp);
}
else
log_warn("Unsupported protocol for port %d", mgports[i].port);

// Store (first) HTTPS port if not already set
if(mgports[i].is_ssl && https_port == 0)
https_port = mgports[i].port;

// Print port information
if(i == 0)
log_info("Web server ports:");
log_info(" - %d (HTTP%s, IPv%s%s%s)",
mgports[i].port, mgports[i].is_ssl ? "S" : "",
mgports[i].protocol == 1 ? "4" : (mgports[i].protocol == 3 ? "6" : "4+6"),
mgports[i].is_redirect ? ", redirecting" : "",
mgports[i].is_optional ? ", optional" : "");
log_info(" - %s:%d (HTTP%s, IPv%s%s%s)",
server_ports[i].addr,
server_ports[i].port,
server_ports[i].is_secure ? "S" : "",
server_ports[i].protocol == 1 ? "4" : "6",
server_ports[i].is_redirect ? ", redirecting" : "",
server_ports[i].is_optional ? ", optional" : "");

}
}
Expand All @@ -275,21 +293,13 @@ in_port_t __attribute__((pure)) get_https_port(void)
return https_port;
}

#define MAX_URL_LEN 255
unsigned short get_api_string(char **buf, const bool domain)
{
// Initialize buffer to empty string
size_t len = 0;
// First byte has the length of the first string
**buf = 0;
const char *domain_str = domain ? config.webserver.domain.v.s : "pi.hole";
size_t api_str_size = strlen(domain_str) + 20;

// Check if the string is too long for the TXT record
if(api_str_size > 255)
{
log_err("API URL too long for TXT record!");
return 0;
}

// TXT record format:
//
Expand All @@ -311,20 +321,30 @@ unsigned short get_api_string(char **buf, const bool domain)
continue;

// Reallocate additional memory for every port
if((*buf = realloc(*buf, (i+1)*api_str_size)) == NULL)
const size_t bufsz = (i + 1) * MAX_URL_LEN;
if((*buf = realloc(*buf, bufsz)) == NULL)
{
log_err("Failed to reallocate API URL buffer!");
return 0;
}
const size_t bufsz = (i+1)*api_str_size;

// Use appropriate domain
const char *addr = domain ? config.webserver.domain.v.s : server_ports[i].addr;

// If we bound to the wildcard address, substitute it with
// 127.0.0.1
if(strcmp(addr, "0.0.0.0") == 0)
addr = "127.0.0.1";
else if(strcasecmp(addr, "[::]") == 0)
addr = "[::1]";

// Append API URL to buffer
// We add this at buffer + 1 because the first byte is the
// length of the string, which we don't know yet
char *api_str = calloc(api_str_size, sizeof(char));
const ssize_t this_len = snprintf(api_str, bufsz - len - 1, "http%s://%s:%d/api/",
char *api_str = calloc(MAX_URL_LEN, sizeof(char));
const ssize_t this_len = snprintf(api_str, MAX_URL_LEN, "http%s://%s:%d/api/",
server_ports[i].is_secure ? "s" : "",
domain_str, server_ports[i].port);
addr, server_ports[i].port);
// Check if snprintf() failed
if(this_len < 0)
{
Expand Down

0 comments on commit 7dab630

Please sign in to comment.