Compare commits

..
5 changed files with 260 additions and 56 deletions

No files matched your search

+5
View File
@@ -59,6 +59,11 @@
#define OPTION6_SUBSCRIBER_ID 38
#define OPTION6_FQDN 39
/* replace this with the real number when allocated.
defining this also enables the relevant code. */
/* #define OPTION6_PREFIX_CLASS 99 */
#define DHCP6SUCCESS 0
#define DHCP6UNSPEC 1
#define DHCP6NOADDRS 2
+10 -8
View File
@@ -266,7 +266,7 @@ struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct
}
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len,
int iaid, struct dhcp_netid *netids, struct in6_addr *ans)
int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans)
{
/* Find a free address: exclude anything in use and anything allocated to
a particular hwaddr/clientid/hostname in our configuration.
@@ -286,7 +286,7 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
for (j = iaid, i = 0; i < clid_len; i++)
j += clid[i] + (j << 6) + (j << 16) - j;
for (pass = 0; pass <= 1; pass++)
for (pass = 0; pass <= plain_range ? 1 : 0; pass++)
for (c = context; c; c = c->current)
if (c->flags & (CONTEXT_DEPRECATE | CONTEXT_STATIC | CONTEXT_RA_STATELESS | CONTEXT_USED))
continue;
@@ -296,7 +296,7 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
{
if (option_bool(OPT_CONSEC_ADDR))
/* seed is largest extant lease addr in this context */
start = lease_find_max_addr6(c);
start = lease_find_max_addr6(c) + serial;
else
start = addr6part(&c->start6) + ((j + c->addr_epoch) % (1 + addr6part(&c->end6) - addr6part(&c->start6)));
@@ -332,7 +332,8 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
/* can dynamically allocate addr */
struct dhcp_context *address6_available(struct dhcp_context *context,
struct in6_addr *taddr,
struct dhcp_netid *netids)
struct dhcp_netid *netids,
int plain_range)
{
u64 start, end, addr = addr6part(taddr);
struct dhcp_context *tmp;
@@ -347,7 +348,7 @@ struct dhcp_context *address6_available(struct dhcp_context *context,
is_same_net6(&tmp->end6, taddr, tmp->prefix) &&
addr >= start &&
addr <= end &&
match_netid(tmp->filter, netids, 1))
match_netid(tmp->filter, netids, plain_range))
return tmp;
}
@@ -356,14 +357,15 @@ struct dhcp_context *address6_available(struct dhcp_context *context,
/* address OK if configured */
struct dhcp_context *address6_valid(struct dhcp_context *context,
struct in6_addr *taddr,
struct dhcp_netid *netids)
struct in6_addr *taddr,
struct dhcp_netid *netids,
int plain_range)
{
struct dhcp_context *tmp;
for (tmp = context; tmp; tmp = tmp->current)
if (is_same_net6(&tmp->start6, taddr, tmp->prefix) &&
match_netid(tmp->filter, netids, 1))
match_netid(tmp->filter, netids, plain_range))
return tmp;
return NULL;
+9 -4
View File
@@ -684,7 +684,7 @@ struct cond_domain {
#ifdef OPTION6_PREFIX_CLASS
struct prefix_class {
int class;
struct dhcp_netid netid;
struct dhcp_netid tag;
struct prefix_class *next;
};
#endif
@@ -829,6 +829,9 @@ extern struct daemon {
unsigned char *duid_config;
char *dbus_name;
unsigned long soa_sn, soa_refresh, soa_retry, soa_expiry;
#ifdef OPTION6_PREFIX_CLASS
struct prefix_class *prefix_classes;
#endif
/* globally used stuff for DNS */
char *packet; /* packet buffer */
@@ -1171,14 +1174,16 @@ int get_incoming_mark(union mysockaddr *peer_addr, struct all_addr *local_addr,
void dhcp6_init(void);
void dhcp6_packet(time_t now);
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len,
int iaid, struct dhcp_netid *netids, 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);
struct dhcp_context *address6_available(struct dhcp_context *context,
struct in6_addr *taddr,
struct dhcp_netid *netids);
struct dhcp_netid *netids,
int plain_range);
struct dhcp_context *address6_valid(struct dhcp_context *context,
struct in6_addr *taddr,
struct dhcp_netid *netids);
struct dhcp_netid *netids,
int plain_range);
struct dhcp_config *find_config6(struct dhcp_config *configs,
struct dhcp_context *context,
unsigned char *duid, int duid_len,
+28 -1
View File
@@ -128,6 +128,9 @@ struct myoption {
#define LOPT_AUTHSFS 317
#define LOPT_AUTHPEER 318
#define LOPT_IPSET 319
#ifdef OPTION6_PREFIX_CLASS
#define LOPT_PREF_CLSS 320
#endif
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -261,6 +264,9 @@ static const struct myoption opts[] =
{ "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
{ "auth-peer", 1, 0, LOPT_AUTHPEER },
{ "ipset", 1, 0, LOPT_IPSET },
#ifdef OPTION6_PREFIX_CLASS
{ "dhcp-prefix-class", 1, 0, LOPT_PREF_CLSS },
#endif
{ NULL, 0, 0, 0 }
};
@@ -400,6 +406,9 @@ static struct {
{ LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
{ LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
{ LOPT_IPSET, ARG_DUP, "/<domain>/<ipset>[,<ipset>...]", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
#ifdef OPTION6_PREFIX_CLASS
{ LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },
#endif
{ 0, 0, NULL, NULL, NULL }
};
@@ -2943,7 +2952,25 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
}
}
break;
#ifdef OPTION6_PREFIX_CLASS
case LOPT_PREF_CLSS: /* --dhcp-prefix-class */
{
struct prefix_class *new = opt_malloc(sizeof(struct prefix_class));
if (!(comma = split(arg)) ||
!atoi_check16(comma, &new->class))
ret_err(gen_err);
new->tag.net = opt_string_alloc(set_prefix(arg));
new->next = daemon->prefix_classes;
daemon->prefix_classes = new;
break;
}
#endif
case 'U': /* --dhcp-vendorclass */
case 'j': /* --dhcp-userclass */
case LOPT_CIRCUIT: /* --dhcp-circuitid */
+208 -43
View File
@@ -29,6 +29,9 @@ struct state {
char *iface_name;
void *packet_options, *end;
struct dhcp_netid *tags, *context_tags;
#ifdef OPTION6_PREFIX_CLASS
struct prefix_class *send_prefix_class;
#endif
};
static int dhcp6_maybe_relay(struct in6_addr *link_address, struct dhcp_netid **relay_tagsp, struct dhcp_context *context,
@@ -42,9 +45,13 @@ static void *opt6_find (void *opts, void *end, unsigned int search, unsigned int
static void *opt6_next(void *opts, void *end);
static unsigned int opt6_uint(unsigned char *opt, int offset, int size);
static void get_context_tag(struct state *state, struct dhcp_context *context);
static void *check_ia(struct state *state, void *opt, void **endp);
static int check_ia(struct state *state, void *opt, void **endp, void **ia_option);
static int build_ia(struct state *state, int *t1cntr);
static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz);
#ifdef OPTION6_PREFIX_CLASS
static struct prefix_class *prefix_class_from_context(struct dhcp_context *context);
#endif
static void mark_context_used(struct state *state, struct dhcp_context *context, struct in6_addr *addr);
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);
static void update_leases(struct state *state, struct dhcp_context *context, struct in6_addr *addr, unsigned int lease_time, time_t now);
@@ -204,6 +211,9 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
struct dhcp_context *context_tmp;
unsigned int ignore = 0;
struct state state;
#ifdef OPTION6_PREFIX_CLASS
struct prefix_class *p;
#endif
state.packet_options = inbuff + 4;
state.end = inbuff + sz;
@@ -221,6 +231,9 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
state.client_hostname = NULL;
state.iface_name = iface_name;
state.fqdn_flags = 0x01; /* default to send if we recieve no FQDN option */
#ifdef OPTION6_PREFIX_CLASS
state.send_prefix_class = NULL;
#endif
/* set tag with name == interface */
iface_id.net = iface_name;
@@ -460,8 +473,22 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
if (have_config(config, CONFIG_DISABLE))
ignore = 1;
}
tagif = run_tag_if(state.tags);
tagif = state.tags;
#ifdef OPTION6_PREFIX_CLASS
/* Add the tags associated with prefix classes so we can use the DHCP ranges.
These are removed and added back one-at-time for SOLICITs
Neccessary to allow REQUEST or RENEW of addresses ADVERTISED under
specific classes. */
for (p = daemon->prefix_classes; p ; p = p->next)
{
p->tag.next = tagif;
tagif = &p->tag;
}
#endif
tagif = run_tag_if(tagif);
/* if all the netids in the ignore list are present, ignore this client */
if (daemon->dhcp_ignore)
@@ -496,7 +523,9 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
{
void *rapid_commit = opt6_find(state.packet_options, state.end, OPTION6_RAPID_COMMIT, 0);
int used_config = 0, address_assigned = 0;
/* tags without all prefix-class tags */
struct dhcp_netid *solicit_tags = run_tag_if(state.tags);
if (rapid_commit)
{
o = new_opt6(OPTION6_RAPID_COMMIT);
@@ -511,19 +540,29 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
if (ignore)
return 0;
/* reset USED bits in leases */
lease6_reset();
for (opt = state.packet_options; opt; opt = opt6_next(opt, state.end))
{
void *ia_option, *ia_end;
unsigned int min_time = 0xffffffff;
int t1cntr;
int config_ok = 0;
int ia_counter;
/* 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;
struct dhcp_context *c;
u32 lease_time, requested_time;
struct dhcp_lease *ltmp;
struct in6_addr *req_addr;
struct in6_addr addr;
if (!(ia_option = check_ia(&state, opt, &ia_end)))
#ifdef OPTION6_PREFIX_CLASS
int dump_all_prefix_classes = 0;
#endif
if (!check_ia(&state, opt, &ia_end, &ia_option))
continue;
if (have_config(config, CONFIG_ADDR6))
@@ -539,22 +578,81 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
config_ok = 0; /* configured address leased elsewhere */
}
/* reset USED bits in leases */
lease6_reset();
/* reset USED bits in contexts - one address per prefix per IAID */
for (c = context; c; c = c->current)
c->flags &= ~CONTEXT_USED;
#ifdef OPTION6_PREFIX_CLASS
if (daemon->prefix_classes && state.ia_type == OPTION6_IA_NA)
{
void *prefix_opt, *oro;
int prefix_class;
if ((oro = opt6_find(state.packet_options, state.end, OPTION6_ORO, 0)))
for (i = 0; i < opt6_len(oro) - 1; i += 2)
if (opt6_uint(oro, i, 2) == OPTION6_PREFIX_CLASS)
break;
if (oro && (i < opt6_len(oro) - 1))
{
/* OPTION_PREFIX_CLASS in ORO, send addresses in all prefix classes */
plain_range = 0;
dump_all_prefix_classes = 1;
}
else
{
if ((prefix_opt = opt6_find(opt6_ptr(opt, 12), ia_end, OPTION6_PREFIX_CLASS, 2)))
{
prefix_class = opt6_uint(prefix_opt, 0, 2);
for (p = daemon->prefix_classes; p ; p = p->next)
if (p->class == prefix_class)
break;
if (!p)
my_syslog(MS_DHCP | LOG_WARNING, _("unknown prefix-class %d"), prefix_class);
else
{
/* add tag to list, and exclude undecorated dhcp-ranges */
p->tag.next = state.tags;
solicit_tags = run_tag_if(&p->tag);
plain_range = 0;
state.send_prefix_class = p;
}
}
else
{
/* client didn't ask for a prefix class, lets see if we can find one. */
for (p = daemon->prefix_classes; p ; p = p->next)
{
p->tag.next = NULL;
if (match_netid(&p->tag, solicit_tags, 1))
break;
}
if (p)
{
plain_range = 0;
state.send_prefix_class = p;
}
}
if (p && option_bool(OPT_LOG_OPTS))
my_syslog(MS_DHCP | LOG_INFO, "%u prefix class %d tag:%s", state.xid, p->class, p->tag.net);
}
}
#endif
o = build_ia(&state, &t1cntr);
for (; ia_option; 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);
ltmp = lease6_find_by_addr(req_addr, 128, 0);
requested_time = opt6_uint(ia_option, 16, 4);
/* reset USED bits in contexts - one address per prefix per IAID */
for (c = context; c; c = c->current)
c->flags &= ~CONTEXT_USED;
if ((c = address6_valid(context, req_addr, tagif)))
if ((c = address6_valid(context, req_addr, solicit_tags, plain_range)))
{
lease_time = c->lease_time;
/* If the client asks for an address on the same network as a configured address,
@@ -567,7 +665,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
if (have_config(config, CONFIG_TIME))
lease_time = config->lease_time;
}
else if (!(c = address6_available(context, req_addr, tagif)))
else if (!(c = address6_available(context, req_addr, solicit_tags, plain_range)))
continue; /* not an address we're allowed */
else if (ltmp &&
(ltmp->clid_len != state.clid_len ||
@@ -576,20 +674,30 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
continue; /* address leased elsewhere */
/* add address to output packet */
#ifdef OPTION6_PREFIX_CLASS
if (dump_all_prefix_classes)
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);
mark_context_used(&state, context, req_addr);
get_context_tag(&state, c);
address_assigned = 1;
}
}
/* Suggest configured address */
if (!used_config && config_ok && (c = address6_valid(context, &config->addr6, tagif)))
if (!used_config && config_ok && (c = address6_valid(context, &config->addr6, solicit_tags, plain_range)))
{
used_config = 1;
if (have_config(config, CONFIG_TIME))
lease_time = config->lease_time;
/* add address to output packet */
#ifdef OPTION6_PREFIX_CLASS
if (dump_all_prefix_classes)
state.send_prefix_class = prefix_class_from_context(c);
#endif
add_address(&state, c, lease_time, requested_time, &min_time, &config->addr6, rapid_commit != NULL, now);
mark_context_used(&state, context, &config->addr6);
get_context_tag(&state, c);
address_assigned = 1;
}
@@ -599,18 +707,28 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
while ((ltmp = lease6_find_by_client(ltmp, state.ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, state.clid, state.clid_len, state.iaid)))
{
req_addr = (struct in6_addr *)ltmp->hwaddr;
if ((c = address6_available(context, req_addr, tagif)))
if ((c = address6_available(context, req_addr, solicit_tags, plain_range)))
{
#ifdef OPTION6_PREFIX_CLASS
if (dump_all_prefix_classes)
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);
mark_context_used(&state, context, req_addr);
get_context_tag(&state, c);
address_assigned = 1;
}
}
/* Return addresses for all valid contexts which don't yet have one */
while ((c = address6_allocate(c, state.clid, state.clid_len, state.iaid, tagif, &addr)))
while ((c = address6_allocate(context, state.clid, state.clid_len, state.iaid, ia_counter, solicit_tags, plain_range, &addr)))
{
#ifdef OPTION6_PREFIX_CLASS
if (dump_all_prefix_classes)
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);
mark_context_used(&state, context, &addr);
get_context_tag(&state, c);
address_assigned = 1;
}
@@ -631,6 +749,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);
}
else
{
@@ -639,9 +758,9 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
put_opt6_short(DHCP6NOADDRS);
put_opt6_string("No addresses available");
end_opt6(o1);
log6_packet(&state, "DHCPADVERTISE", NULL, _("No addresses available"));
}
tagif = add_options(&state, fallback, context);
break;
}
@@ -663,8 +782,8 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
unsigned int min_time = 0xffffffff;
int t1cntr;
if (!(ia_option = check_ia(&state, opt, &ia_end)))
continue;
if (!check_ia(&state, opt, &ia_end, &ia_option))
continue;
o = build_ia(&state, &t1cntr);
@@ -675,7 +794,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
struct dhcp_context *dynamic, *c;
unsigned int lease_time;
if ((dynamic = address6_available(context, req_addr, tagif)) || (c = address6_valid(context, req_addr, tagif)))
if ((dynamic = address6_available(context, req_addr, tagif, 1)) || (c = address6_valid(context, req_addr, tagif, 1)))
{
if (!dynamic && !(have_config(config, CONFIG_ADDR6) || !IN6_ARE_ADDR_EQUAL(&config->addr6, req_addr)))
{
@@ -739,6 +858,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
put_opt6_short(DHCP6NOADDRS);
put_opt6_string("No addresses available");
end_opt6(o1);
log6_packet(&state, "DHCPREPLY", NULL, _("No addresses available"));
}
tagif = add_options(&state, fallback, context);
@@ -759,7 +879,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
unsigned int min_time = 0xffffffff;
int t1cntr, iacntr;
if (!(ia_option = check_ia(&state, opt, &ia_end)))
if (!check_ia(&state, opt, &ia_end, &ia_option))
continue;
o = build_ia(&state, &t1cntr);
@@ -798,8 +918,8 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
}
if ((this_context = address6_available(context, req_addr, tagif)) ||
(this_context = address6_valid(context, req_addr, tagif)))
if ((this_context = address6_available(context, req_addr, tagif, 1)) ||
(this_context = address6_valid(context, req_addr, tagif, 1)))
{
get_context_tag(&state, this_context);
@@ -853,13 +973,13 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
{
void *ia_option, *ia_end;
for (ia_option = check_ia(&state, opt, &ia_end);
for (check_ia(&state, opt, &ia_end, &ia_option);
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);
if (!address6_available(context, req_addr, tagif))
if (!address6_available(context, req_addr, tagif, 1))
{
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOTONLINK);
@@ -909,7 +1029,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
void *ia_option, *ia_end;
int made_ia = 0;
for (ia_option = check_ia(&state, opt, &ia_end);
for (check_ia(&state, opt, &ia_end, &ia_option);
ia_option;
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
@@ -971,7 +1091,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
void *ia_option, *ia_end;
int made_ia = 0;
for (ia_option = check_ia(&state, opt, &ia_end);
for (check_ia(&state, opt, &ia_end, &ia_option);
ia_option;
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
@@ -1044,7 +1164,7 @@ 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)
{
void *opt, *oro;
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;
@@ -1255,23 +1375,41 @@ static void get_context_tag(struct state *state, struct dhcp_context *context)
}
}
}
static void *check_ia(struct state *state, void *opt, void **endp)
#ifdef OPTION6_PREFIX_CLASS
static struct prefix_class *prefix_class_from_context(struct dhcp_context *context)
{
struct prefix_class *p;
struct dhcp_netid *t;
for (p = daemon->prefix_classes; p ; p = p->next)
for (t = context->filter; t; t = t->next)
if (strcmp(p->tag.net, t->net) == 0)
return p;
return NULL;
}
#endif
static int check_ia(struct state *state, void *opt, void **endp, void **ia_option)
{
state->ia_type = opt6_type(opt);
*ia_option = NULL;
if (state->ia_type != OPTION6_IA_NA && state->ia_type != OPTION6_IA_TA)
return NULL;
return 0;
if (state->ia_type == OPTION6_IA_NA && opt6_len(opt) < 12)
return NULL;
return 0;
if (state->ia_type == OPTION6_IA_TA && opt6_len(opt) < 4)
return NULL;
return 0;
*endp = opt6_ptr(opt, opt6_len(opt));
state->iaid = opt6_uint(opt, 0, 4);
return opt6_find(opt6_ptr(opt, state->ia_type == OPTION6_IA_NA ? 12 : 4), *endp, OPTION6_IAADDR, 24);
*ia_option = opt6_find(opt6_ptr(opt, state->ia_type == OPTION6_IA_NA ? 12 : 4), *endp, OPTION6_IAADDR, 24);
return 1;
}
@@ -1339,6 +1477,15 @@ static void add_address(struct state *state, struct dhcp_context *context, unsig
put_opt6_long((context->preferred < lease_time) ? context->preferred : lease_time);
put_opt6_long(valid_time); /* valid lifetime */
#ifdef OPTION6_PREFIX_CLASS
if (state->send_prefix_class)
{
int o1 = new_opt6(OPTION6_PREFIX_CLASS);
put_opt6_short(state->send_prefix_class->class);
end_opt6(o1);
}
#endif
end_opt6(o);
if (do_update)
@@ -1365,15 +1512,26 @@ static void add_address(struct state *state, struct dhcp_context *context, unsig
}
}
/* Mark that we have an address for this prefix. */
for (context = state->context; context; context = context->current)
if (is_same_net6(addr, &context->start6, context->prefix))
context->flags |= CONTEXT_USED;
log6_packet(state, do_update ? "DHCPREPLY" : "DHCPADVERTISE", addr, state->hostname);
}
static void mark_context_used(struct state *state, struct dhcp_context *context, struct in6_addr *addr)
{
/* Mark that we have an address for this prefix. */
#ifdef OPTION6_PREFIX_CLASS
for (; context; context = context->current)
if (is_same_net6(addr, &context->start6, context->prefix) &&
(!state->send_prefix_class || state->send_prefix_class == prefix_class_from_context(context)))
context->flags |= CONTEXT_USED;
#else
(void)state; /* warning */
for (; context; context = context->current)
if (is_same_net6(addr, &context->start6, context->prefix))
context->flags |= CONTEXT_USED;
#endif
}
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);
@@ -1502,6 +1660,13 @@ static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_op
optname = "iaaddr";
ia_options = opt6_ptr(opt, 24);
}
#ifdef OPTION6_PREFIX_CLASS
else if (type == OPTION6_PREFIX_CLASS)
{
optname = "prefix-class";
sprintf(daemon->namebuff, "class=%u", opt6_uint(opt, 0, 2));
}
#endif
else if (type == OPTION6_STATUS_CODE)
{
int len = sprintf(daemon->namebuff, "%u ", opt6_uint(opt, 0, 2));