summaryrefslogtreecommitdiff
path: root/src/edns0.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/edns0.c')
-rw-r--r--src/edns0.c142
1 files changed, 84 insertions, 58 deletions
diff --git a/src/edns0.c b/src/edns0.c
index 7bd26b8..c498eb1 100644
--- a/src/edns0.c
+++ b/src/edns0.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -178,7 +178,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
memcpy(buff, datap, rdlen);
/* now, delete OPT RR */
- plen = rrfilter(header, plen, 0);
+ plen = rrfilter(header, plen, RRFILTER_EDNS0);
/* Now, force addition of a new one */
p = NULL;
@@ -264,44 +264,62 @@ static void encoder(unsigned char *in, char *out)
out[3] = char64(in[2]);
}
+/* OPT_ADD_MAC = MAC is added (if available)
+ OPT_ADD_MAC + OPT_STRIP_MAC = MAC is replaced, if not available, it is only removed
+ OPT_STRIP_MAC = MAC is removed */
static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned char *limit,
union mysockaddr *l3, time_t now, int *cacheablep)
{
- int maclen, replace = 2; /* can't get mac address, just delete any incoming. */
+ int replace = 0, maclen = 0;
unsigned char mac[DHCP_CHADDR_MAX];
- char encode[18]; /* handle 6 byte MACs */
+ char encode[18]; /* handle 6 byte MACs ONLY */
- if ((maclen = find_mac(l3, mac, 1, now)) == 6)
+ if ((option_bool(OPT_MAC_B64) || option_bool(OPT_MAC_HEX)) && (maclen = find_mac(l3, mac, 1, now)) == 6)
{
- replace = 1;
- *cacheablep = 0;
-
- if (option_bool(OPT_MAC_HEX))
- print_mac(encode, mac, maclen);
- else
- {
- encoder(mac, encode);
- encoder(mac+3, encode+4);
- encode[8] = 0;
- }
+ if (option_bool(OPT_STRIP_MAC))
+ replace = 1;
+ *cacheablep = 0;
+
+ if (option_bool(OPT_MAC_HEX))
+ print_mac(encode, mac, maclen);
+ else
+ {
+ encoder(mac, encode);
+ encoder(mac+3, encode+4);
+ encode[8] = 0;
+ }
}
+ else if (option_bool(OPT_STRIP_MAC))
+ replace = 2;
+
+ if (replace != 0 || maclen == 6)
+ plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMDEVICEID, (unsigned char *)encode, strlen(encode), 0, replace);
- return add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMDEVICEID, (unsigned char *)encode, strlen(encode), 0, replace);
+ return plen;
}
+/* OPT_ADD_MAC = MAC is added (if available)
+ OPT_ADD_MAC + OPT_STRIP_MAC = MAC is replaced, if not available, it is only removed
+ OPT_STRIP_MAC = MAC is removed */
static size_t add_mac(struct dns_header *header, size_t plen, unsigned char *limit,
union mysockaddr *l3, time_t now, int *cacheablep)
{
- int maclen;
+ int maclen = 0, replace = 0;
unsigned char mac[DHCP_CHADDR_MAX];
-
- if ((maclen = find_mac(l3, mac, 1, now)) != 0)
+
+ if (option_bool(OPT_ADD_MAC) && (maclen = find_mac(l3, mac, 1, now)) != 0)
{
*cacheablep = 0;
- plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac, maclen, 0, 0);
+ if (option_bool(OPT_STRIP_MAC))
+ replace = 1;
}
+ else if (option_bool(OPT_STRIP_MAC))
+ replace = 2;
+ if (replace != 0 || maclen != 0)
+ plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac, maclen, 0, replace);
+
return plen;
}
@@ -378,15 +396,29 @@ static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source,
return len + 4;
}
-static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *source, int *cacheable)
+/* OPT_CLIENT_SUBNET = client subnet is added
+ OPT_CLIENT_SUBNET + OPT_STRIP_ECS = client subnet is replaced
+ OPT_STRIP_ECS = client subnet is removed */
+static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned char *limit,
+ union mysockaddr *source, int *cacheable)
{
/* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
- int len;
+ int replace = 0, len = 0;
struct subnet_opt opt;
- len = calc_subnet_opt(&opt, source, cacheable);
- return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, 0);
+ if (option_bool(OPT_CLIENT_SUBNET))
+ {
+ if (option_bool(OPT_STRIP_ECS))
+ replace = 1;
+ len = calc_subnet_opt(&opt, source, cacheable);
+ }
+ else if (option_bool(OPT_STRIP_ECS))
+ replace = 2;
+ else
+ return plen;
+
+ return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, replace);
}
int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer)
@@ -460,47 +492,45 @@ static size_t add_umbrella_opt(struct dns_header *header, size_t plen, unsigned
struct umbrella_opt opt = {{"ODNS"}, UMBRELLA_VERSION, 0, {}};
u8 *u = &opt.fields[0];
-
- if (daemon->umbrella_org) {
- PUTSHORT(UMBRELLA_ORG, u);
- PUTLONG(daemon->umbrella_org, u);
- }
-
int family = source->sa.sa_family;
- PUTSHORT(family == AF_INET ? UMBRELLA_IPV4 : UMBRELLA_IPV6, u);
int size = family == AF_INET ? INADDRSZ : IN6ADDRSZ;
+
+ if (daemon->umbrella_org)
+ {
+ PUTSHORT(UMBRELLA_ORG, u);
+ PUTLONG(daemon->umbrella_org, u);
+ }
+
+ PUTSHORT(family == AF_INET ? UMBRELLA_IPV4 : UMBRELLA_IPV6, u);
memcpy(u, get_addrp(source, family), size);
u += size;
+
+ if (option_bool(OPT_UMBRELLA_DEVID))
+ {
+ PUTSHORT(UMBRELLA_DEVICE, u);
+ memcpy(u, (char *)&daemon->umbrella_device, UMBRELLA_DEVICESZ);
+ u += UMBRELLA_DEVICESZ;
+ }
- if (option_bool(OPT_UMBRELLA_DEVID)) {
- PUTSHORT(UMBRELLA_DEVICE, u);
- memcpy(u, (char *)&daemon->umbrella_device, UMBRELLA_DEVICESZ);
- u += UMBRELLA_DEVICESZ;
- }
-
- if (daemon->umbrella_asset) {
- PUTSHORT(UMBRELLA_ASSET, u);
- PUTLONG(daemon->umbrella_asset, u);
- }
-
- int len = u - &opt.magic[0];
- return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_UMBRELLA, (unsigned char *)&opt, len, 0, 1);
+ if (daemon->umbrella_asset)
+ {
+ PUTSHORT(UMBRELLA_ASSET, u);
+ PUTLONG(daemon->umbrella_asset, u);
+ }
+
+ return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_UMBRELLA, (unsigned char *)&opt, u - (u8 *)&opt, 0, 1);
}
/* Set *check_subnet if we add a client subnet option, which needs to checked
in the reply. Set *cacheable to zero if we add an option which the answer
may depend on. */
size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *limit,
- union mysockaddr *source, time_t now, int *check_subnet, int *cacheable)
+ union mysockaddr *source, time_t now, int *cacheable)
{
- *check_subnet = 0;
*cacheable = 1;
- if (option_bool(OPT_ADD_MAC))
- plen = add_mac(header, plen, limit, source, now, cacheable);
-
- if (option_bool(OPT_MAC_B64) || option_bool(OPT_MAC_HEX))
- plen = add_dns_client(header, plen, limit, source, now, cacheable);
+ plen = add_mac(header, plen, limit, source, now, cacheable);
+ plen = add_dns_client(header, plen, limit, source, now, cacheable);
if (daemon->dns_client_id)
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMCPEID,
@@ -509,11 +539,7 @@ size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *l
if (option_bool(OPT_UMBRELLA))
plen = add_umbrella_opt(header, plen, limit, source, cacheable);
- if (option_bool(OPT_CLIENT_SUBNET))
- {
- plen = add_source_addr(header, plen, limit, source, cacheable);
- *check_subnet = 1;
- }
-
+ plen = add_source_addr(header, plen, limit, source, cacheable);
+
return plen;
}