Make wildcard-configured addresses work on multiple networks.

This commit is contained in:
Simon Kelley
2013-03-15 18:25:10 +00:00
parent 0f128eb58c
commit de92b479d9
3 changed files with 163 additions and 118 deletions

View File

@@ -371,29 +371,36 @@ struct dhcp_context *address6_valid(struct dhcp_context *context,
return NULL; return NULL;
} }
static int is_config_in_context6(struct dhcp_context *context, struct dhcp_config *config) int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr)
{ {
/* expand wildcard on contructed contexts */ if (!config || !(config->flags & CONFIG_ADDR6))
if ((config->flags & CONFIG_WILDCARD) && return 0;
(context->flags & CONTEXT_CONSTRUCTED))
if ((config->flags & CONFIG_WILDCARD) && context->prefix == 64)
{ {
u64 addrpart = addr6part(&config->addr6); *addr = context->start6;
config->addr6 = context->start6; setaddr6part(addr, addr6part(&config->addr6));
setaddr6part(&config->addr6, addrpart);
return 1; return 1;
} }
if (!(config->flags & CONFIG_ADDR6) || is_addr_in_context6(context, &config->addr6)) if (is_same_net6(&context->start6, &config->addr6, context->prefix))
{
*addr = config->addr6;
return 1; return 1;
}
return 0; return 0;
} }
static int is_config_in_context6(struct dhcp_context *context, struct dhcp_config *config)
int is_addr_in_context6(struct dhcp_context *context, struct in6_addr *addr)
{ {
if (!(config->flags & CONFIG_ADDR6) ||
(config->flags & CONFIG_WILDCARD))
return 1;
for (; context; context = context->current) for (; context; context = context->current)
if (is_same_net6(addr, &context->start6, context->prefix)) if (is_same_net6(&config->addr6, &context->start6, context->prefix))
return 1; return 1;
return 0; return 0;

View File

@@ -723,6 +723,7 @@ struct dhcp_context {
#define CONTEXT_RA 8192 #define CONTEXT_RA 8192
#define CONTEXT_WILDCARD 16384 #define CONTEXT_WILDCARD 16384
#define CONTEXT_USED 32768 #define CONTEXT_USED 32768
#define CONTEXT_CONF_USED 65536
struct ping_result { struct ping_result {
struct in_addr addr; struct in_addr addr;
@@ -1175,7 +1176,7 @@ void dhcp6_init(void);
void dhcp6_packet(time_t now); void dhcp6_packet(time_t now);
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len, struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len,
int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans); int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans);
int is_addr_in_context6(struct dhcp_context *context, struct in6_addr *addr); int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr);
struct dhcp_context *address6_available(struct dhcp_context *context, struct dhcp_context *address6_available(struct dhcp_context *context,
struct in6_addr *taddr, struct in6_addr *taddr,
struct dhcp_netid *netids, struct dhcp_netid *netids,

View File

@@ -52,11 +52,15 @@ static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz);
static struct prefix_class *prefix_class_from_context(struct dhcp_context *context); static struct prefix_class *prefix_class_from_context(struct dhcp_context *context);
#endif #endif
static void mark_context_used(struct state *state, struct dhcp_context *context, struct in6_addr *addr); 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, unsigned int requested_time,
unsigned int *min_time, struct in6_addr *addr, int update_lease, time_t now); 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 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 int add_local_addrs(struct dhcp_context *context);
struct dhcp_netid *add_options(struct state *state, struct in6_addr *fallback, struct dhcp_context *context); struct dhcp_netid *add_options(struct state *state, struct in6_addr *fallback, struct dhcp_context *context);
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);
#define opt6_len(opt) ((int)(opt6_uint(opt, -2, 2))) #define opt6_len(opt) ((int)(opt6_uint(opt, -2, 2)))
#define opt6_type(opt) (opt6_uint(opt, -4, 2)) #define opt6_type(opt) (opt6_uint(opt, -4, 2))
@@ -522,9 +526,10 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
case DHCP6SOLICIT: case DHCP6SOLICIT:
{ {
void *rapid_commit = opt6_find(state.packet_options, state.end, OPTION6_RAPID_COMMIT, 0); void *rapid_commit = opt6_find(state.packet_options, state.end, OPTION6_RAPID_COMMIT, 0);
int used_config = 0, address_assigned = 0; int address_assigned = 0;
/* tags without all prefix-class tags */ /* tags without all prefix-class tags */
struct dhcp_netid *solicit_tags = run_tag_if(state.tags); struct dhcp_netid *solicit_tags = run_tag_if(state.tags);
struct dhcp_context *c;
if (rapid_commit) if (rapid_commit)
{ {
@@ -535,7 +540,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
/* set reply message type */ /* set reply message type */
*outmsgtypep = rapid_commit ? DHCP6REPLY : DHCP6ADVERTISE; *outmsgtypep = rapid_commit ? DHCP6REPLY : DHCP6ADVERTISE;
log6_packet(&state, "DHCPSOLICIT", NULL, ignore ? "ignored" : NULL); log6_packet(&state, "DHCPSOLICIT", NULL, ignore ? _("ignored") : NULL);
if (ignore) if (ignore)
return 0; return 0;
@@ -543,17 +548,19 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
/* reset USED bits in leases */ /* reset USED bits in leases */
lease6_reset(); lease6_reset();
/* Can use configured address max once per prefix */
for (c = context; c; c = c->current)
c->flags &= ~CONTEXT_CONF_USED;
for (opt = state.packet_options; opt; opt = opt6_next(opt, state.end)) for (opt = state.packet_options; opt; opt = opt6_next(opt, state.end))
{ {
void *ia_option, *ia_end; void *ia_option, *ia_end;
unsigned int min_time = 0xffffffff; unsigned int min_time = 0xffffffff;
int t1cntr; int t1cntr;
int config_ok = 0;
int ia_counter; int ia_counter;
/* set unless we're sending a particular prefix-class, when we /* 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. */ want only dhcp-ranges with the correct tags set and not those without any tags. */
int plain_range = 1; int plain_range = 1;
struct dhcp_context *c;
u32 lease_time, requested_time; u32 lease_time, requested_time;
struct dhcp_lease *ltmp; struct dhcp_lease *ltmp;
struct in6_addr *req_addr; struct in6_addr *req_addr;
@@ -565,19 +572,6 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
if (!check_ia(&state, opt, &ia_end, &ia_option)) if (!check_ia(&state, opt, &ia_end, &ia_option))
continue; continue;
if (have_config(config, CONFIG_ADDR6))
{
struct dhcp_lease *config_lease = lease6_find_by_addr(&config->addr6, 128, 0);
config_ok = 1;
if (config_lease &&
(config_lease->clid_len != state.clid_len ||
memcmp(config_lease->clid, state.clid, state.clid_len) != 0 ||
config_lease->hwaddr_type != state.iaid))
config_ok = 0; /* configured address leased elsewhere */
}
/* reset USED bits in contexts - one address per prefix per IAID */ /* reset USED bits in contexts - one address per prefix per IAID */
for (c = context; c; c = c->current) for (c = context; c; c = c->current)
c->flags &= ~CONTEXT_USED; c->flags &= ~CONTEXT_USED;
@@ -649,7 +643,6 @@ 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)) 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); req_addr = opt6_ptr(ia_option, 0);
ltmp = lease6_find_by_addr(req_addr, 128, 0);
requested_time = opt6_uint(ia_option, 16, 4); requested_time = opt6_uint(ia_option, 16, 4);
if ((c = address6_valid(context, req_addr, solicit_tags, plain_range))) if ((c = address6_valid(context, req_addr, solicit_tags, plain_range)))
@@ -658,19 +651,16 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
/* If the client asks for an address on the same network as a configured address, /* If the client asks for an address on the same network as a configured address,
offer the configured address instead, to make moving to newly-configured offer the configured address instead, to make moving to newly-configured
addresses automatic. */ addresses automatic. */
if (!used_config && config_ok && is_same_net6(req_addr, &config->addr6, c->prefix)) if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr) && check_address(&state, &addr))
{ {
req_addr = &config->addr6; req_addr = &addr;
used_config = 1; mark_config_used(c, &addr);
if (have_config(config, CONFIG_TIME)) if (have_config(config, CONFIG_TIME))
lease_time = config->lease_time; lease_time = config->lease_time;
} }
else if (!(c = address6_available(context, req_addr, solicit_tags, plain_range))) else if (!(c = address6_available(context, req_addr, solicit_tags, plain_range)))
continue; /* not an address we're allowed */ continue; /* not an address we're allowed */
else if (ltmp && else if (!check_address(&state, req_addr))
(ltmp->clid_len != state.clid_len ||
memcmp(ltmp->clid, state.clid, state.clid_len) != 0 ||
ltmp->hwaddr_type != state.iaid))
continue; /* address leased elsewhere */ continue; /* address leased elsewhere */
/* add address to output packet */ /* add address to output packet */
@@ -685,10 +675,11 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
} }
} }
/* Suggest configured address */ /* Suggest configured address(es) */
if (!used_config && config_ok && (c = address6_valid(context, &config->addr6, solicit_tags, plain_range))) for (c = context; c; c = c->current)
if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr) && check_address(&state, &addr))
{ {
used_config = 1; mark_config_used(context, &addr);
if (have_config(config, CONFIG_TIME)) if (have_config(config, CONFIG_TIME))
lease_time = config->lease_time; lease_time = config->lease_time;
/* add address to output packet */ /* add address to output packet */
@@ -696,8 +687,8 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
if (dump_all_prefix_classes) if (dump_all_prefix_classes)
state.send_prefix_class = prefix_class_from_context(c); state.send_prefix_class = prefix_class_from_context(c);
#endif #endif
add_address(&state, c, lease_time, requested_time, &min_time, &config->addr6, rapid_commit != NULL, now); add_address(&state, c, lease_time, requested_time, &min_time, &addr, rapid_commit != NULL, now);
mark_context_used(&state, context, &config->addr6); mark_context_used(&state, context, &addr);
get_context_tag(&state, c); get_context_tag(&state, c);
address_assigned = 1; address_assigned = 1;
} }
@@ -741,7 +732,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
{ {
o1 = new_opt6(OPTION6_STATUS_CODE); o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6SUCCESS); put_opt6_short(DHCP6SUCCESS);
put_opt6_string("Oh hai from dnsmasq"); put_opt6_string(_("success"));
end_opt6(o1); end_opt6(o1);
/* If --dhcp-authoritative is set, we can tell client not to wait for /* If --dhcp-authoritative is set, we can tell client not to wait for
@@ -756,9 +747,9 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
/* no address, return error */ /* no address, return error */
o1 = new_opt6(OPTION6_STATUS_CODE); o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOADDRS); put_opt6_short(DHCP6NOADDRS);
put_opt6_string("No addresses available"); put_opt6_string(_("no addresses available"));
end_opt6(o1); end_opt6(o1);
log6_packet(&state, "DHCPADVERTISE", NULL, _("No addresses available")); log6_packet(&state, "DHCPADVERTISE", NULL, _("no addresses available"));
} }
break; break;
@@ -771,7 +762,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
/* set reply message type */ /* set reply message type */
*outmsgtypep = DHCP6REPLY; *outmsgtypep = DHCP6REPLY;
log6_packet(&state, "DHCPREQUEST", NULL, ignore ? "ignored" : NULL); log6_packet(&state, "DHCPREQUEST", NULL, ignore ? _("ignored") : NULL);
if (ignore) if (ignore)
return 0; return 0;
@@ -793,24 +784,28 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
u32 requested_time = opt6_uint(ia_option, 16, 4); u32 requested_time = opt6_uint(ia_option, 16, 4);
struct dhcp_context *dynamic, *c; struct dhcp_context *dynamic, *c;
unsigned int lease_time; unsigned int lease_time;
struct in6_addr addr;
int config_ok = 0;
if ((dynamic = address6_available(context, req_addr, tagif, 1)) || (c = address6_valid(context, req_addr, tagif, 1))) if ((c = address6_valid(context, req_addr, tagif, 1)))
config_ok = config_valid(config, c, &addr) && IN6_ARE_ADDR_EQUAL(&addr, req_addr);
if ((dynamic = address6_available(context, req_addr, tagif, 1)) || c)
{ {
if (!dynamic && !(have_config(config, CONFIG_ADDR6) || !IN6_ARE_ADDR_EQUAL(&config->addr6, req_addr))) if (!dynamic && !config_ok)
{ {
/* Static range, not configured. */ /* Static range, not configured. */
o1 = new_opt6(OPTION6_STATUS_CODE); o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6UNSPEC); put_opt6_short(DHCP6UNSPEC);
put_opt6_string("Address unavailable"); put_opt6_string(_("address unavailable"));
end_opt6(o1); end_opt6(o1);
} }
else if (lease6_find_by_addr(req_addr, 128, 0) && else if (!check_address(&state, req_addr))
!lease6_find(state.clid, state.clid_len, state.ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, state.iaid, req_addr))
{ {
/* Address leased to another DUID/IAID */ /* Address leased to another DUID/IAID */
o1 = new_opt6(OPTION6_STATUS_CODE); o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6UNSPEC); put_opt6_short(DHCP6UNSPEC);
put_opt6_string("Address in use"); put_opt6_string(_("address in use"));
end_opt6(o1); end_opt6(o1);
} }
else else
@@ -820,9 +815,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
lease_time = dynamic->lease_time; lease_time = dynamic->lease_time;
if (have_config(config, CONFIG_ADDR6) && if (config_ok && have_config(config, CONFIG_TIME))
IN6_ARE_ADDR_EQUAL(&config->addr6, req_addr) &&
have_config(config, CONFIG_TIME))
lease_time = config->lease_time; lease_time = config->lease_time;
add_address(&state, dynamic, lease_time, requested_time, &min_time, req_addr, 1, now); add_address(&state, dynamic, lease_time, requested_time, &min_time, req_addr, 1, now);
@@ -830,12 +823,12 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
address_assigned = 1; address_assigned = 1;
} }
} }
else if (msg_type == DHCP6REQUEST) else
{ {
/* requested address not on the correct link */ /* requested address not on the correct link */
o1 = new_opt6(OPTION6_STATUS_CODE); o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOTONLINK); put_opt6_short(DHCP6NOTONLINK);
put_opt6_string("Not on link"); put_opt6_string(_("not on link"));
end_opt6(o1); end_opt6(o1);
} }
} }
@@ -848,7 +841,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
{ {
o1 = new_opt6(OPTION6_STATUS_CODE); o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6SUCCESS); put_opt6_short(DHCP6SUCCESS);
put_opt6_string("Oh hai from dnsmasq"); put_opt6_string(_("success"));
end_opt6(o1); end_opt6(o1);
} }
else else
@@ -856,9 +849,9 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
/* no address, return error */ /* no address, return error */
o1 = new_opt6(OPTION6_STATUS_CODE); o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOADDRS); put_opt6_short(DHCP6NOADDRS);
put_opt6_string("No addresses available"); put_opt6_string(_("no addresses available"));
end_opt6(o1); end_opt6(o1);
log6_packet(&state, "DHCPREPLY", NULL, _("No addresses available")); log6_packet(&state, "DHCPREPLY", NULL, _("no addresses available"));
} }
tagif = add_options(&state, fallback, context); tagif = add_options(&state, fallback, context);
@@ -890,13 +883,10 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
struct dhcp_lease *lease = NULL; struct dhcp_lease *lease = NULL;
struct in6_addr *req_addr = opt6_ptr(ia_option, 0); struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
u32 requested_time = opt6_uint(ia_option, 16, 4); u32 requested_time = opt6_uint(ia_option, 16, 4);
unsigned int lease_time; unsigned int preferred_time = 0; /* in case renewal inappropriate */
unsigned int valid_time = 0;
char *message = NULL;
struct dhcp_context *this_context; struct dhcp_context *this_context;
struct dhcp_config *valid_config = config;
/* don't use a config to set lease time if it specifies an address which isn't this. */
if (have_config(config, CONFIG_ADDR6) && !IN6_ARE_ADDR_EQUAL(&config->addr6, req_addr))
valid_config = NULL;
if (!(lease = lease6_find(state.clid, state.clid_len, if (!(lease = lease6_find(state.clid, state.clid_len,
state.ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, state.ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
@@ -908,11 +898,11 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
save_counter(iacntr); save_counter(iacntr);
t1cntr = 0; t1cntr = 0;
log6_packet(&state, "DHCPREPLY", req_addr, "lease not found"); log6_packet(&state, "DHCPREPLY", req_addr, _("lease not found"));
o1 = new_opt6(OPTION6_STATUS_CODE); o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOBINDING); put_opt6_short(DHCP6NOBINDING);
put_opt6_string("No binding found"); put_opt6_string(_("no binding found"));
end_opt6(o1); end_opt6(o1);
break; break;
} }
@@ -921,35 +911,41 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
if ((this_context = address6_available(context, req_addr, tagif, 1)) || if ((this_context = address6_available(context, req_addr, tagif, 1)) ||
(this_context = address6_valid(context, req_addr, tagif, 1))) (this_context = address6_valid(context, req_addr, tagif, 1)))
{ {
struct in6_addr addr;
unsigned int lease_time;
get_context_tag(&state, this_context); get_context_tag(&state, this_context);
lease_time = have_config(valid_config, CONFIG_TIME) ? valid_config->lease_time : this_context->lease_time; if (config_valid(config, this_context, &addr) && IN6_ARE_ADDR_EQUAL(&addr, req_addr) && have_config(config, CONFIG_TIME))
lease_time = config->lease_time;
else
lease_time = this_context->lease_time;
if (requested_time < 120u ) calculate_times(this_context, &min_time, &valid_time, &preferred_time, lease_time, requested_time);
requested_time = 120u; /* sanity */
if (lease_time == 0xffffffff || (requested_time != 0xffffffff && requested_time < lease_time))
lease_time = requested_time;
lease_set_expires(lease, lease_time, now); lease_set_expires(lease, valid_time, now);
if (state.ia_type == OPTION6_IA_NA && state.hostname) if (state.ia_type == OPTION6_IA_NA && state.hostname)
{ {
char *addr_domain = get_domain6(req_addr); char *addr_domain = get_domain6(req_addr);
if (!state.send_domain) if (!state.send_domain)
state.send_domain = addr_domain; state.send_domain = addr_domain;
lease_set_hostname(lease, state.hostname, state.hostname_auth, addr_domain, state.domain); lease_set_hostname(lease, state.hostname, state.hostname_auth, addr_domain, state.domain);
message = state.hostname;
} }
if (lease_time < min_time)
min_time = lease_time;
}
log6_packet(&state, "DHCPREPLY", req_addr, state.hostname); if (preferred_time == 0)
message = _("deprecated");
}
else
message = _("address invalid");
log6_packet(&state, "DHCPREPLY", req_addr, message);
o1 = new_opt6(OPTION6_IAADDR); o1 = new_opt6(OPTION6_IAADDR);
put_opt6(req_addr, sizeof(*req_addr)); put_opt6(req_addr, sizeof(*req_addr));
/* preferred lifetime */ put_opt6_long(preferred_time);
put_opt6_long(!this_context || (this_context->flags & CONTEXT_DEPRECATE) ? 0 : lease_time); put_opt6_long(valid_time);
put_opt6_long(!this_context ? 0 : lease_time); /* valid lifetime */
end_opt6(o1); end_opt6(o1);
} }
@@ -983,7 +979,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
{ {
o1 = new_opt6(OPTION6_STATUS_CODE); o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOTONLINK); put_opt6_short(DHCP6NOTONLINK);
put_opt6_string("Confirm failed"); put_opt6_string(_("confirm failed"));
end_opt6(o1); end_opt6(o1);
return 1; return 1;
} }
@@ -994,7 +990,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
o1 = new_opt6(OPTION6_STATUS_CODE); o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6SUCCESS ); put_opt6_short(DHCP6SUCCESS );
put_opt6_string("All addresses still on link"); put_opt6_string(_("all addresses still on link"));
end_opt6(o1); end_opt6(o1);
break; break;
} }
@@ -1008,7 +1004,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
context->netid.next = NULL; context->netid.next = NULL;
state.context_tags = &context->netid; state.context_tags = &context->netid;
} }
log6_packet(&state, "DHCPINFORMATION-REQUEST", NULL, ignore ? "ignored" : state.hostname); log6_packet(&state, "DHCPINFORMATION-REQUEST", NULL, ignore ? _("ignored") : state.hostname);
if (ignore) if (ignore)
return 0; return 0;
*outmsgtypep = DHCP6REPLY; *outmsgtypep = DHCP6REPLY;
@@ -1064,7 +1060,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
{ {
o1 = new_opt6(OPTION6_STATUS_CODE); o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOBINDING); put_opt6_short(DHCP6NOBINDING);
put_opt6_string("No binding found"); put_opt6_string(_("no binding found"));
end_opt6(o1); end_opt6(o1);
end_opt6(o); end_opt6(o);
@@ -1073,7 +1069,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
o1 = new_opt6(OPTION6_STATUS_CODE); o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6SUCCESS); put_opt6_short(DHCP6SUCCESS);
put_opt6_string("Release received"); put_opt6_string(_("release received"));
end_opt6(o1); end_opt6(o1);
break; break;
@@ -1141,7 +1137,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
{ {
o1 = new_opt6(OPTION6_STATUS_CODE); o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOBINDING); put_opt6_short(DHCP6NOBINDING);
put_opt6_string("No binding found"); put_opt6_string(_("no binding found"));
end_opt6(o1); end_opt6(o1);
end_opt6(o); end_opt6(o);
@@ -1459,23 +1455,15 @@ 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, unsigned int requested_time,
unsigned int *min_time, struct in6_addr *addr, int do_update, time_t now) unsigned int *min_time, struct in6_addr *addr, int do_update, time_t now)
{ {
unsigned int valid_time = (context->valid < lease_time) ? context->valid : lease_time; unsigned int valid_time, preferred_time;
int o = new_opt6(OPTION6_IAADDR); int o = new_opt6(OPTION6_IAADDR);
struct dhcp_lease *lease; struct dhcp_lease *lease;
calculate_times(context, min_time, &valid_time, &preferred_time, lease_time, requested_time);
put_opt6(addr, sizeof(*addr)); put_opt6(addr, sizeof(*addr));
put_opt6_long(preferred_time);
/* preferred lifetime */ put_opt6_long(valid_time);
if (requested_time < 120u )
requested_time = 120u; /* sanity */
if (lease_time == 0xffffffff || (requested_time != 0xffffffff && requested_time < lease_time))
lease_time = requested_time;
if (lease_time < *min_time)
*min_time = lease_time;
put_opt6_long((context->preferred < lease_time) ? context->preferred : lease_time);
put_opt6_long(valid_time); /* valid lifetime */
#ifdef OPTION6_PREFIX_CLASS #ifdef OPTION6_PREFIX_CLASS
if (state->send_prefix_class) if (state->send_prefix_class)
@@ -1532,6 +1520,55 @@ static void mark_context_used(struct state *state, struct dhcp_context *context,
#endif #endif
} }
static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr)
{
for (; context; context = context->current)
if (is_same_net6(addr, &context->start6, context->prefix))
context->flags |= CONTEXT_CONF_USED;
}
/* make sure address not leased to another CLID/IAID */
static int check_address(struct state *state, struct in6_addr *addr)
{
struct dhcp_lease *lease;
if (!(lease = lease6_find_by_addr(addr, 128, 0)))
return 1;
if (lease->clid_len != state->clid_len ||
memcmp(lease->clid, state->clid, state->clid_len) != 0 ||
lease->hwaddr_type != state->iaid)
return 0;
return 1;
}
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_time, valid_time;
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)
preferred_time = 0;
if (preferred_time != 0 && preferred_time < *min_time)
*min_time = preferred_time;
if (valid_time != 0 && valid_time < *min_time)
*min_time = valid_time;
*valid_timep = valid_time;
*preferred_timep = preferred_time;
}
static void update_leases(struct state *state, struct dhcp_context *context, struct in6_addr *addr, unsigned int lease_time, 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)
{ {
struct dhcp_lease *lease = lease6_find_by_addr(addr, 128, 0); struct dhcp_lease *lease = lease6_find_by_addr(addr, 128, 0);