diff options
author | Simon Kelley <simon@thekelleys.org.uk> | 2021-07-18 18:18:56 +0100 |
---|---|---|
committer | Simon Kelley <simon@thekelleys.org.uk> | 2021-07-18 18:18:56 +0100 |
commit | adf9dec1e6be3ef56412b7e556b2dd47ac7fee51 (patch) | |
tree | 25e298e660236c89ecd574c5002036a0dbdd5960 | |
parent | 767d9cbd9692fb7722b05ac60ee261ad25a5d113 (diff) | |
download | dnsmasq-adf9dec1e6be3ef56412b7e556b2dd47ac7fee51.tar.gz |
Allow shorter IPv6 prefix lengths in (some) --synth-domain options.
-rw-r--r-- | CHANGELOG | 3 | ||||
-rw-r--r-- | man/dnsmasq.8 | 3 | ||||
-rw-r--r-- | src/dnsmasq.h | 4 | ||||
-rw-r--r-- | src/domain.c | 68 | ||||
-rw-r--r-- | src/option.c | 12 |
5 files changed, 51 insertions, 39 deletions
@@ -76,6 +76,9 @@ version 2.86 Disallowed queries are not forwarded; they are rejected with a REFUSED error code. + Allow smaller then 64 prefix lengths in synth-domain, with caveats. + --synth-domain=1234:4567::/56,example.com is now valid. + version 2.85 Fix problem with DNS retries in 2.83/2.84. diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 index b6a1f27..b3c335e 100644 --- a/man/dnsmasq.8 +++ b/man/dnsmasq.8 @@ -705,7 +705,8 @@ configured a zero is added in front of the label. ::1 becomes 0--1. V4 mapped IPv6 addresses, which have a representation like ::ffff:1.2.3.4 are handled specially, and become like 0--ffff-1-2-3-4 The address range can be of the form -<ip address>,<ip address> or <ip address>/<netmask> in both forms of the option. +<start address>,<end address> or <ip address>/<prefix-length> in both forms of the option. For IPv6 the start and end addresses +must fall in the same /64 network, or prefix-length must be greater than or equal to 64 except that shorter prefix lengths than 64 are allowed only if non-sequential names are in use. .TP .B --dumpfile=<path/to/file> Specify the location of a pcap-format file which dnsmasq uses to dump copies of network packets for debugging purposes. If the file exists when dnsmasq starts, it is not deleted; new packets are added to the end. diff --git a/src/dnsmasq.h b/src/dnsmasq.h index a88cbc5..6e20636 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -960,10 +960,10 @@ struct dhcp_bridge { }; struct cond_domain { - char *domain, *prefix; + char *domain, *prefix; /* prefix is text-prefix on domain name */ struct in_addr start, end; struct in6_addr start6, end6; - int is6, indexed; + int is6, indexed, prefixlen; struct cond_domain *next; }; diff --git a/src/domain.c b/src/domain.c index 189bdd1..91e0f22 100644 --- a/src/domain.c +++ b/src/domain.c @@ -18,8 +18,9 @@ static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c); +static int match_domain(struct in_addr addr, struct cond_domain *c); static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c); - +static int match_domain6(struct in6_addr *addr, struct cond_domain *c); int is_name_synthetic(int flags, char *name, union all_addr *addr) { @@ -135,28 +136,9 @@ int is_name_synthetic(int flags, char *name, union all_addr *addr) } if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr)) - { - if (prot == AF_INET) - { - if (!c->is6 && - ntohl(addr->addr4.s_addr) >= ntohl(c->start.s_addr) && - ntohl(addr->addr4.s_addr) <= ntohl(c->end.s_addr)) - found = 1; - } - else - { - u64 addrpart = addr6part(&addr->addr6); - - if (c->is6 && - is_same_net6(&addr->addr6, &c->start6, 64) && - addrpart >= addr6part(&c->start6) && - addrpart <= addr6part(&c->end6)) - found = 1; - } - } - + found = (prot == AF_INET) ? match_domain(addr->addr4, c) : match_domain6(&addr->addr6, c); } - + /* restore name */ for (p = tail; *p; p++) if (*p == '.' || *p == ':') @@ -246,14 +228,22 @@ int is_rev_synth(int flag, union all_addr *addr, char *name) } +static int match_domain(struct in_addr addr, struct cond_domain *c) +{ + if (!c->is6 && + ntohl(addr.s_addr) >= ntohl(c->start.s_addr) && + ntohl(addr.s_addr) <= ntohl(c->end.s_addr)) + return 1; + + return 0; +} + static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c) { for (; c; c = c->next) - if (!c->is6 && - ntohl(addr.s_addr) >= ntohl(c->start.s_addr) && - ntohl(addr.s_addr) <= ntohl(c->end.s_addr)) + if (match_domain(addr, c)) return c; - + return NULL; } @@ -267,16 +257,30 @@ char *get_domain(struct in_addr addr) return daemon->domain_suffix; } - -static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c) +static int match_domain6(struct in6_addr *addr, struct cond_domain *c) { u64 addrpart = addr6part(addr); + if (c->is6) + { + if (c->prefixlen >= 64) + { + if (is_same_net6(addr, &c->start6, 64) && + addrpart >= addr6part(&c->start6) && + addrpart <= addr6part(&c->end6)) + return 1; + } + else if (is_same_net6(addr, &c->start6, c->prefixlen)) + return 1; + } + + return 0; +} + +static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c) +{ for (; c; c = c->next) - if (c->is6 && - is_same_net6(addr, &c->start6, 64) && - addrpart >= addr6part(&c->start6) && - addrpart <= addr6part(&c->end6)) + if (match_domain6(addr, c)) return c; return NULL; diff --git a/src/option.c b/src/option.c index 964c3b1..e857c76 100644 --- a/src/option.c +++ b/src/option.c @@ -2268,6 +2268,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma new->prefix = NULL; new->indexed = 0; + new->prefixlen = 0; unhide_metas(comma); if ((netpart = split_chr(comma, '/'))) @@ -2313,16 +2314,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma u64 mask = (1LLU << (128 - msize)) - 1LLU; u64 addrpart = addr6part(&new->start6); new->is6 = 1; + new->prefixlen = msize; /* prefix==64 overflows the mask calculation above */ - if (msize == 64) + if (msize <= 64) mask = (u64)-1LL; new->end6 = new->start6; setaddr6part(&new->start6, addrpart & ~mask); setaddr6part(&new->end6, addrpart | mask); - if (msize < 64) + if (msize < 64 && option == 's') ret_err_free(gen_err, new); else if (arg) { @@ -2393,15 +2395,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma else { char *star; - new->next = daemon->synth_domains; - daemon->synth_domains = new; if (new->prefix && (star = strrchr(new->prefix, '*')) && *(star+1) == 0) { *star = 0; new->indexed = 1; + if (new->is6 && new->prefixlen < 64) + ret_err_free(_("prefix too small"), new); } + new->next = daemon->synth_domains; + daemon->synth_domains = new; } } else if (option == 's') |