struct binding_scope *scope; /* "set var = value;" */
time_t hard_lifetime_end_time; /* time address expires */
time_t soft_lifetime_end_time; /* time ephemeral expires */
+ u_int32_t prefer; /* cached preferred lifetime */
+ u_int32_t valid; /* cached valid lifetime */
struct ia_xx *ia; /* IA for this lease */
struct ipv6_pool *ipv6_pool; /* pool for this lease */
/*
u_int16_t ia_type; /* IA_XX */
int num_iaaddr; /* number of IAADDR for this IA */
int max_iaaddr; /* space available for IAADDR */
+ time_t cltt; /* client last transaction time */
struct iaaddr **iaaddr; /* pointers to the various IAADDRs */
};
u_int32_t iaid;
struct iaddr iaddr;
binding_state_t state;
+ u_int32_t prefer;
+ u_int32_t valid;
TIME end_time;
struct iaaddr *iaaddr;
struct ipv6_pool *pool;
token = next_token(&val, NULL, cfile);
if (token == RBRACE) break;
+ if (token == CLTT) {
+ ia->cltt = parse_date (cfile);
+ continue;
+ }
+
if (token != IAADDR) {
parse_warn(cfile, "corrupt lease file; "
"expecting IAADDR or right brace");
}
state = FTS_LAST+1;
+ prefer = valid = 0;
end_time = -1;
for (;;) {
token = next_token(&val, NULL, cfile);
}
break;
+ /* Lease preferred lifetime. */
+ case PREFERRED_LIFE:
+ token = next_token(&val, NULL, cfile);
+ if (token != NUMBER) {
+ parse_warn(cfile, "%s is not a valid "
+ "preferred time",
+ val);
+ skip_to_semi(cfile);
+ continue;
+ }
+ prefer = atoi (val);
+ break;
+
+ /* Lease valid lifetime. */
+ case MAX_LIFE:
+ token = next_token(&val, NULL, cfile);
+ if (token != NUMBER) {
+ parse_warn(cfile, "%s is not a valid "
+ "max time",
+ val);
+ skip_to_semi(cfile);
+ continue;
+ }
+ valid = atoi (val);
+ break;
+
/* Lease expiration time. */
case ENDS:
end_time = parse_date(cfile);
memcpy(&iaaddr->addr, iaddr.iabuf, sizeof(iaaddr->addr));
iaaddr->plen = 0;
iaaddr->state = state;
+ iaaddr->prefer = prefer;
+ iaaddr->valid = valid;
if (iaaddr->state == FTS_RELEASED)
iaaddr->hard_lifetime_end_time = end_time;
u_int32_t iaid;
struct iaddr iaddr;
binding_state_t state;
+ u_int32_t prefer;
+ u_int32_t valid;
TIME end_time;
struct iaaddr *iaaddr;
struct ipv6_pool *pool;
token = next_token(&val, NULL, cfile);
if (token == RBRACE) break;
+ if (token == CLTT) {
+ ia->cltt = parse_date (cfile);
+ continue;
+ }
+
if (token != IAADDR) {
parse_warn(cfile, "corrupt lease file; "
"expecting IAADDR or right brace");
}
state = FTS_LAST+1;
+ prefer = valid = 0;
end_time = -1;
for (;;) {
token = next_token(&val, NULL, cfile);
}
break;
+ /* Lease preferred lifetime. */
+ case PREFERRED_LIFE:
+ token = next_token(&val, NULL, cfile);
+ if (token != NUMBER) {
+ parse_warn(cfile, "%s is not a valid "
+ "preferred time",
+ val);
+ skip_to_semi(cfile);
+ continue;
+ }
+ prefer = atoi (val);
+ break;
+
+ /* Lease valid lifetime. */
+ case MAX_LIFE:
+ token = next_token(&val, NULL, cfile);
+ if (token != NUMBER) {
+ parse_warn(cfile, "%s is not a valid "
+ "max time",
+ val);
+ skip_to_semi(cfile);
+ continue;
+ }
+ valid = atoi (val);
+ break;
+
/* Lease expiration time. */
case ENDS:
end_time = parse_date(cfile);
memcpy(&iaaddr->addr, iaddr.iabuf, sizeof(iaaddr->addr));
iaaddr->plen = 0;
iaaddr->state = state;
+ iaaddr->prefer = prefer;
+ iaaddr->valid = valid;
if (iaaddr->state == FTS_RELEASED)
iaaddr->hard_lifetime_end_time = end_time;
struct iaddr iaddr;
u_int8_t plen;
binding_state_t state;
+ u_int32_t prefer;
+ u_int32_t valid;
TIME end_time;
struct iaaddr *iapref;
struct ipv6_pool *pool;
token = next_token(&val, NULL, cfile);
if (token == RBRACE) break;
+ if (token == CLTT) {
+ ia->cltt = parse_date (cfile);
+ continue;
+ }
+
if (token != IAPREFIX) {
parse_warn(cfile, "corrupt lease file; expecting "
"IAPREFIX or right brace");
}
state = FTS_LAST+1;
+ prefer = valid = 0;
end_time = -1;
for (;;) {
token = next_token(&val, NULL, cfile);
}
break;
+ /* Lease preferred lifetime. */
+ case PREFERRED_LIFE:
+ token = next_token(&val, NULL, cfile);
+ if (token != NUMBER) {
+ parse_warn(cfile, "%s is not a valid "
+ "preferred time",
+ val);
+ skip_to_semi(cfile);
+ continue;
+ }
+ prefer = atoi (val);
+ break;
+
+ /* Lease valid lifetime. */
+ case MAX_LIFE:
+ token = next_token(&val, NULL, cfile);
+ if (token != NUMBER) {
+ parse_warn(cfile, "%s is not a valid "
+ "max time",
+ val);
+ skip_to_semi(cfile);
+ continue;
+ }
+ valid = atoi (val);
+ break;
+
/* Prefix expiration time. */
case ENDS:
end_time = parse_date(cfile);
memcpy(&iapref->addr, iaddr.iabuf, sizeof(iapref->addr));
iapref->plen = plen;
iapref->state = state;
+ iapref->prefer = prefer;
+ iapref->valid = valid;
if (iapref->state == FTS_RELEASED)
iapref->hard_lifetime_end_time = end_time;
if (fprintf_ret < 0) {
goto error_exit;
}
+ if (ia->cltt != MIN_TIME) {
+ tval = print_time(ia->cltt);
+ if (tval == NULL) {
+ goto error_exit;
+ }
+ if (fprintf(db_file, " cltt %s\n", tval) < 0) {
+ goto error_exit;
+ }
+ }
for (i=0; i<ia->num_iaaddr; i++) {
iaaddr = ia->iaaddr[i];
binding_state) < 0) {
goto error_exit;
}
+ if (fprintf(db_file, " preferred-life %u\n",
+ (unsigned)iaaddr->prefer) < 0) {
+ goto error_exit;
+ }
+ if (fprintf(db_file, " max-life %u\n",
+ (unsigned)iaaddr->valid) < 0) {
+ goto error_exit;
+ }
/* Note that from here on out, the \n is prepended to the
* next write, rather than appended to the current write.
*
* TODO: RFC5007 ORO in query-options.
*
- * TODO: RFC5007 not default preferred and valid time.
- *
- * TODO: RFC5007 not zero Client Last Transaction Time (clt-time).
- *
* TODO: RFC5007 lq-relay-data.
*
* TODO: RFC5007 lq-client-link.
}
data.data = data.buffer->data;
memcpy(data.buffer->data, &iaaddr->addr, 16);
- lifetime = DEFAULT_DEFAULT_LEASE_TIME;
- lifetime = (lifetime / 2) + (lifetime / 8);
+ lifetime = iaaddr->prefer;
putULong(data.buffer->data + 16, lifetime);
- lifetime = DEFAULT_DEFAULT_LEASE_TIME;
+ lifetime = iaaddr->valid;
putULong(data.buffer->data + 20, lifetime);
if (!save_option_buffer(&dhcpv6_universe, opt_state,
NULL, (unsigned char *)data.data, data.len,
}
data_string_forget(&data, MDL);
- lifetime = 0;
+ lifetime = htonl(iaaddr->ia->cltt);
if (!save_option_buffer(&dhcpv6_universe, opt_state,
NULL, (unsigned char *)&lifetime, 4,
D6O_CLT_TIME, 0)) {
}
/* Put new ia into the hash. */
+ reply->ia->cltt = cur_time;
ia_id = &reply->ia->iaid_duid;
ia_hash_add(ia_na_active, (unsigned char *)ia_id->data,
ia_id->len, reply->ia, MDL);
}
/* Put new ia into the hash. */
+ reply->ia->cltt = cur_time;
ia_id = &reply->ia->iaid_duid;
ia_hash_add(ia_ta_active, (unsigned char *)ia_id->data,
ia_id->len, reply->ia, MDL);
/* Perform dynamic lease related update work. */
if (reply->lease != NULL) {
+ /* Cached lifetimes */
+ reply->lease->prefer = reply->send_prefer;
+ reply->lease->valid = reply->send_valid;
+
/* Advance (or rewind) the valid lifetime. */
if (reply->buf.reply.msg_type == DHCPV6_REPLY) {
reply->lease->soft_lifetime_end_time =
}
/* Put new ia into the hash. */
+ reply->ia->cltt = cur_time;
ia_id = &reply->ia->iaid_duid;
ia_hash_add(ia_pd_active, (unsigned char *)ia_id->data,
ia_id->len, reply->ia, MDL);
/* Perform dynamic prefix related update work. */
if (reply->lease != NULL) {
+ /* Cached lifetimes */
+ reply->lease->prefer = reply->send_prefer;
+ reply->lease->valid = reply->send_valid;
+
/* Advance (or rewind) the valid lifetime. */
if (reply->buf.reply.msg_type == DHCPV6_REPLY) {
reply->lease->soft_lifetime_end_time =
tmp_addr, sizeof(tmp_addr)));
if (lease != NULL) {
decline_lease6(lease->ipv6_pool, lease);
+ lease->ia->cltt = cur_time;
write_ia(lease->ia);
}
}
inet_ntop(AF_INET6, iaaddr->data, tmp_addr, sizeof(tmp_addr)));
if (lease != NULL) {
release_lease6(lease->ipv6_pool, lease);
+ lease->ia->cltt = cur_time;
write_ia(lease->ia);
}
}
(unsigned) getUChar(iapref->data + 8));
if (prefix != NULL) {
release_lease6(prefix->ipv6_pool, prefix);
+ prefix->ia->cltt = cur_time;
write_ia(prefix->ia);
}
}