Tidy previous commit and add manpage entries for new options.

This commit is contained in:
Simon Kelley
2022-01-15 17:57:57 +00:00
parent 3ab0ad8748
commit 27ce754b3d
4 changed files with 77 additions and 68 deletions

View File

@@ -742,6 +742,9 @@ have security and privacy implications. The warning about caching
given for \fB--add-subnet\fP applies to \fB--add-mac\fP too. An alternative encoding of the given for \fB--add-subnet\fP applies to \fB--add-mac\fP too. An alternative encoding of the
MAC, as base64, is enabled by adding the "base64" parameter and a human-readable encoding of hex-and-colons is enabled by added the "text" parameter. MAC, as base64, is enabled by adding the "base64" parameter and a human-readable encoding of hex-and-colons is enabled by added the "text" parameter.
.TP .TP
.B --strip-mac
Remove any MAC address information already in downstream queries before forwarding upstream.
.TP
.B --add-cpe-id=<string> .B --add-cpe-id=<string>
Add an arbitrary identifying string to DNS queries which are Add an arbitrary identifying string to DNS queries which are
forwarded upstream. forwarded upstream.
@@ -767,6 +770,11 @@ will add 1.2.3.0/24 for IPv4 requestors and ::/0 for IPv6 requestors.
.B --add-subnet=1.2.3.4/24,1.2.3.4/24 .B --add-subnet=1.2.3.4/24,1.2.3.4/24
will add 1.2.3.0/24 for both IPv4 and IPv6 requestors. will add 1.2.3.0/24 for both IPv4 and IPv6 requestors.
.TP .TP
.B --strip-subnet
Remove any subnet address already present in a downstream query before forwarding it upstream. If --add-subnet is set this also
ensures that any downstream-provided subnet is replaced by the one added by dnsmasq. Otherwise, dnsmaaq will NOT replace an
existing subnet in the query.
.TP
.B --umbrella[=[deviceid:<deviceid>][,orgid:<orgid>][,assetid:<id>]] .B --umbrella[=[deviceid:<deviceid>][,orgid:<orgid>][,assetid:<id>]]
Embeds the requestor's IP address in DNS queries forwarded upstream. Embeds the requestor's IP address in DNS queries forwarded upstream.
If device id or, asset id or organization id are specified, the information is If device id or, asset id or organization id are specified, the information is

View File

@@ -724,7 +724,7 @@ struct hostsfile {
#define FREC_NOREBIND 1 #define FREC_NOREBIND 1
#define FREC_CHECKING_DISABLED 2 #define FREC_CHECKING_DISABLED 2
#define FREC_HAS_SUBNET 4 #define FREC_NO_CACHE 4
#define FREC_DNSKEY_QUERY 8 #define FREC_DNSKEY_QUERY 8
#define FREC_DS_QUERY 16 #define FREC_DS_QUERY 16
#define FREC_AD_QUESTION 32 #define FREC_AD_QUESTION 32
@@ -733,7 +733,6 @@ struct hostsfile {
#define FREC_TEST_PKTSZ 256 #define FREC_TEST_PKTSZ 256
#define FREC_HAS_EXTRADATA 512 #define FREC_HAS_EXTRADATA 512
#define FREC_HAS_PHEADER 1024 #define FREC_HAS_PHEADER 1024
#define FREC_NO_CACHE 2048
#define HASH_SIZE 32 /* SHA-256 digest size */ #define HASH_SIZE 32 /* SHA-256 digest size */
@@ -1785,7 +1784,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do, int replace); unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do, int replace);
size_t add_do_bit(struct dns_header *header, size_t plen, unsigned char *limit); size_t add_do_bit(struct dns_header *header, size_t plen, unsigned char *limit);
size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *limit, 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);
int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer); int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer);
/* arp.c */ /* arp.c */

View File

@@ -264,49 +264,62 @@ static void encoder(unsigned char *in, char *out)
out[3] = char64(in[2]); 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, static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned char *limit,
union mysockaddr *l3, time_t now, int *cacheablep) 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]; 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; if (option_bool(OPT_STRIP_MAC))
*cacheablep = 0; replace = 1;
*cacheablep = 0;
if (option_bool(OPT_MAC_HEX))
print_mac(encode, mac, maclen); if (option_bool(OPT_MAC_HEX))
else print_mac(encode, mac, maclen);
{ else
encoder(mac, encode); {
encoder(mac+3, encode+4); encoder(mac, encode);
encode[8] = 0; encoder(mac+3, encode+4);
} encode[8] = 0;
}
} }
else if (option_bool(OPT_STRIP_MAC))
replace = 2;
return add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMDEVICEID, (unsigned char *)encode, strlen(encode), 0, replace); if (replace != 0 || maclen == 6)
plen = 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, static size_t add_mac(struct dns_header *header, size_t plen, unsigned char *limit,
union mysockaddr *l3, time_t now, int *cacheablep, const int replace) union mysockaddr *l3, time_t now, int *cacheablep)
{ {
int maclen; int maclen = 0, replace = 0;
unsigned char mac[DHCP_CHADDR_MAX]; 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; *cacheablep = 0;
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac, maclen, 0, replace); if (option_bool(OPT_STRIP_MAC))
replace = 1;
} }
else if(replace > 0) else if (option_bool(OPT_STRIP_MAC))
{ replace = 2;
/* Asked to replace MAC address but it is not available here. We just remove whatever might be there */
plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, EDNS0_OPTION_MAC, NULL, 0, 0, 2);
}
if (replace != 0 || maclen != 0)
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac, maclen, 0, replace);
return plen; return plen;
} }
@@ -383,15 +396,28 @@ static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source,
return len + 4; return len + 4;
} }
/* 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, static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned char *limit,
union mysockaddr *source, int *cacheable, const int replace) union mysockaddr *source, int *cacheable)
{ {
/* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */ /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
int len; int replace = 0, len = 0;
struct subnet_opt opt; struct subnet_opt opt;
len = calc_subnet_opt(&opt, source, cacheable); 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); return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, replace);
} }
@@ -499,24 +525,12 @@ static size_t add_umbrella_opt(struct dns_header *header, size_t plen, unsigned
in the reply. Set *cacheable to zero if we add an option which the answer in the reply. Set *cacheable to zero if we add an option which the answer
may depend on. */ may depend on. */
size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *limit, 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; *cacheable = 1;
/* OPT_ADD_MAC = MAC is added (if available) plen = add_mac(header, plen, limit, source, now, cacheable);
OPT_ADD_MAC + OPT_STRIP_MAC = MAC is replaced, if not available, it is only removed plen = add_dns_client(header, plen, limit, source, now, cacheable);
OPT_STRIP_MAC = MAC is removed */
if (option_bool(OPT_ADD_MAC))
plen = add_mac(header, plen, limit, source, now, cacheable, option_bool(OPT_STRIP_MAC) ? 1 : 0);
else if (option_bool(OPT_STRIP_MAC))
plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, EDNS0_OPTION_MAC, NULL, 0, 0, 2);
/* Use --strip-mac also for --add-mac=hex and --add-mac=text */
if (option_bool(OPT_MAC_B64) || option_bool(OPT_MAC_HEX))
plen = add_dns_client(header, plen, limit, source, now, cacheable);
else if (option_bool(OPT_STRIP_MAC))
plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, EDNS0_OPTION_NOMDEVICEID, NULL, 0, 0, 2);
if (daemon->dns_client_id) if (daemon->dns_client_id)
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMCPEID, plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMCPEID,
@@ -525,16 +539,7 @@ size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *l
if (option_bool(OPT_UMBRELLA)) if (option_bool(OPT_UMBRELLA))
plen = add_umbrella_opt(header, plen, limit, source, cacheable); plen = add_umbrella_opt(header, plen, limit, source, cacheable);
/* OPT_CLIENT_SUBNET = client subnet is added plen = add_source_addr(header, plen, limit, source, cacheable);
OPT_CLIENT_SUBNET + OPT_STRIP_ECS = client subnet is replaced
OPT_STRIP_ECS = client subnet is removed */
if (option_bool(OPT_CLIENT_SUBNET))
{
plen = add_source_addr(header, plen, limit, source, cacheable, option_bool(OPT_STRIP_ECS) ? 1 : 0);
*check_subnet = 1;
}
else if (option_bool(OPT_STRIP_ECS))
plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, EDNS0_OPTION_CLIENT_SUBNET, NULL, 0, 0, 2);
return plen; return plen;
} }

View File

@@ -195,7 +195,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL); unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
int old_src = 0, old_reply = 0; int old_src = 0, old_reply = 0;
int first, last, start = 0; int first, last, start = 0;
int subnet, cacheable, forwarded = 0; int cacheable, forwarded = 0;
size_t edns0_len; size_t edns0_len;
unsigned char *pheader; unsigned char *pheader;
int ede = EDE_UNSET; int ede = EDE_UNSET;
@@ -443,10 +443,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
{ {
header->id = htons(forward->new_id); header->id = htons(forward->new_id);
plen = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->frec_src.source, now, &subnet, &cacheable); plen = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->frec_src.source, now, &cacheable);
if (subnet)
forward->flags |= FREC_HAS_SUBNET;
if (!cacheable) if (!cacheable)
forward->flags |= FREC_NO_CACHE; forward->flags |= FREC_NO_CACHE;
@@ -624,7 +621,7 @@ static struct ipsets *domain_find_sets(struct ipsets *setlist, const char *domai
static size_t process_reply(struct dns_header *header, time_t now, struct server *server, size_t n, int check_rebind, static size_t process_reply(struct dns_header *header, time_t now, struct server *server, size_t n, int check_rebind,
int no_cache, int cache_secure, int bogusanswer, int ad_reqd, int do_bit, int added_pheader, int no_cache, int cache_secure, int bogusanswer, int ad_reqd, int do_bit, int added_pheader,
int check_subnet, union mysockaddr *query_source, unsigned char *limit, int ede) union mysockaddr *query_source, unsigned char *limit, int ede)
{ {
unsigned char *pheader, *sizep; unsigned char *pheader, *sizep;
struct ipsets *ipsets = NULL, *nftsets = NULL; struct ipsets *ipsets = NULL, *nftsets = NULL;
@@ -651,7 +648,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
/* Get extended RCODE. */ /* Get extended RCODE. */
rcode |= sizep[2] << 4; rcode |= sizep[2] << 4;
if (check_subnet && !check_source(header, plen, pheader, query_source)) if (option_bool(OPT_CLIENT_SUBNET) && !check_source(header, plen, pheader, query_source))
{ {
my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch")); my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch"));
return 0; return 0;
@@ -1241,7 +1238,7 @@ static void return_reply(time_t now, struct frec *forward, struct dns_header *he
if ((nn = process_reply(header, now, forward->sentto, (size_t)n, check_rebind, no_cache_dnssec, cache_secure, bogusanswer, if ((nn = process_reply(header, now, forward->sentto, (size_t)n, check_rebind, no_cache_dnssec, cache_secure, bogusanswer,
forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION, forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION,
forward->flags & FREC_ADDED_PHEADER, forward->flags & FREC_HAS_SUBNET, &forward->frec_src.source, forward->flags & FREC_ADDED_PHEADER, &forward->frec_src.source,
((unsigned char *)header) + daemon->edns_pktsz, ede))) ((unsigned char *)header) + daemon->edns_pktsz, ede)))
{ {
struct frec_src *src; struct frec_src *src;
@@ -1928,7 +1925,7 @@ unsigned char *tcp_request(int confd, time_t now,
int local_auth = 0; int local_auth = 0;
#endif #endif
int checking_disabled, do_bit, added_pheader = 0, have_pseudoheader = 0; int checking_disabled, do_bit, added_pheader = 0, have_pseudoheader = 0;
int check_subnet, cacheable, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0; int cacheable, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
size_t m; size_t m;
unsigned short qtype; unsigned short qtype;
unsigned int gotname; unsigned int gotname;
@@ -2146,7 +2143,7 @@ unsigned char *tcp_request(int confd, time_t now,
else else
start = master->last_server; start = master->last_server;
size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &check_subnet, &cacheable); size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &cacheable);
#ifdef HAVE_DNSSEC #ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID) && (master->flags & SERV_DO_DNSSEC)) if (option_bool(OPT_DNSSEC_VALID) && (master->flags & SERV_DO_DNSSEC))
@@ -2224,7 +2221,7 @@ unsigned char *tcp_request(int confd, time_t now,
m = process_reply(header, now, serv, (unsigned int)m, m = process_reply(header, now, serv, (unsigned int)m,
option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer, option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer,
ad_reqd, do_bit, added_pheader, check_subnet, &peer_addr, ((unsigned char *)header) + 65536, ede); ad_reqd, do_bit, added_pheader, &peer_addr, ((unsigned char *)header) + 65536, ede);
} }
} }
} }