diff options
author | Simon Kelley <simon@thekelleys.org.uk> | 2013-07-27 21:32:32 +0100 |
---|---|---|
committer | Simon Kelley <simon@thekelleys.org.uk> | 2013-07-28 09:37:38 +0100 |
commit | 871d4562f11ac281b4e7074000daf53a38937497 (patch) | |
tree | 391a95985cc23343d5539167da7538857568dbf3 | |
parent | 0f371f9e1aba19ccdd396b98ccacb92ff182a2f1 (diff) | |
download | dnsmasq-871d4562f11ac281b4e7074000daf53a38937497.tar.gz |
Support RFC-4242 information-refresh-time.
-rw-r--r-- | CHANGELOG | 6 | ||||
-rw-r--r-- | src/dhcp6-protocol.h | 1 | ||||
-rw-r--r-- | src/rfc3315.c | 46 |
3 files changed, 43 insertions, 10 deletions
@@ -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,....... */ |