mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
Fix DHCPv6 lease time calculation when client sends VL==0 or PL==0
This commit is contained in:
111
src/rfc3315.c
111
src/rfc3315.c
@@ -54,13 +54,13 @@ static struct prefix_class *prefix_class_from_context(struct dhcp_context *conte
|
||||
static void mark_context_used(struct state *state, struct dhcp_context *context, struct in6_addr *addr);
|
||||
static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr);
|
||||
static int check_address(struct state *state, struct in6_addr *addr);
|
||||
static void add_address(struct state *state, struct dhcp_context *context, unsigned int lease_time, unsigned int requested_time,
|
||||
static void add_address(struct state *state, struct dhcp_context *context, unsigned int lease_time, void *ia_option,
|
||||
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);
|
||||
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);
|
||||
unsigned int *preferred_timep, unsigned int lease_time);
|
||||
|
||||
#define opt6_len(opt) ((int)(opt6_uint(opt, -2, 2)))
|
||||
#define opt6_type(opt) (opt6_uint(opt, -4, 2))
|
||||
@@ -574,7 +574,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
||||
/* set unless we're sending a particular prefix-class, when we
|
||||
want only dhcp-ranges with the correct tags set and not those without any tags. */
|
||||
int plain_range = 1;
|
||||
u32 lease_time, requested_time;
|
||||
u32 lease_time;
|
||||
struct dhcp_lease *ltmp;
|
||||
struct in6_addr *req_addr;
|
||||
struct in6_addr addr;
|
||||
@@ -645,8 +645,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
||||
for (ia_counter = 0; ia_option; ia_counter++, ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
||||
{
|
||||
req_addr = opt6_ptr(ia_option, 0);
|
||||
requested_time = opt6_uint(ia_option, 16, 4);
|
||||
|
||||
|
||||
if ((c = address6_valid(context, req_addr, solicit_tags, plain_range)))
|
||||
{
|
||||
lease_time = c->lease_time;
|
||||
@@ -670,7 +669,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
||||
if (dump_all_prefix_classes && state.ia_type == OPTION6_IA_NA)
|
||||
state.send_prefix_class = prefix_class_from_context(c);
|
||||
#endif
|
||||
add_address(&state, c, lease_time, requested_time, &min_time, req_addr, rapid_commit != NULL, now);
|
||||
add_address(&state, c, lease_time, ia_option, &min_time, req_addr, rapid_commit != NULL, now);
|
||||
mark_context_used(&state, context, req_addr);
|
||||
get_context_tag(&state, c);
|
||||
address_assigned = 1;
|
||||
@@ -694,7 +693,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
||||
if (dump_all_prefix_classes && state.ia_type == OPTION6_IA_NA)
|
||||
state.send_prefix_class = prefix_class_from_context(c);
|
||||
#endif
|
||||
add_address(&state, c, lease_time, lease_time, &min_time, &addr, rapid_commit != NULL, now);
|
||||
add_address(&state, c, lease_time, NULL, &min_time, &addr, rapid_commit != NULL, now);
|
||||
mark_context_used(&state, context, &addr);
|
||||
get_context_tag(&state, c);
|
||||
address_assigned = 1;
|
||||
@@ -711,7 +710,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
||||
if (dump_all_prefix_classes && state.ia_type == OPTION6_IA_NA)
|
||||
state.send_prefix_class = prefix_class_from_context(c);
|
||||
#endif
|
||||
add_address(&state, c, c->lease_time, c->lease_time, &min_time, req_addr, rapid_commit != NULL, now);
|
||||
add_address(&state, c, c->lease_time, NULL, &min_time, req_addr, rapid_commit != NULL, now);
|
||||
mark_context_used(&state, context, req_addr);
|
||||
get_context_tag(&state, c);
|
||||
address_assigned = 1;
|
||||
@@ -725,7 +724,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
||||
if (dump_all_prefix_classes && state.ia_type == OPTION6_IA_NA)
|
||||
state.send_prefix_class = prefix_class_from_context(c);
|
||||
#endif
|
||||
add_address(&state, c, c->lease_time, c->lease_time, &min_time, &addr, rapid_commit != NULL, now);
|
||||
add_address(&state, c, c->lease_time, NULL, &min_time, &addr, rapid_commit != NULL, now);
|
||||
mark_context_used(&state, context, &addr);
|
||||
get_context_tag(&state, c);
|
||||
address_assigned = 1;
|
||||
@@ -788,7 +787,6 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
||||
for (; ia_option; ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
||||
{
|
||||
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
|
||||
u32 requested_time = opt6_uint(ia_option, 16, 4);
|
||||
struct dhcp_context *dynamic, *c;
|
||||
unsigned int lease_time;
|
||||
struct in6_addr addr;
|
||||
@@ -829,7 +827,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
||||
if (dump_all_prefix_classes && state.ia_type == OPTION6_IA_NA)
|
||||
state.send_prefix_class = prefix_class_from_context(c);
|
||||
#endif
|
||||
add_address(&state, dynamic, lease_time, requested_time, &min_time, req_addr, 1, now);
|
||||
add_address(&state, dynamic, lease_time, ia_option, &min_time, req_addr, 1, now);
|
||||
get_context_tag(&state, dynamic);
|
||||
address_assigned = 1;
|
||||
}
|
||||
@@ -893,9 +891,8 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
||||
{
|
||||
struct dhcp_lease *lease = NULL;
|
||||
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
|
||||
u32 requested_time = opt6_uint(ia_option, 16, 4);
|
||||
unsigned int preferred_time = 0; /* in case renewal inappropriate */
|
||||
unsigned int valid_time = 0;
|
||||
unsigned int preferred_time = opt6_uint(ia_option, 16, 4);
|
||||
unsigned int valid_time = opt6_uint(ia_option, 20, 4);
|
||||
char *message = NULL;
|
||||
struct dhcp_context *this_context;
|
||||
|
||||
@@ -915,6 +912,8 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
||||
put_opt6_short(DHCP6NOBINDING);
|
||||
put_opt6_string(_("no binding found"));
|
||||
end_opt6(o1);
|
||||
|
||||
preferred_time = valid_time = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -932,7 +931,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
||||
else
|
||||
lease_time = this_context->lease_time;
|
||||
|
||||
calculate_times(this_context, &min_time, &valid_time, &preferred_time, lease_time, requested_time);
|
||||
calculate_times(this_context, &min_time, &valid_time, &preferred_time, lease_time);
|
||||
|
||||
lease_set_expires(lease, valid_time, now);
|
||||
if (state.ia_type == OPTION6_IA_NA && state.hostname)
|
||||
@@ -949,8 +948,11 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
||||
message = _("deprecated");
|
||||
}
|
||||
else
|
||||
message = _("address invalid");
|
||||
|
||||
{
|
||||
preferred_time = valid_time = 0;
|
||||
message = _("address invalid");
|
||||
}
|
||||
|
||||
log6_packet(&state, "DHCPREPLY", req_addr, message);
|
||||
|
||||
o1 = new_opt6(OPTION6_IAADDR);
|
||||
@@ -1500,14 +1502,21 @@ static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz)
|
||||
}
|
||||
}
|
||||
|
||||
static void add_address(struct state *state, struct dhcp_context *context, unsigned int lease_time, unsigned int requested_time,
|
||||
static void add_address(struct state *state, struct dhcp_context *context, unsigned int lease_time, void *ia_option,
|
||||
unsigned int *min_time, struct in6_addr *addr, int do_update, time_t now)
|
||||
{
|
||||
unsigned int valid_time, preferred_time;
|
||||
unsigned int valid_time = 0, preferred_time = 0;
|
||||
int o = new_opt6(OPTION6_IAADDR);
|
||||
struct dhcp_lease *lease;
|
||||
|
||||
calculate_times(context, min_time, &valid_time, &preferred_time, lease_time, requested_time);
|
||||
/* get client requested times */
|
||||
if (ia_option)
|
||||
{
|
||||
preferred_time = opt6_uint(ia_option, 16, 4);
|
||||
valid_time = opt6_uint(ia_option, 20, 4);
|
||||
}
|
||||
|
||||
calculate_times(context, min_time, &valid_time, &preferred_time, lease_time);
|
||||
|
||||
put_opt6(addr, sizeof(*addr));
|
||||
put_opt6_long(preferred_time);
|
||||
@@ -1591,22 +1600,60 @@ static int check_address(struct state *state, struct in6_addr *addr)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Calculate valid and preferred times to send in leases/renewals.
|
||||
|
||||
Inputs are:
|
||||
|
||||
*valid_timep, *preferred_timep - requested times from IAADDR options.
|
||||
context->valid, context->preferred - times associated with subnet address on local interface.
|
||||
context->flags | CONTEXT_DEPRECATE - "deprecated" flag in dhcp-range.
|
||||
lease_time - configured time for context for individual client.
|
||||
*min_time - smallest valid time sent so far.
|
||||
|
||||
Outputs are :
|
||||
|
||||
*valid_timep, *preferred_timep - times to be send in IAADDR option.
|
||||
*min_time - smallest valid time sent so far, to calculate T1 and T2.
|
||||
|
||||
*/
|
||||
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)
|
||||
unsigned int *preferred_timep, unsigned int lease_time)
|
||||
{
|
||||
unsigned int preferred_time, valid_time;
|
||||
unsigned int req_preferred = *preferred_timep, req_valid = *valid_timep;
|
||||
unsigned int valid_time = lease_time, preferred_time = lease_time;
|
||||
|
||||
/* RFC 3315: "A server ignores the lifetimes set
|
||||
by the client if the preferred lifetime is greater than the valid
|
||||
lifetime. */
|
||||
if (req_preferred <= req_valid)
|
||||
{
|
||||
if (req_preferred != 0)
|
||||
{
|
||||
/* 0 == "no preference from client" */
|
||||
if (req_preferred < 120u)
|
||||
req_preferred = 120u; /* sanity */
|
||||
|
||||
if (req_preferred < preferred_time)
|
||||
preferred_time = req_preferred;
|
||||
}
|
||||
|
||||
if (req_valid != 0)
|
||||
/* 0 == "no preference from client" */
|
||||
{
|
||||
if (req_valid < 120u)
|
||||
req_valid = 120u; /* sanity */
|
||||
|
||||
if (req_valid < valid_time)
|
||||
valid_time = req_valid;
|
||||
}
|
||||
}
|
||||
|
||||
if (requested_time < 120u )
|
||||
requested_time = 120u; /* sanity */
|
||||
if (lease_time == 0xffffffff || (requested_time != 0xffffffff && requested_time < lease_time))
|
||||
lease_time = requested_time;
|
||||
|
||||
valid_time = (context->valid < lease_time) ? context->valid : lease_time;
|
||||
preferred_time = (context->preferred < lease_time) ? context->preferred : lease_time;
|
||||
|
||||
if (context->flags & CONTEXT_DEPRECATE)
|
||||
/* deprecate (preferred == 0) which configured, or when local address
|
||||
is deprecated */
|
||||
if ((context->flags & CONTEXT_DEPRECATE) || context->preferred == 0)
|
||||
preferred_time = 0;
|
||||
|
||||
|
||||
if (preferred_time != 0 && preferred_time < *min_time)
|
||||
*min_time = preferred_time;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user