diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 index 487e23f..88609f1 100644 --- a/man/dnsmasq.8 +++ b/man/dnsmasq.8 @@ -576,14 +576,14 @@ for details. Instead, the keyword .B ra-names may be used. This does the same at ra-only, but also enables a mode which gives DNS names to dual-stack hosts which do SLAAC for -IPv6. Dnsmasq uses the hosts IPv4 lease to derive the name, network +IPv6. Dnsmasq uses the host's IPv4 lease to derive the name, network segment and MAC address and assumes that the host will also have an IPv6 address calculated using the SLAAC alogrithm, on the same network -segment. An AAAA record is added to the DNS for this IPv6 +segment. The address is pinged, and if a reply is received, an AAAA +record is added to the DNS for this IPv6 address. Note that this is only happens for directly-connected -networks, (not one doing DHCP via a relay) and it will generate an -erroneous AAAA record if a host is using privacy extensions or does -not support IPv6. Use with care. +networks, (not one doing DHCP via a relay) and it will not work +if a host is using privacy extensions. The interface: section is not normally used. See the NOTES section for details of this. @@ -1292,13 +1292,17 @@ only a subset of this is needed, and dnsmasq can handle it, using existing DHCP configuration to provide most data. When RA is enabled, dnsmasq will advertise a prefix for each dhcp-range, with default router and recursive DNS server as the relevant link-local address on -the machine running dnsmasq. The "managed address" bits are set, -except for a dhcp-range which is marked as "ra-only", in which case RA -is provided but no DHCPv6 service and the managed address bits are -cleared. +the machine running dnsmasq. The "managed address" bits are set, and +the "use SLAAC" bit is reset, except for a dhcp-range which is +marked as "ra-only" or "ra-names", in which case RA is provided but no +DHCPv6 service and the managed address bits are +cleared and the "use SLAAC" bit set. If the same subnet appears in a +normal dhcp-range and an "ra-only" dhcp-range, then the "managed +address" bits and the "use SLAAC" bits are all set, allowing SLAAC and +DHCP address to co-exist on the same subnet. .B enable-ra enables router advertisement for prefixes where dnsmasq is doing -DHCPv6. It is not needed to "ra-only" prefixes. Creating an "ra-only" +DHCPv6. It is not needed for "ra-only" prefixes. Creating an "ra-only" prefix and not setting .B enable-ra sends advertisements only to "ra-only" prefixes. diff --git a/src/dnsmasq.c b/src/dnsmasq.c index b2810c5..531e0b0 100644 --- a/src/dnsmasq.c +++ b/src/dnsmasq.c @@ -23,7 +23,6 @@ struct daemon *daemon; static volatile pid_t pid = 0; static volatile int pipewrite; -static int alarm_queued = 0; static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp); static void check_dns_listeners(fd_set *set, time_t now); @@ -868,20 +867,14 @@ static void sig_handler(int sig) /* now == 0 -> queue immediate callback */ void send_alarm(time_t event, time_t now) { - - if (now != 0 && event == 0) - return; - - if ((now == 0 || difftime(event, now) <= 0.0)) + if (now == 0 || event != 0) { - if (!alarm_queued) - { - send_event(pipewrite, EVENT_ALARM, 0, NULL); - alarm_queued = 1; - } + /* alarm(0) or alarm(-ve) doesn't do what we want.... */ + if ((now == 0 || difftime(event, now) <= 0.0)) + send_event(pipewrite, EVENT_ALARM, 0, NULL); + else + alarm((unsigned)difftime(event, now)); } - else - alarm((unsigned)difftime(event, now)); } void send_event(int fd, int event, int data, char *msg) @@ -995,7 +988,6 @@ static void async_event(int pipe, time_t now) break; case EVENT_ALARM: - alarm_queued = 0; #ifdef HAVE_DHCP if (daemon->dhcp || daemon->dhcp6) { diff --git a/src/radv.c b/src/radv.c index 854f35b..ab15b68 100644 --- a/src/radv.c +++ b/src/radv.c @@ -206,7 +206,7 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest) ra->type = ND_ROUTER_ADVERT; ra->code = 0; ra->hop_limit = hop_limit; - ra->flags = 0; + ra->flags = 0x00; ra->lifetime = htons(1800); /* AdvDefaultLifetime*/ ra->reachable_time = 0; ra->retrans_time = 0; @@ -246,7 +246,7 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest) /* set managed bits unless we're providing only RA on this link */ if (parm.managed) - ra->flags = 0xc0; + ra->flags = 0xc0; /* M flag, managed, O flag, other */ /* decide where we're sending */ memset(&addr, 0, sizeof(addr)); @@ -293,7 +293,11 @@ static int add_prefixes(struct in6_addr *local, int prefix, is_same_net6(local, &context->start6, prefix) && is_same_net6(local, &context->end6, prefix)) { - if (!(context->flags & CONTEXT_RA_ONLY)) + int do_slaac = 0; + + if (context->flags & CONTEXT_RA_ONLY) + do_slaac = 1; + else { /* don't do RA for non-ra-only unless --enable-ra is set */ if (!option_bool(OPT_RA)) @@ -317,6 +321,10 @@ static int add_prefixes(struct in6_addr *local, int prefix, is_same_net6(local, &tmp->start6, prefix) && is_same_net6(local, &tmp->end6, prefix)) { + /* if any dhcp-range with ra-only on this subnet + set the "do_slaac" bit */ + if (tmp->flags & CONTEXT_RA_ONLY) + do_slaac = 1; tmp->flags |= CONTEXT_RA_DONE; context->ra_time = 0; } @@ -335,7 +343,7 @@ static int add_prefixes(struct in6_addr *local, int prefix, opt->len = 4; opt->prefix_len = prefix; /* autonomous only is we're not doing dhcp */ - opt->flags = (context->flags & CONTEXT_RA_ONLY) ? 0xc0 : 0x00; + opt->flags = do_slaac ? 0x40 : 0x00; opt->valid_lifetime = opt->preferred_lifetime = htonl(time); opt->reserved = 0;