diff options
author | Simon Kelley <simon@thekelleys.org.uk> | 2014-02-17 21:43:27 +0000 |
---|---|---|
committer | Simon Kelley <simon@thekelleys.org.uk> | 2014-02-17 21:43:27 +0000 |
commit | de73a497cad2172312c2233e0f3492dc5572ae34 (patch) | |
tree | bcc9f8af17051c70384f6921d8b4d9c96597fd52 | |
parent | e3ec15af106eda302a537a3570d6527933fa1494 (diff) | |
download | dnsmasq-de73a497cad2172312c2233e0f3492dc5572ae34.tar.gz |
--rev-server option. Syntactic sugar for PTR queries.
-rw-r--r-- | CHANGELOG | 4 | ||||
-rw-r--r-- | man/dnsmasq.8 | 8 | ||||
-rw-r--r-- | src/option.c | 142 |
3 files changed, 102 insertions, 52 deletions
@@ -62,7 +62,9 @@ version 2.69 an invaluable period of full-time work to get it to a workable state. - + Add --rev-server. Thanks to Dave Taht for suggesting this. + + version 2.68 Use random addresses for DHCPv6 temporary address allocations, instead of algorithmically determined stable diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 index f3c5de1..8d2c95d 100644 --- a/man/dnsmasq.8 +++ b/man/dnsmasq.8 @@ -415,6 +415,14 @@ source address specified but the port may be specified directly as part of the source address. Forcing queries to an interface is not implemented on all platforms supported by dnsmasq. .TP +.B --rev-server=<ip-address>/<prefix-len>,<ipaddr>[#<port>][@<source-ip>|<interface>[#<port>]] +This is functionally the same as +.B --server, +but provides some syntactic sugar to make specifying address-to-name queries easier. For example +.B --rev-server=1.2.3.0/24,192.168.0.1 +is exactly equivalent to +.B --server=/3.2.1.in-addr.arpa/192.168.0.1 +.TP .B \-A, --address=/<domain>/[domain/]<ipaddr> Specify an IP address to return for any host in the given domains. Queries in the domains are never forwarded and always replied to diff --git a/src/option.c b/src/option.c index f7f98d5..f3d107d 100644 --- a/src/option.c +++ b/src/option.c @@ -141,6 +141,7 @@ struct myoption { #define LOPT_SEC_VALID 329 #define LOPT_TRUST_ANCHOR 330 #define LOPT_DNSSEC_DEBUG 331 +#define LOPT_REV_SERV 332 #ifdef HAVE_GETOPT_LONG static const struct option opts[] = @@ -178,6 +179,7 @@ static const struct myoption opts[] = { "pid-file", 2, 0, 'x' }, { "strict-order", 0, 0, 'o' }, { "server", 1, 0, 'S' }, + { "rev-server", 1, 0, LOPT_REV_SERV }, { "local", 1, 0, LOPT_LOCAL }, { "address", 1, 0, 'A' }, { "conf-file", 2, 0, 'C' }, @@ -348,6 +350,7 @@ static struct { { 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL }, { 'r', ARG_DUP, "<path>", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE }, { 'S', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL }, + { LOPT_REV_SERV, ARG_DUP, "<addr>/<prefix>,<ipaddr>", gettext_noop("Specify address of upstream servers for reverse address queries"), NULL }, { LOPT_LOCAL, ARG_DUP, "/<domain>/", gettext_noop("Never forward queries to specified domains."), NULL }, { 's', ARG_DUP, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL }, { 't', ARG_ONE, "<host_name>", gettext_noop("Specify default target in an MX record."), NULL }, @@ -591,6 +594,7 @@ static int atoi_check16(char *a, int *res) return 1; } +#ifdef HAVE_DNSSEC static int atoi_check8(char *a, int *res) { if (!(atoi_check(a, res)) || @@ -600,6 +604,7 @@ static int atoi_check8(char *a, int *res) return 1; } +#endif static void add_txt(char *name, char *txt) { @@ -762,6 +767,54 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a return NULL; } +static struct server *add_rev4(struct in_addr addr, int msize) +{ + struct server *serv = opt_malloc(sizeof(struct server)); + in_addr_t a = ntohl(addr.s_addr) >> 8; + char *p; + + memset(serv, 0, sizeof(struct server)); + p = serv->domain = opt_malloc(25); /* strlen("xxx.yyy.zzz.in-addr.arpa")+1 */ + + if (msize == 24) + p += sprintf(p, "%d.", a & 0xff); + a = a >> 8; + if (msize != 8) + p += sprintf(p, "%d.", a & 0xff); + a = a >> 8; + p += sprintf(p, "%d.in-addr.arpa", a & 0xff); + + serv->flags = SERV_HAS_DOMAIN; + serv->next = daemon->servers; + daemon->servers = serv; + + return serv; + +} + +static struct server *add_rev6(struct in6_addr *addr, int msize) +{ + struct server *serv = opt_malloc(sizeof(struct server)); + char *p; + int i; + + memset(serv, 0, sizeof(struct server)); + p = serv->domain = opt_malloc(73); /* strlen("32*<n.>ip6.arpa")+1 */ + + for (i = msize-1; i >= 0; i -= 4) + { + int dig = ((unsigned char *)addr)[i>>3]; + p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4); + } + p += sprintf(p, "ip6.arpa"); + + serv->flags = SERV_HAS_DOMAIN; + serv->next = daemon->servers; + daemon->servers = serv; + + return serv; +} + #ifdef HAVE_DHCP static int is_tag_prefix(char *arg) @@ -1824,34 +1877,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma ret_err(gen_err); else { - /* generate the equivalent of - local=/<domain>/ - local=/xxx.yyy.zzz.in-addr.arpa/ */ - struct server *serv = opt_malloc(sizeof(struct server)); - in_addr_t a = ntohl(new->start.s_addr) >> 8; - char *p; - - memset(serv, 0, sizeof(struct server)); - serv->domain = d; - serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR; - serv->next = daemon->servers; - daemon->servers = serv; - - serv = opt_malloc(sizeof(struct server)); - memset(serv, 0, sizeof(struct server)); - p = serv->domain = opt_malloc(25); /* strlen("xxx.yyy.zzz.in-addr.arpa")+1 */ - - if (msize == 24) - p += sprintf(p, "%d.", a & 0xff); - a = a >> 8; - if (msize != 8) - p += sprintf(p, "%d.", a & 0xff); - a = a >> 8; - p += sprintf(p, "%d.in-addr.arpa", a & 0xff); - - serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR; - serv->next = daemon->servers; - daemon->servers = serv; + /* generate the equivalent of + local=/<domain>/ + local=/xxx.yyy.zzz.in-addr.arpa/ */ + struct server *serv = add_rev4(new->start, msize); + serv->flags |= SERV_NO_ADDR; } } } @@ -1887,29 +1917,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma /* generate the equivalent of local=/<domain>/ local=/xxx.yyy.zzz.ip6.arpa/ */ - struct server *serv = opt_malloc(sizeof(struct server)); - char *p; - - memset(serv, 0, sizeof(struct server)); - serv->domain = d; - serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR; - serv->next = daemon->servers; - daemon->servers = serv; - - serv = opt_malloc(sizeof(struct server)); - memset(serv, 0, sizeof(struct server)); - p = serv->domain = opt_malloc(73); /* strlen("32*<n.>ip6.arpa")+1 */ - - for (i = msize-1; i >= 0; i -= 4) - { - int dig = ((unsigned char *)&new->start6)[i>>3]; - p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4); - } - p += sprintf(p, "ip6.arpa"); - - serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR; - serv->next = daemon->servers; - daemon->servers = serv; + struct server *serv = add_rev6(&new->start6, msize); + serv->flags |= SERV_NO_ADDR; } } } @@ -2180,6 +2189,37 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma break; } + case LOPT_REV_SERV: /* --rev-server */ + { + char *string; + int size; + struct server *serv; + struct in_addr addr4; +#ifdef HAVE_IPV6 + struct in6_addr addr6; +#endif + + unhide_metas(arg); + if (!arg || !(comma=split(arg)) || !(string = split_chr(arg, '/')) || !atoi_check(string, &size)) + ret_err(gen_err); + + if (inet_pton(AF_INET, arg, &addr4)) + serv = add_rev4(addr4, size); +#ifdef HAVE_IPV6 + else if (inet_pton(AF_INET6, arg, &addr6)) + serv = add_rev6(&addr6, size); +#endif + else + ret_err(gen_err); + + string = parse_server(comma, &serv->addr, &serv->source_addr, serv->interface, &serv->flags); + + if (string) + ret_err(string); + + break; + } + case LOPT_IPSET: /* --ipset */ #ifndef HAVE_IPSET ret_err(_("recompile with HAVE_IPSET defined to enable ipset directives")); |