diff --git a/lib/isccfg/duration.c b/lib/isccfg/duration.c index 0a7501b022..27dddca1cc 100644 --- a/lib/isccfg/duration.c +++ b/lib/isccfg/duration.c @@ -28,6 +28,8 @@ #include #include +#include + #include /* @@ -153,3 +155,48 @@ isccfg_duration_fromtext(isc_textregion_t *source, duration->iso8601 = true; return (ISC_R_SUCCESS); } + +isc_result_t +isccfg_parse_duration(isc_textregion_t *source, isccfg_duration_t *duration) { + isc_result_t result; + + REQUIRE(duration != NULL); + + duration->unlimited = false; + result = isccfg_duration_fromtext(source, duration); + if (result == ISC_R_BADNUMBER) { + /* Fallback to dns_ttl_fromtext. */ + uint32_t ttl; + result = dns_ttl_fromtext(source, &ttl); + if (result == ISC_R_SUCCESS) { + /* + * With dns_ttl_fromtext() the information on optional + * units is lost, and is treated as seconds from now on. + */ + duration->iso8601 = false; + duration->parts[6] = ttl; + } + } + + return (result); +} + +uint32_t +isccfg_duration_toseconds(const isccfg_duration_t *duration) { + uint32_t seconds = 0; + + REQUIRE(duration != NULL); + + seconds += duration->parts[6]; /* Seconds */ + seconds += duration->parts[5] * 60; /* Minutes */ + seconds += duration->parts[4] * 3600; /* Hours */ + seconds += duration->parts[3] * 86400; /* Days */ + seconds += duration->parts[2] * 86400 * 7; /* Weeks */ + /* + * The below additions are not entirely correct + * because days may very per month and per year. + */ + seconds += duration->parts[1] * 86400 * 31; /* Months */ + seconds += duration->parts[0] * 86400 * 365; /* Years */ + return (seconds); +} diff --git a/lib/isccfg/include/isccfg/duration.h b/lib/isccfg/include/isccfg/duration.h index 32b23e4342..b64bea520f 100644 --- a/lib/isccfg/include/isccfg/duration.h +++ b/lib/isccfg/include/isccfg/duration.h @@ -55,4 +55,29 @@ isccfg_duration_fromtext(isc_textregion_t *source, isccfg_duration_t *duration); *\li DNS_R_BADNUMBER */ +isc_result_t +isccfg_parse_duration(isc_textregion_t *source, isccfg_duration_t *duration); +/*%< + * Converts a duration string to a ISO 8601 duration. + * If the string does not start with a P (or p), fall back to TTL-style value. + * In that case the duration will be treated in seconds only. + * + * Returns: + *\li ISC_R_SUCCESS + *\li DNS_R_BADNUMBER + *\li DNS_R_BADTTL + */ + +uint32_t +isccfg_duration_toseconds(const isccfg_duration_t *duration); +/*%< + * Converts an ISO 8601 duration to seconds. + * The conversion is approximate: + * - Months will be treated as 31 days. + * - Years will be treated as 365 days. + * + * Returns: + *\li The duration in seconds. + */ + ISC_LANG_ENDDECLS diff --git a/lib/isccfg/kaspconf.c b/lib/isccfg/kaspconf.c index 7c476b1a68..a0460ff968 100644 --- a/lib/isccfg/kaspconf.c +++ b/lib/isccfg/kaspconf.c @@ -65,20 +65,9 @@ parse_duration(const char *str) { DE_CONST(str, tr.base); tr.length = strlen(tr.base); - result = isccfg_duration_fromtext(&tr, &duration); - if (result == ISC_R_BADNUMBER) { - /* Fallback to dns_ttl_fromtext. */ - (void)dns_ttl_fromtext(&tr, &time); - return (time); - } + result = isccfg_parse_duration(&tr, &duration); if (result == ISC_R_SUCCESS) { - time += duration.parts[6]; /* Seconds */ - time += duration.parts[5] * 60; /* Minutes */ - time += duration.parts[4] * 3600; /* Hours */ - time += duration.parts[3] * 86400; /* Days */ - time += duration.parts[2] * 86400 * 7; /* Weaks */ - time += duration.parts[1] * 86400 * 31; /* Months */ - time += duration.parts[0] * 86400 * 365; /* Years */ + time = isccfg_duration_toseconds(&duration); } return (time); } diff --git a/lib/isccfg/parser.c b/lib/isccfg/parser.c index db2a328c2a..4ea849e64f 100644 --- a/lib/isccfg/parser.c +++ b/lib/isccfg/parser.c @@ -1139,19 +1139,7 @@ cfg_obj_isduration(const cfg_obj_t *obj) { uint32_t cfg_obj_asduration(const cfg_obj_t *obj) { REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_duration); - uint32_t duration = 0; - duration += obj->value.duration.parts[6]; /* Seconds */ - duration += obj->value.duration.parts[5] * 60; /* Minutes */ - duration += obj->value.duration.parts[4] * 3600; /* Hours */ - duration += obj->value.duration.parts[3] * 86400; /* Days */ - duration += obj->value.duration.parts[2] * 86400 * 7; /* Weaks */ - /* - * The below additions are not entirely correct - * because days may very per month and per year. - */ - duration += obj->value.duration.parts[1] * 86400 * 31; /* Months */ - duration += obj->value.duration.parts[0] * 86400 * 365; /* Years */ - return (duration); + return isccfg_duration_toseconds(&(obj->value.duration)); } static isc_result_t @@ -1160,24 +1148,9 @@ parse_duration(cfg_parser_t *pctx, cfg_obj_t **ret) { cfg_obj_t *obj = NULL; isccfg_duration_t duration; - duration.unlimited = false; - - result = isccfg_duration_fromtext(&pctx->token.value.as_textregion, + result = isccfg_parse_duration(&pctx->token.value.as_textregion, &duration); - if (result == ISC_R_BADNUMBER) { - /* Fallback to dns_ttl_fromtext. */ - uint32_t ttl; - result = dns_ttl_fromtext(&pctx->token.value.as_textregion, - &ttl); - if (result == ISC_R_SUCCESS) { - /* - * With dns_ttl_fromtext() the information on optional - * units is lost, and is treated as seconds from now on. - */ - duration.iso8601 = false; - duration.parts[6] = ttl; - } - } + if (result == ISC_R_RANGE) { cfg_parser_error(pctx, CFG_LOG_NEAR, "duration or TTL out of range");