summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Kelley <simon@thekelleys.org.uk>2013-07-27 21:32:32 +0100
committerSimon Kelley <simon@thekelleys.org.uk>2013-07-28 09:37:38 +0100
commit871d4562f11ac281b4e7074000daf53a38937497 (patch)
tree391a95985cc23343d5539167da7538857568dbf3
parent0f371f9e1aba19ccdd396b98ccacb92ff182a2f1 (diff)
downloaddnsmasq-871d4562f11ac281b4e7074000daf53a38937497.tar.gz
Support RFC-4242 information-refresh-time.
-rw-r--r--CHANGELOG6
-rw-r--r--src/dhcp6-protocol.h1
-rw-r--r--src/rfc3315.c46
3 files changed, 43 insertions, 10 deletions
diff --git a/CHANGELOG b/CHANGELOG
index c18f1ae..9322f8f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -85,6 +85,12 @@ version 2.67
Fix MAC address enumeration on *BSD. Thanks to Brad Smith
for the bug report.
+ Support RFC-4242 information-refresh-time options in the
+ reply to DHCPv6 information-request. The lease time of the
+ smallest valid dhcp-range is sent. Thanks to Uwe Schindler
+ for suggesting this.
+
+
version 2.66
Add the ability to act as an authoritative DNS
server. Dnsmasq can now answer queries from the wider 'net
diff --git a/src/dhcp6-protocol.h b/src/dhcp6-protocol.h
index 50d84a9..c4eef35 100644
--- a/src/dhcp6-protocol.h
+++ b/src/dhcp6-protocol.h
@@ -55,6 +55,7 @@
#define OPTION6_RECONF_ACCEPT 20
#define OPTION6_DNS_SERVER 23
#define OPTION6_DOMAIN_SEARCH 24
+#define OPTION6_REFRESH_TIME 32
#define OPTION6_REMOTE_ID 37
#define OPTION6_SUBSCRIBER_ID 38
#define OPTION6_FQDN 39
diff --git a/src/rfc3315.c b/src/rfc3315.c
index 22d1983..a7d511d 100644
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -58,7 +58,7 @@ static void add_address(struct state *state, struct dhcp_context *context, unsig
unsigned int *min_time, struct in6_addr *addr, int update_lease, time_t now);
static void update_leases(struct state *state, struct dhcp_context *context, struct in6_addr *addr, unsigned int lease_time, time_t now);
static int add_local_addrs(struct dhcp_context *context);
-struct dhcp_netid *add_options(struct state *state, struct in6_addr *fallback, struct dhcp_context *context);
+static struct dhcp_netid *add_options(struct state *state, struct in6_addr *fallback, struct dhcp_context *context, int do_refresh);
static void calculate_times(struct dhcp_context *context, unsigned int *min_time, unsigned int *valid_timep,
unsigned int *preferred_timep, unsigned int lease_time, unsigned int requested_time);
@@ -747,7 +747,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
o = new_opt6(OPTION6_PREFERENCE);
put_opt6_char(option_bool(OPT_AUTHORITATIVE) ? 255 : 0);
end_opt6(o);
- tagif = add_options(&state, fallback, context);
+ tagif = add_options(&state, fallback, context, 0);
}
else
{
@@ -865,7 +865,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
log6_packet(&state, "DHCPREPLY", NULL, _("no addresses available"));
}
- tagif = add_options(&state, fallback, context);
+ tagif = add_options(&state, fallback, context, 0);
break;
}
@@ -964,7 +964,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
end_opt6(o);
}
- tagif = add_options(&state, fallback, context);
+ tagif = add_options(&state, fallback, context, 0);
break;
}
@@ -1028,7 +1028,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
if (ignore)
return 0;
*outmsgtypep = DHCP6REPLY;
- tagif = add_options(&state, fallback, context);
+ tagif = add_options(&state, fallback, context, 1);
break;
}
@@ -1178,13 +1178,16 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
}
-struct dhcp_netid *add_options(struct state *state, struct in6_addr *fallback, struct dhcp_context *context)
+static struct dhcp_netid *add_options(struct state *state,
+ struct in6_addr *fallback,
+ struct dhcp_context *context,
+ int do_refresh)
{
void *oro;
/* filter options based on tags, those we want get DHOPT_TAGOK bit set */
struct dhcp_netid *tagif = option_filter(state->tags, state->context_tags, daemon->dhcp_opts6);
struct dhcp_opt *opt_cfg;
- int done_dns = 0, do_encap = 0;
+ int done_dns = 0, done_refresh = !do_refresh, do_encap = 0;
int i, o, o1;
oro = opt6_find(state->packet_options, state->end, OPTION6_ORO, 0);
@@ -1212,6 +1215,9 @@ struct dhcp_netid *add_options(struct state *state, struct in6_addr *fallback, s
if (opt_cfg->len == 0)
continue;
}
+
+ if (opt_cfg->opt == OPTION6_REFRESH_TIME)
+ done_refresh = 1;
o = new_opt6(opt_cfg->opt);
if (opt_cfg->flags & DHOPT_ADDR6)
@@ -1235,15 +1241,35 @@ struct dhcp_netid *add_options(struct state *state, struct in6_addr *fallback, s
end_opt6(o);
}
- if (daemon->port == NAMESERVER_PORT && !done_dns &&
- (!IN6_IS_ADDR_UNSPECIFIED(&context->local6) ||
- !IN6_IS_ADDR_UNSPECIFIED(fallback)))
+ if (daemon->port == NAMESERVER_PORT && !done_dns)
{
o = new_opt6(OPTION6_DNS_SERVER);
if (!add_local_addrs(context))
put_opt6(fallback, IN6ADDRSZ);
end_opt6(o);
}
+
+ if (context && !done_refresh)
+ {
+ struct dhcp_context *c;
+ unsigned int lease_time = 0xffffffff;
+
+ /* Find the smallest lease tie of all contexts,
+ subjext to the RFC-4242 stipulation that this must not
+ be less than 600. */
+ for (c = context; c; c = c->next)
+ if (c->lease_time < lease_time)
+ {
+ if (c->lease_time < 600)
+ lease_time = 600;
+ else
+ lease_time = c->lease_time;
+ }
+
+ o = new_opt6(OPTION6_REFRESH_TIME);
+ put_opt6_long(lease_time);
+ end_opt6(o);
+ }
/* handle vendor-identifying vendor-encapsulated options,
dhcp-option = vi-encap:13,17,....... */