RDNSS and DNSSL data in router advertisements.

This commit is contained in:
Simon Kelley
2012-03-31 21:18:55 +01:00
parent 05e92e5afe
commit 18f0fb050b
6 changed files with 113 additions and 24 deletions

View File

@@ -70,6 +70,9 @@ version 2.61
Fix bug in address6_available() which caused DHCPv6 lease
aquistion to fail of more than one dhcp-range in use.
Provide RDNSS and DNSSL data in router advertisements,
using the settings provided for DHCP options
option6:domain-search and option6:dns-server.
version 2.60

View File

@@ -1343,6 +1343,10 @@ the machine running dnsmasq. By default, he "managed address" bits are set, and
the "use SLAAC" bit is reset. This can be changed for individual
subnets with the mode keywords described in
.B --dhcp-range.
RFC6106 DNS parameters are included in the advertisements. By default,
the relevant link-local address of the machine running dnsmasq is sent
as recursive DNS server. If provided, the DHCPv6 options dns-server and
domain-search are used for RDNSS and DNSSL.
.TP
.B --enable-tftp[=<interface>]
Enable the TFTP server function. This is deliberately limited to that

View File

@@ -54,6 +54,7 @@
#define OPTION6_RECONFIGURE_MSG 19
#define OPTION6_RECONF_ACCEPT 20
#define OPTION6_DNS_SERVER 23
#define OPTION6_DOMAIN_SEARCH 24
#define OPTION6_REMOTE_ID 37
#define OPTION6_SUBSCRIBER_ID 38
#define OPTION6_FQDN 39

View File

@@ -1000,6 +1000,7 @@ static char *parse_dhcp_opt(char *arg, int flags)
while (arg && *arg)
{
u16 len = strlen(arg);
unhide_metas(arg);
PUTSHORT(len, p);
memcpy(p, arg, len);
p += len;
@@ -1013,29 +1014,40 @@ static char *parse_dhcp_opt(char *arg, int flags)
}
else if (comma && (opt_len & OT_RFC1035_NAME))
{
int i, commas = 1;
unsigned char *p, *newp;
for (i = 0; comma[i]; i++)
if (comma[i] == ',')
commas++;
newp = opt_malloc(strlen(comma)+(2*commas));
p = newp;
unsigned char *p = NULL, *newp, *end;
int len = 0;
arg = comma;
comma = split(arg);
while (arg && *arg)
{
p = do_rfc1035_name(p, arg);
*p++ = 0;
char *dom = canonicalise_opt(arg);
if (!dom)
{
problem = _("bad domain in dhcp-option");
break;
}
newp = opt_malloc(len + strlen(dom) + 2);
if (p)
{
memcpy(newp, p, len);
free(p);
}
p = newp;
end = do_rfc1035_name(p + len, dom);
*end++ = 0;
len = end - p;
free(dom);
arg = comma;
comma = split(arg);
}
new->val = newp;
new->len = p - newp;
new->val = p;
new->len = len;
}
#endif
else

View File

@@ -43,6 +43,7 @@ struct prefix_opt {
#define ICMP6_OPT_PREFIX 3
#define ICMP6_OPT_MTU 5
#define ICMP6_OPT_RDNSS 25
#define ICMP6_OPT_DNSSL 31

View File

@@ -29,6 +29,7 @@
struct ra_param {
int ind, managed, other, found_context, first;
char *if_name;
struct dhcp_netid *tags;
struct in6_addr link_local;
};
@@ -189,6 +190,9 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
struct ifreq ifr;
struct sockaddr_in6 addr;
struct dhcp_context *context;
struct dhcp_netid iface_id;
struct dhcp_opt *opt_cfg;
int done_dns = 0;
save_counter(0);
ra = expand(sizeof(struct ra_packet));
@@ -208,8 +212,16 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
parm.if_name = iface_name;
parm.first = 1;
/* set tag with name == interface */
iface_id.net = iface_name;
iface_id.next = NULL;
parm.tags = &iface_id;
for (context = daemon->ra_contexts; context; context = context->next)
context->flags &= ~CONTEXT_RA_DONE;
{
context->flags &= ~CONTEXT_RA_DONE;
context->netid.next = &context->netid;
}
if (!iface_enumerate(AF_INET6, &parm, add_prefixes) ||
!parm.found_context)
@@ -227,13 +239,62 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
iface_enumerate(AF_LOCAL, &iface, add_lla);
/* RDNSS, RFC 6106 */
put_opt6_char(ICMP6_OPT_RDNSS);
put_opt6_char(3);
put_opt6_short(0);
put_opt6_long(1800); /* lifetime - twice RA retransmit */
put_opt6(&parm.link_local, IN6ADDRSZ);
/* RDNSS, RFC 6106, use relevant DHCP6 options */
(void)option_filter(parm.tags, NULL, daemon->dhcp_opts6);
for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
{
int i;
/* netids match and not encapsulated? */
if (!(opt_cfg->flags & DHOPT_TAGOK))
continue;
if (opt_cfg->opt == OPTION6_DNS_SERVER)
{
struct in6_addr *a = (struct in6_addr *)opt_cfg->val;
done_dns = 1;
if (opt_cfg->len == 0)
continue;
put_opt6_char(ICMP6_OPT_RDNSS);
put_opt6_char((opt_cfg->len/8) + 1);
put_opt6_short(0);
put_opt6_long(1800); /* lifetime - twice RA retransmit */
/* zero means "self" */
for (i = 0; i < opt_cfg->len; i += IN6ADDRSZ, a++)
if (IN6_IS_ADDR_UNSPECIFIED(a))
put_opt6(&parm.link_local, IN6ADDRSZ);
else
put_opt6(a, IN6ADDRSZ);
}
if (opt_cfg->opt == OPTION6_DOMAIN_SEARCH && opt_cfg->len != 0)
{
int len = ((opt_cfg->len+7)/8);
put_opt6_char(ICMP6_OPT_DNSSL);
put_opt6_char(len + 1);
put_opt6_short(0);
put_opt6_long(1800); /* lifetime - twice RA retransmit */
put_opt6(opt_cfg->val, opt_cfg->len);
/* pad */
for (i = opt_cfg->len; i < len * 8; i++)
put_opt6_char(0);
}
}
if (!done_dns)
{
/* default == us. */
put_opt6_char(ICMP6_OPT_RDNSS);
put_opt6_char(3);
put_opt6_short(0);
put_opt6_long(1800); /* lifetime - twice RA retransmit */
put_opt6(&parm.link_local, IN6ADDRSZ);
}
/* set managed bits unless we're providing only RA on this link */
if (parm.managed)
@@ -324,6 +385,13 @@ static int add_prefixes(struct in6_addr *local, int prefix,
param->first = 0;
param->found_context = 1;
/* collect dhcp-range tags */
if (context->netid.next == &context->netid && context->netid.net)
{
context->netid.next = param->tags;
param->tags = &context->netid;
}
if (!(context->flags & CONTEXT_RA_DONE))
{
context->flags |= CONTEXT_RA_DONE;