Simplify EDNS handling code and also interpret replies received from upstream
Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
parent
6a1de9fdc0
commit
37de8662ea
|
@ -783,7 +783,8 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
|
|||
a.log.rcode = rcode;
|
||||
a.log.ede = ede;
|
||||
log_query(F_UPSTREAM | F_RCODE, "error", &a, NULL, 0);
|
||||
|
||||
FTL_parse_pseudoheaders(pheader, (size_t)plen);
|
||||
|
||||
return resize_packet(header, n, pheader, plen);
|
||||
}
|
||||
|
||||
|
@ -1750,9 +1751,8 @@ void receive_query(struct listener *listen, time_t now)
|
|||
have_mark = get_incoming_mark(&source_addr, &dst_addr, /* istcp: */ 0, &mark);
|
||||
#endif
|
||||
//********************** Pi-hole modification **********************//
|
||||
ednsData edns = { 0 };
|
||||
if (find_pseudoheader(header, (size_t)n, NULL, &pheader, NULL, NULL))
|
||||
FTL_parse_pseudoheaders(header, n, &source_addr, &edns);
|
||||
if ((pheader = find_pseudoheader(header, (size_t)n, NULL, &pheader, NULL, NULL)))
|
||||
FTL_parse_pseudoheaders(pheader, (size_t)n);
|
||||
//******************************************************************//
|
||||
|
||||
if (extract_request(header, (size_t)n, daemon->namebuff, &type))
|
||||
|
@ -1763,7 +1763,7 @@ void receive_query(struct listener *listen, time_t now)
|
|||
log_query_mysockaddr(F_QUERY | F_FORWARD, daemon->namebuff,
|
||||
&source_addr, auth_dns ? "auth" : "query", type);
|
||||
piholeblocked = FTL_new_query(F_QUERY | F_FORWARD , daemon->namebuff,
|
||||
&source_addr, auth_dns ? "auth" : "query", type, daemon->log_display_id, &edns, UDP);
|
||||
&source_addr, auth_dns ? "auth" : "query", type, daemon->log_display_id, UDP);
|
||||
|
||||
#ifdef HAVE_CONNTRACK
|
||||
is_single_query = 1;
|
||||
|
@ -2298,9 +2298,9 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||
no_cache_dnssec = 1;
|
||||
|
||||
//********************** Pi-hole modification **********************//
|
||||
ednsData edns = { 0 };
|
||||
if (find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL, NULL))
|
||||
FTL_parse_pseudoheaders(header, size, &peer_addr, &edns);
|
||||
unsigned char *pheader = NULL;
|
||||
if ((pheader = find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL, NULL)))
|
||||
FTL_parse_pseudoheaders(pheader, (size_t)size);
|
||||
//******************************************************************//
|
||||
|
||||
if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
|
||||
|
@ -2320,7 +2320,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||
&peer_addr, auth_dns ? "auth" : "query", qtype);
|
||||
|
||||
piholeblocked = FTL_new_query(F_QUERY | F_FORWARD, daemon->namebuff,
|
||||
&peer_addr, auth_dns ? "auth" : "query", qtype, daemon->log_display_id, &edns, TCP);
|
||||
&peer_addr, auth_dns ? "auth" : "query", qtype, daemon->log_display_id, TCP);
|
||||
|
||||
#ifdef HAVE_AUTH
|
||||
/* find queries for zones we're authoritative for, and answer them directly */
|
||||
|
|
|
@ -128,8 +128,6 @@ void FTL_hook(unsigned int flags, const char *name, union all_addr *addr, char *
|
|||
if(!config.show_dnssec)
|
||||
return;
|
||||
|
||||
const ednsData edns = { 0 };
|
||||
|
||||
// Type is overloaded with port since 2d65d55, so we have to
|
||||
// derive the real query type from the arg string
|
||||
unsigned short qtype = type;
|
||||
|
@ -158,7 +156,7 @@ void FTL_hook(unsigned int flags, const char *name, union all_addr *addr, char *
|
|||
arg = (char*)"dnssec-unknown";
|
||||
}
|
||||
|
||||
_FTL_new_query(flags, name, NULL, arg, qtype, id, &edns, INTERNAL, file, line);
|
||||
_FTL_new_query(flags, name, NULL, arg, qtype, id, INTERNAL, file, line);
|
||||
// forwarded upstream (type is used to store the upstream port)
|
||||
FTL_forwarded(flags, name, addr, type, id, path, line);
|
||||
}
|
||||
|
@ -464,7 +462,7 @@ static bool is_pihole_domain(const char *domain)
|
|||
bool _FTL_new_query(const unsigned int flags, const char *name,
|
||||
union mysockaddr *addr, char *arg,
|
||||
const unsigned short qtype, const int id,
|
||||
const ednsData *edns, const enum protocol proto,
|
||||
const enum protocol proto,
|
||||
const char* file, const int line)
|
||||
{
|
||||
// Create new query in data structure
|
||||
|
@ -596,6 +594,7 @@ bool _FTL_new_query(const unsigned int flags, const char *name,
|
|||
in_port_t clientPort = daemon->port;
|
||||
bool internal_query = false;
|
||||
char clientIP[ADDRSTRLEN+1] = { 0 };
|
||||
ednsData *edns = getEDNS();
|
||||
if(config.edns0_ecs && edns && edns->client_set)
|
||||
{
|
||||
// Use ECS provided client
|
||||
|
@ -3345,7 +3344,7 @@ int check_struct_sizes(void)
|
|||
result += check_one_struct("clientsData", sizeof(clientsData), 672, 648);
|
||||
result += check_one_struct("domainsData", sizeof(domainsData), 24, 20);
|
||||
result += check_one_struct("DNSCacheData", sizeof(DNSCacheData), 16, 16);
|
||||
result += check_one_struct("ednsData", sizeof(ednsData), 72, 72);
|
||||
result += check_one_struct("ednsData", sizeof(ednsData), 76, 76);
|
||||
result += check_one_struct("overTimeData", sizeof(overTimeData), 32, 24);
|
||||
result += check_one_struct("regexData", sizeof(regexData), 64, 48);
|
||||
result += check_one_struct("SharedMemory", sizeof(SharedMemory), 24, 12);
|
||||
|
|
|
@ -23,8 +23,8 @@ void FTL_hook(unsigned int flags, const char *name, union all_addr *addr, char *
|
|||
#define FTL_iface(iface, addr, addrfamily) _FTL_iface(iface, addr, addrfamily, __FILE__, __LINE__)
|
||||
void _FTL_iface(struct irec *recviface, const union all_addr *addr, const sa_family_t addrfamily, const char* file, const int line);
|
||||
|
||||
#define FTL_new_query(flags, name, addr, arg, qtype, id, edns, proto) _FTL_new_query(flags, name, addr, arg, qtype, id, edns, proto, __FILE__, __LINE__)
|
||||
bool _FTL_new_query(const unsigned int flags, const char *name, union mysockaddr *addr, char *arg, const unsigned short qtype, const int id, const ednsData *edns, enum protocol proto, const char* file, const int line);
|
||||
#define FTL_new_query(flags, name, addr, arg, qtype, id, proto) _FTL_new_query(flags, name, addr, arg, qtype, id, proto, __FILE__, __LINE__)
|
||||
bool _FTL_new_query(const unsigned int flags, const char *name, union mysockaddr *addr, char *arg, const unsigned short qtype, const int id, enum protocol proto, const char* file, const int line);
|
||||
|
||||
#define FTL_header_analysis(header4, rcode, server, id) _FTL_header_analysis(header4, rcode, server, id, __FILE__, __LINE__)
|
||||
void _FTL_header_analysis(const unsigned char header4, const unsigned int rcode, const struct server *server, const int id, const char* file, const int line);
|
||||
|
|
69
src/edns0.c
69
src/edns0.c
|
@ -41,14 +41,26 @@
|
|||
// dnsmasq option: --add-cpe-id=...
|
||||
#define EDNS0_CPE_ID EDNS0_OPTION_NOMCPEID
|
||||
|
||||
void FTL_parse_pseudoheaders(struct dns_header *header, size_t n, union mysockaddr *peer, ednsData *edns)
|
||||
{
|
||||
int is_sign;
|
||||
size_t plen;
|
||||
unsigned char *pheader, *sizep;
|
||||
static ednsData edns = { 0 };
|
||||
|
||||
// Extract additional record A.K.A. pseudoheader
|
||||
if (!(pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign, NULL)))
|
||||
ednsData *getEDNS(void)
|
||||
{
|
||||
if(edns.valid)
|
||||
{
|
||||
// Return pointer to ednsData structure and reset it for the
|
||||
// next query
|
||||
edns.valid = false;
|
||||
return &edns;
|
||||
}
|
||||
|
||||
// No valid EDNS data available
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FTL_parse_pseudoheaders(unsigned char *pheader, const size_t plen)
|
||||
{
|
||||
// Return early if we have no pseudoheader (a.k.a. additional records)
|
||||
if (!pheader)
|
||||
return;
|
||||
|
||||
// Debug logging
|
||||
|
@ -152,6 +164,11 @@ void FTL_parse_pseudoheaders(struct dns_header *header, size_t n, union mysockad
|
|||
if(edns0_version != 0x00)
|
||||
return;
|
||||
|
||||
// Reset EDNS(0) data
|
||||
memset(&edns, 0, sizeof(ednsData));
|
||||
edns.ede = -1;
|
||||
edns.valid = true;
|
||||
|
||||
size_t offset; // The header is 11 bytes before the beginning of OPTION-DATA
|
||||
while ((offset = (p - pheader - 11u)) < rdlen && rdlen < UINT16_MAX)
|
||||
{
|
||||
|
@ -225,8 +242,8 @@ void FTL_parse_pseudoheaders(struct dns_header *header, size_t n, union mysockad
|
|||
}
|
||||
|
||||
// Copy data to edns struct
|
||||
strncpy(edns->client, ipaddr, ADDRSTRLEN);
|
||||
edns->client[ADDRSTRLEN-1] = '\0';
|
||||
strncpy(edns.client, ipaddr, ADDRSTRLEN);
|
||||
edns.client[ADDRSTRLEN-1] = '\0';
|
||||
|
||||
// Only set the address as useful when it is not the
|
||||
// loopback address of the distant machine (127.0.0.0/8 or ::1)
|
||||
|
@ -239,7 +256,7 @@ void FTL_parse_pseudoheaders(struct dns_header *header, size_t n, union mysockad
|
|||
}
|
||||
else
|
||||
{
|
||||
edns->client_set = true;
|
||||
edns.client_set = true;
|
||||
if(config.debug & DEBUG_EDNS0)
|
||||
logg("EDNS(0) CLIENT SUBNET: %s/%u - OK (IPv%u)",
|
||||
ipaddr, source_netmask, family == 1 ? 4 : 6);
|
||||
|
@ -292,11 +309,11 @@ void FTL_parse_pseudoheaders(struct dns_header *header, size_t n, union mysockad
|
|||
else if(code == EDNS0_MAC_ADDR_BYTE && optlen == 6)
|
||||
{
|
||||
// EDNS(0) MAC address (BYTE format)
|
||||
memcpy(edns->mac_byte, p, sizeof(edns->mac_byte));
|
||||
print_mac(edns->mac_text, (unsigned char*)edns->mac_byte, sizeof(edns->mac_byte));
|
||||
edns->mac_set = true;
|
||||
memcpy(edns.mac_byte, p, sizeof(edns.mac_byte));
|
||||
print_mac(edns.mac_text, (unsigned char*)edns.mac_byte, sizeof(edns.mac_byte));
|
||||
edns.mac_set = true;
|
||||
if(config.debug & DEBUG_EDNS0)
|
||||
logg("EDNS(0) MAC address (BYTE format): %s", edns->mac_text);
|
||||
logg("EDNS(0) MAC address (BYTE format): %s", edns.mac_text);
|
||||
|
||||
// Advance working pointer
|
||||
p += 6;
|
||||
|
@ -304,19 +321,19 @@ void FTL_parse_pseudoheaders(struct dns_header *header, size_t n, union mysockad
|
|||
else if(code == EDNS0_MAC_ADDR_TEXT && optlen == 17)
|
||||
{
|
||||
// EDNS(0) MAC address (TEXT format)
|
||||
memcpy(edns->mac_text, p, 17);
|
||||
edns->mac_text[17] = '\0';
|
||||
if(sscanf(edns->mac_text, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
|
||||
&edns->mac_byte[0],
|
||||
&edns->mac_byte[1],
|
||||
&edns->mac_byte[2],
|
||||
&edns->mac_byte[3],
|
||||
&edns->mac_byte[4],
|
||||
&edns->mac_byte[5]) == 6)
|
||||
memcpy(edns.mac_text, p, 17);
|
||||
edns.mac_text[17] = '\0';
|
||||
if(sscanf(edns.mac_text, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
|
||||
(unsigned char*)&edns.mac_byte[0],
|
||||
(unsigned char*)&edns.mac_byte[1],
|
||||
(unsigned char*)&edns.mac_byte[2],
|
||||
(unsigned char*)&edns.mac_byte[3],
|
||||
(unsigned char*)&edns.mac_byte[4],
|
||||
(unsigned char*)&edns.mac_byte[5]) == 6)
|
||||
{
|
||||
edns->mac_set = true;
|
||||
edns.mac_set = true;
|
||||
if(config.debug & DEBUG_EDNS0)
|
||||
logg("EDNS(0) MAC address (TEXT format): %s", edns->mac_text);
|
||||
logg("EDNS(0) MAC address (TEXT format): %s", edns.mac_text);
|
||||
}
|
||||
else if(config.debug & DEBUG_EDNS0)
|
||||
{
|
||||
|
@ -358,7 +375,7 @@ void FTL_parse_pseudoheaders(struct dns_header *header, size_t n, union mysockad
|
|||
else
|
||||
{
|
||||
if(config.debug & DEBUG_EDNS0)
|
||||
logg("EDNS(0):n option %u with length %u", code, optlen);
|
||||
logg("EDNS(0): option %u with length %u", code, optlen);
|
||||
// Not implemented, skip this record
|
||||
|
||||
// Advance working pointer
|
||||
|
|
|
@ -11,13 +11,16 @@
|
|||
#define EDNS0_HEADER
|
||||
|
||||
typedef struct {
|
||||
bool client_set;
|
||||
bool mac_set;
|
||||
bool client_set :1;
|
||||
bool mac_set :1;
|
||||
bool valid :1;
|
||||
char client[ADDRSTRLEN];
|
||||
char mac_byte[6];
|
||||
char mac_text[18];
|
||||
int ede;
|
||||
} ednsData;
|
||||
|
||||
void FTL_parse_pseudoheaders(struct dns_header *header, size_t n, union mysockaddr *peer, ednsData *edns);
|
||||
ednsData *getEDNS(void);
|
||||
void FTL_parse_pseudoheaders(unsigned char *pheader, const size_t plen);
|
||||
|
||||
#endif // EDNS0_HEADER
|
||||
|
|
Loading…
Reference in New Issue