diff --git a/includes/dhcpd.h b/includes/dhcpd.h index 75f6ffe6..fd86ab25 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -1347,6 +1347,8 @@ struct iaaddr { 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 */ /* @@ -1365,6 +1367,7 @@ struct ia_xx { 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 */ }; diff --git a/server/confpars.c b/server/confpars.c index 3a54da05..96e4c4b0 100644 --- a/server/confpars.c +++ b/server/confpars.c @@ -4082,6 +4082,8 @@ parse_ia_na_declaration(struct parse *cfile) { 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; @@ -4129,6 +4131,11 @@ parse_ia_na_declaration(struct parse *cfile) { 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"); @@ -4152,6 +4159,7 @@ parse_ia_na_declaration(struct parse *cfile) { } state = FTS_LAST+1; + prefer = valid = 0; end_time = -1; for (;;) { token = next_token(&val, NULL, cfile); @@ -4202,6 +4210,32 @@ parse_ia_na_declaration(struct parse *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); @@ -4315,6 +4349,8 @@ parse_ia_na_declaration(struct parse *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; @@ -4379,6 +4415,8 @@ parse_ia_ta_declaration(struct parse *cfile) { 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; @@ -4426,6 +4464,11 @@ parse_ia_ta_declaration(struct parse *cfile) { 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"); @@ -4449,6 +4492,7 @@ parse_ia_ta_declaration(struct parse *cfile) { } state = FTS_LAST+1; + prefer = valid = 0; end_time = -1; for (;;) { token = next_token(&val, NULL, cfile); @@ -4499,6 +4543,32 @@ parse_ia_ta_declaration(struct parse *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); @@ -4612,6 +4682,8 @@ parse_ia_ta_declaration(struct parse *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; @@ -4677,6 +4749,8 @@ parse_ia_pd_declaration(struct parse *cfile) { 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; @@ -4724,6 +4798,11 @@ parse_ia_pd_declaration(struct parse *cfile) { 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"); @@ -4747,6 +4826,7 @@ parse_ia_pd_declaration(struct parse *cfile) { } state = FTS_LAST+1; + prefer = valid = 0; end_time = -1; for (;;) { token = next_token(&val, NULL, cfile); @@ -4797,6 +4877,32 @@ parse_ia_pd_declaration(struct parse *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); @@ -4910,6 +5016,8 @@ parse_ia_pd_declaration(struct parse *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; diff --git a/server/db.c b/server/db.c index 29b140d3..42120d31 100644 --- a/server/db.c +++ b/server/db.c @@ -548,6 +548,15 @@ write_ia(const struct ia_xx *ia) { 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; inum_iaaddr; i++) { iaaddr = ia->iaaddr[i]; @@ -570,6 +579,14 @@ write_ia(const struct ia_xx *ia) { 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. diff --git a/server/dhcpleasequery.c b/server/dhcpleasequery.c index 0c4174a6..97fc4e0e 100644 --- a/server/dhcpleasequery.c +++ b/server/dhcpleasequery.c @@ -656,10 +656,6 @@ dhcpleasequery(struct packet *packet, int ms_nulltp) { * * 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. @@ -952,10 +948,9 @@ process_lq_by_address(struct lq6_state *lq) { } 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, @@ -965,7 +960,7 @@ process_lq_by_address(struct lq6_state *lq) { } 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)) { diff --git a/server/dhcpv6.c b/server/dhcpv6.c index 2dad33ed..6fde7584 100644 --- a/server/dhcpv6.c +++ b/server/dhcpv6.c @@ -1827,6 +1827,7 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) { } /* 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); @@ -2441,6 +2442,7 @@ reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) { } /* 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); @@ -2750,6 +2752,10 @@ reply_process_is_addressed(struct reply_state *reply, /* 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 = @@ -3186,6 +3192,7 @@ reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia) { } /* 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); @@ -3698,6 +3705,10 @@ reply_process_is_prefixed(struct reply_state *reply, /* 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 = @@ -4276,6 +4287,7 @@ ia_na_match_decline(const struct data_string *client_id, tmp_addr, sizeof(tmp_addr))); if (lease != NULL) { decline_lease6(lease->ipv6_pool, lease); + lease->ia->cltt = cur_time; write_ia(lease->ia); } } @@ -4692,6 +4704,7 @@ ia_na_match_release(const struct data_string *client_id, 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); } } @@ -4784,6 +4797,7 @@ ia_pd_match_release(const struct data_string *client_id, (unsigned) getUChar(iapref->data + 8)); if (prefix != NULL) { release_lease6(prefix->ipv6_pool, prefix); + prefix->ia->cltt = cur_time; write_ia(prefix->ia); } }