diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 index eb7f76f..d4b4322 100644 --- a/man/dnsmasq.8 +++ b/man/dnsmasq.8 @@ -199,7 +199,12 @@ or .B --listen-address configuration, indeed .B --auth-server -will overide these and provide a different DNS service on the specified interface. The is the "glue record". It should resolve in the global DNS to a A and/or AAAA record which points to the address dnsmasq is listening on. +will overide these and provide a different DNS service on the +specified interface. The is the "glue record". It should +resolve in the global DNS to a A and/or AAAA record which points to +the address dnsmasq is listening on. When an interface is specified, +it may be qualified with "/4" or "/6" to specify only the IPv4 or IPv6 +addresses associated with the interface. .TP .B \-2, --no-dhcp-interface= Do not provide DHCP or TFTP on the specified interface, but do provide DNS service. diff --git a/src/auth.c b/src/auth.c index e7168c2..763c169 100644 --- a/src/auth.c +++ b/src/auth.c @@ -660,16 +660,16 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n *cut = 0; for (addrlist = intr->addr; addrlist; addrlist = addrlist->next) - if (!(subnet->flags & ADDRLIST_IPV6) && - (local_query || filter_zone(zone, F_IPV4, &addrlist->addr)) && + if (!(addrlist->flags & ADDRLIST_IPV6) && + (local_query || filter_zone(zone, F_IPV4, &addrlist->addr)) && add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl, NULL, T_A, C_IN, "4", cut ? intr->name : NULL, &addrlist->addr)) anscount++; #ifdef HAVE_IPV6 for (addrlist = intr->addr; addrlist; addrlist = addrlist->next) - if ((subnet->flags & ADDRLIST_IPV6) && - (local_query || filter_zone(zone, F_IPV6, &addrlist->addr)) && + if ((addrlist->flags & ADDRLIST_IPV6) && + (local_query || filter_zone(zone, F_IPV6, &addrlist->addr)) && add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl, NULL, T_AAAA, C_IN, "6", cut ? intr->name : NULL, &addrlist->addr)) anscount++; diff --git a/src/network.c b/src/network.c index 3515a52..51d9d53 100644 --- a/src/network.c +++ b/src/network.c @@ -159,7 +159,8 @@ int iface_check(int family, struct all_addr *addr, char *name, int *auth) for (tmp = daemon->authinterface; tmp; tmp = tmp->next) if (tmp->name) { - if (strcmp(tmp->name, name) == 0) + if (strcmp(tmp->name, name) == 0 && + (tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family)) break; } else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET && diff --git a/src/option.c b/src/option.c index 42c0198..0ca00b9 100644 --- a/src/option.c +++ b/src/option.c @@ -1620,8 +1620,22 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma new->addr.sa.sa_family = AF_INET6; #endif else - new->name = opt_string_alloc(arg); - + { + char *fam = split_chr(arg, '/'); + new->name = opt_string_alloc(arg); + new->addr.sa.sa_family = 0; + if (fam) + { + if (strcmp(fam, "4") == 0) + new->addr.sa.sa_family = AF_INET; +#ifdef HAVE_IPV6 + else if (strcmp(fam, "6") == 0) + new->addr.sa.sa_family = AF_INET6; +#endif + else + ret_err(gen_err); + } + } new->next = daemon->authinterface; daemon->authinterface = new; diff --git a/src/radv.c b/src/radv.c index 22c2d1f..93503a0 100644 --- a/src/radv.c +++ b/src/radv.c @@ -205,7 +205,7 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de struct dhcp_netid iface_id; struct dhcp_opt *opt_cfg; struct ra_interface *ra_param = find_iface_param(iface_name); - int done_dns = 0; + int done_dns = 0, old_prefix = 0; #ifdef HAVE_LINUX_NETWORK FILE *f; #endif @@ -267,7 +267,7 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de struct in6_addr local = context->start6; int do_slaac = 0; - parm.found_context = 1; + old_prefix = 1; /* zero net part of address */ setaddr6part(&local, addr6part(&local) & ~((context->prefix == 64) ? (u64)-1LL : (1LLU << (128 - context->prefix)) - 1LLU)); @@ -300,9 +300,14 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de up = &context->next; } - if (!parm.found_context) - return; - + /* If we're advertising only old prefixes, set router lifetime to zero. */ + if (old_prefix && !parm.found_context) + ra->lifetime = htons(0); + + /* No prefixes to advertise. */ + if (!old_prefix && !parm.found_context) + return; + #ifdef HAVE_LINUX_NETWORK /* Note that IPv6 MTU is not necessarilly the same as the IPv4 MTU available from SIOCGIFMTU */