2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 14:35:26 +00:00

Allow for key lifetime unlimited

The keyword 'unlimited' can be used instead of PT0S which means the
same but is more comprehensible for users.

Also fix some redundant "none" parameters in the kasp test.
This commit is contained in:
Matthijs Mekking
2020-02-06 15:41:47 +01:00
committed by Evan Hunt
parent 9dc630016e
commit 2733edb2a6
17 changed files with 194 additions and 63 deletions

View File

@@ -115,7 +115,7 @@ dlz <replaceable>string</replaceable> {
<literallayout class="normal"> <literallayout class="normal">
dnssec-policy <replaceable>string</replaceable> { dnssec-policy <replaceable>string</replaceable> {
dnskey-ttl <replaceable>duration</replaceable>; dnskey-ttl <replaceable>duration</replaceable>;
keys { ( csk | ksk | zsk ) ( key-directory ) lifetime <replaceable>duration</replaceable> keys { ( csk | ksk | zsk ) ( key-directory ) lifetime ( <replaceable>duration</replaceable> | unlimited )
algorithm <replaceable>integer</replaceable> [ <replaceable>integer</replaceable> ]; ... }; algorithm <replaceable>integer</replaceable> [ <replaceable>integer</replaceable> ]; ... };
max-zone-ttl <replaceable>duration</replaceable>; max-zone-ttl <replaceable>duration</replaceable>;
parent-ds-ttl <replaceable>duration</replaceable>; parent-ds-ttl <replaceable>duration</replaceable>;

View File

@@ -19,7 +19,7 @@ dnssec-policy "test" {
keys { keys {
ksk key-directory lifetime P1Y algorithm 13 256; ksk key-directory lifetime P1Y algorithm 13 256;
zsk key-directory lifetime P30D algorithm 13; zsk key-directory lifetime P30D algorithm 13;
csk key-directory lifetime P30D algorithm 8 2048; csk key-directory lifetime unlimited algorithm 8 2048;
}; };
max-zone-ttl 86400; max-zone-ttl 86400;
parent-ds-ttl 7200; parent-ds-ttl 7200;

View File

@@ -45,6 +45,13 @@ zone "default.kasp" {
dnssec-policy "default"; dnssec-policy "default";
}; };
/* Key lifetime unlimited. */
zone "unlimited.kasp" {
type master;
file "unlimited.kasp.db";
dnssec-policy "unlimited";
};
/* A master zone with dnssec-policy, no keys created. */ /* A master zone with dnssec-policy, no keys created. */
zone "rsasha1.kasp" { zone "rsasha1.kasp" {
type master; type master;

View File

@@ -9,6 +9,14 @@
* information regarding copyright ownership. * information regarding copyright ownership.
*/ */
dnssec-policy "unlimited" {
dnskey-ttl 1234;
keys {
csk key-directory lifetime unlimited algorithm 13;
};
};
dnssec-policy "rsasha1" { dnssec-policy "rsasha1" {
dnskey-ttl 1234; dnskey-ttl 1234;

View File

@@ -43,7 +43,8 @@ U="UNRETENTIVE"
# Set up zones that will be initially signed. # Set up zones that will be initially signed.
# #
for zn in default rsasha1 dnssec-keygen some-keys legacy-keys pregenerated \ for zn in default rsasha1 dnssec-keygen some-keys legacy-keys pregenerated \
rumoured rsasha1-nsec3 rsasha256 rsasha512 ecdsa256 ecdsa384 inherit rumoured rsasha1-nsec3 rsasha256 rsasha512 ecdsa256 ecdsa384 \
inherit unlimited
do do
setup "${zn}.kasp" setup "${zn}.kasp"
cp template.db.in "$zonefile" cp template.db.in "$zonefile"

View File

@@ -1026,6 +1026,22 @@ check_keys
check_apex check_apex
check_subdomain check_subdomain
#
# Zone: unlimited.kasp.
#
zone_properties "ns3" "unlimited.kasp" "unlimited" "1234" "1" "10.53.0.3"
key_properties "KEY1" "csk" "0" "13" "ECDSAP256SHA256" "256" "yes" "yes"
key_clear "KEY2"
key_clear "KEY3"
# The first key is immediately published and activated.
key_timings "KEY1" "published" "active" "none" "none" "none"
# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait.
key_states "KEY1" "omnipresent" "rumoured" "rumoured" "rumoured" "hidden"
check_keys
check_apex
check_subdomain
dnssec_verify
# #
# Zone: inherit.kasp. # Zone: inherit.kasp.
# #
@@ -1451,7 +1467,7 @@ check_subdomain
# ns5/override.inherit.signed # ns5/override.inherit.signed
# ns5/inherit.override.signed # ns5/inherit.override.signed
key_properties "KEY1" "csk" "0" "13" "ECDSAP256SHA256" "256" "yes" "yes" key_properties "KEY1" "csk" "0" "13" "ECDSAP256SHA256" "256" "yes" "yes"
key_timings "KEY1" "published" "active" "none" "none" "none" "none" key_timings "KEY1" "published" "active" "none" "none" "none"
key_states "KEY1" "omnipresent" "rumoured" "rumoured" "rumoured" "hidden" key_states "KEY1" "omnipresent" "rumoured" "rumoured" "rumoured" "hidden"
zone_properties "ns2" "signed.tld" "default" "3600" "1" "10.53.0.2" zone_properties "ns2" "signed.tld" "default" "3600" "1" "10.53.0.2"
@@ -1496,7 +1512,7 @@ dnssec_verify
# ns5/override.override.unsigned # ns5/override.override.unsigned
# ns5/override.none.unsigned # ns5/override.none.unsigned
key_properties "KEY1" "csk" "0" "14" "ECDSAP384SHA384" "384" "yes" "yes" key_properties "KEY1" "csk" "0" "14" "ECDSAP384SHA384" "384" "yes" "yes"
key_timings "KEY1" "published" "active" "none" "none" "none" "none" key_timings "KEY1" "published" "active" "none" "none" "none"
key_states "KEY1" "omnipresent" "rumoured" "rumoured" "rumoured" "hidden" key_states "KEY1" "omnipresent" "rumoured" "rumoured" "rumoured" "hidden"
zone_properties "ns4" "inherit.inherit.signed" "test" "3600" "1" "10.53.0.4" zone_properties "ns4" "inherit.inherit.signed" "test" "3600" "1" "10.53.0.4"

View File

@@ -11113,7 +11113,7 @@ example.com CNAME rpz-tcp-only.
</para> </para>
<programlisting>keys { <programlisting>keys {
ksk key-directory lifetime P5Y algorithm 8 2048; ksk key-directory lifetime unlimited algorithm 8 2048;
zsk key-directory lifetime P30D algorithm 8; zsk key-directory lifetime P30D algorithm 8;
csk key-directory lifetime P6MT12H3M15S algorithm 13; csk key-directory lifetime P6MT12H3M15S algorithm 13;
}; };
@@ -11133,16 +11133,27 @@ example.com CNAME rpz-tcp-only.
<command>key-directory</command>. <command>key-directory</command>.
</para> </para>
<para> <para>
The third token tells how long the key may be used. In the The <command>lifetime</command> parameter specifies how
example the first key has a lifetime of 5 years, the second long a key may be used before rolling over. In the
key may be used for 30 days and the third key has a rather example above, the first key will have an unlimited
peculiar lifetime of 6 months, 12 hours, 3 minutes and 15 lifetime, the second key may be used for 30 days, and the
seconds. third key has a rather peculiar lifetime of 6 months,
12 hours, 3 minutes and 15 seconds. A lifetime of 0
seconds is the same as <command>unlimited</command>.
</para> </para>
<para> <para>
The last token(s) are the key's algorithm and algorithm Note that the lifetime of a key may be extended if
length. The length may be omitted as shown in the retiring it too soon would cause validation failures:
example for the second and third key. for example, if the key were configured to roll more
frequently than its TTL, its lifetime would
automatically be extended to account for this.
</para>
<para>
The <command>algorithm</command> parameter(s) are the key's
algorithm, expressed numerically, and its size in bits. The
size may be omitted, as shown in the example for the
second and third keys; in this case an appropriate
default size will be used.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@@ -14,7 +14,7 @@
<programlisting> <programlisting>
<command>dnssec-policy</command> <replaceable>string</replaceable> { <command>dnssec-policy</command> <replaceable>string</replaceable> {
<command>dnskey-ttl</command> <replaceable>duration</replaceable>; <command>dnskey-ttl</command> <replaceable>duration</replaceable>;
<command>keys</command> { ( csk | ksk | zsk ) key-directory lifetime <replaceable>duration</replaceable> algorithm <replaceable>integer</replaceable> [ <replaceable>integer</replaceable> ] ; ... }; <command>keys</command> { ( csk | ksk | zsk ) key-directory lifetime ( <replaceable>duration</replaceable> | unlimited ) algorithm <replaceable>integer</replaceable> [ <replaceable>integer</replaceable> ] ; ... };
<command>max-zone-ttl</command> <replaceable>duration</replaceable>; <command>max-zone-ttl</command> <replaceable>duration</replaceable>;
<command>parent-ds-ttl</command> <replaceable>duration</replaceable>; <command>parent-ds-ttl</command> <replaceable>duration</replaceable>;
<command>parent-propagation-delay</command> <replaceable>duration</replaceable>; <command>parent-propagation-delay</command> <replaceable>duration</replaceable>;

View File

@@ -199,9 +199,9 @@ is referred to as a CSK. Below is an example configuration for the three types
of keys: of keys:
``` ```
keys { keys {
ksk key-directory lifetime P5Y algorithm ECDSAP256SHA256; ksk key-directory lifetime unlimited algorithm ECDSAP256SHA256;
zsk key-directory lifetime P30D algorithm ECDSAP256SHA256; zsk key-directory lifetime P30D algorithm ECDSAP256SHA256;
csk key-directory lifetime PT0S algorithm 8 2048; csk key-directory lifetime P5Y algorithm 8 2048;
}; };
``` ```

View File

@@ -2,7 +2,7 @@ dnssec-policy "default" {
// Keys // Keys
keys { keys {
csk key-directory lifetime 0 algorithm 13; csk key-directory lifetime unlimited algorithm 13;
}; };
// Key timings // Key timings

View File

@@ -23,7 +23,7 @@ dlz <string> {
dnssec-policy <string> { dnssec-policy <string> {
dnskey-ttl <duration>; dnskey-ttl <duration>;
keys { ( csk | ksk | zsk ) ( key-directory ) lifetime <duration> keys { ( csk | ksk | zsk ) ( key-directory ) lifetime ( <duration> | unlimited )
algorithm <integer> [ <integer> ]; ... }; algorithm <integer> [ <integer> ]; ... };
max-zone-ttl <duration>; max-zone-ttl <duration>;
parent-ds-ttl <duration>; parent-ds-ttl <duration>;

View File

@@ -23,7 +23,7 @@ dlz <string> {
dnssec-policy <string> { dnssec-policy <string> {
dnskey-ttl <duration>; dnskey-ttl <duration>;
keys { ( csk | ksk | zsk ) ( key-directory ) lifetime <duration> keys { ( csk | ksk | zsk ) ( key-directory ) lifetime ( <duration> | unlimited )
algorithm <integer> [ <integer> ]; ... }; algorithm <integer> [ <integer> ]; ... };
max-zone-ttl <duration>; max-zone-ttl <duration>;
parent-ds-ttl <duration>; parent-ds-ttl <duration>;

View File

@@ -173,6 +173,7 @@ struct cfg_duration {
*/ */
uint32_t parts[7]; uint32_t parts[7];
bool iso8601; bool iso8601;
bool unlimited;
}; };
/*% /*%
@@ -344,6 +345,7 @@ LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_unsupported;
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_fixedpoint; LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_fixedpoint;
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_percentage; LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_percentage;
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_duration; LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_duration;
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_duration_or_unlimited;
/*@}*/ /*@}*/
isc_result_t isc_result_t
@@ -535,6 +537,13 @@ cfg_parse_duration(cfg_parser_t *pctx, const cfg_type_t *type,
void void
cfg_print_duration(cfg_printer_t *pctx, const cfg_obj_t *obj); cfg_print_duration(cfg_printer_t *pctx, const cfg_obj_t *obj);
isc_result_t
cfg_parse_duration_or_unlimited(cfg_parser_t *pctx, const cfg_type_t *type,
cfg_obj_t **ret);
void
cfg_print_duration_or_unlimited(cfg_printer_t *pctx, const cfg_obj_t *obj);
isc_result_t isc_result_t
cfg_parse_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); cfg_parse_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);

View File

@@ -78,7 +78,7 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t* kasp)
if (config == NULL) { if (config == NULL) {
/* We are creating a key reference for the default kasp. */ /* We are creating a key reference for the default kasp. */
key->role |= DNS_KASP_KEY_ROLE_KSK | DNS_KASP_KEY_ROLE_ZSK; key->role |= DNS_KASP_KEY_ROLE_KSK | DNS_KASP_KEY_ROLE_ZSK;
key->lifetime = 0; key->lifetime = 0; /* unlimited */
key->algorithm = DNS_KEYALG_ECDSA256; key->algorithm = DNS_KEYALG_ECDSA256;
key->length = -1; key->length = -1;
} else { } else {
@@ -94,10 +94,16 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t* kasp)
key->role |= DNS_KASP_KEY_ROLE_KSK; key->role |= DNS_KASP_KEY_ROLE_KSK;
key->role |= DNS_KASP_KEY_ROLE_ZSK; key->role |= DNS_KASP_KEY_ROLE_ZSK;
} }
key->lifetime = cfg_obj_asduration(
cfg_tuple_get(config, "lifetime")); key->lifetime = 0; /* unlimited */
key->algorithm = cfg_obj_asuint32( obj = cfg_tuple_get(config, "lifetime");
cfg_tuple_get(config, "algorithm")); if (cfg_obj_isduration(obj)) {
key->lifetime = cfg_obj_asduration(obj);
}
obj = cfg_tuple_get(config, "algorithm");
key->algorithm = cfg_obj_asuint32(obj);
obj = cfg_tuple_get(config, "length"); obj = cfg_tuple_get(config, "length");
if (cfg_obj_isuint32(obj)) { if (cfg_obj_isuint32(obj)) {
key->length = cfg_obj_asuint32(obj); key->length = cfg_obj_asuint32(obj);

View File

@@ -96,7 +96,7 @@ static cfg_type_t cfg_type_logseverity;
static cfg_type_t cfg_type_logsuffix; static cfg_type_t cfg_type_logsuffix;
static cfg_type_t cfg_type_logversions; static cfg_type_t cfg_type_logversions;
static cfg_type_t cfg_type_masterselement; static cfg_type_t cfg_type_masterselement;
static cfg_type_t cfg_type_maxttl; static cfg_type_t cfg_type_maxduration;
static cfg_type_t cfg_type_minimal; static cfg_type_t cfg_type_minimal;
static cfg_type_t cfg_type_nameportiplist; static cfg_type_t cfg_type_nameportiplist;
static cfg_type_t cfg_type_notifytype; static cfg_type_t cfg_type_notifytype;
@@ -439,6 +439,24 @@ static cfg_type_t cfg_type_category = {
&cfg_rep_tuple, category_fields &cfg_rep_tuple, category_fields
}; };
static isc_result_t
parse_maxduration(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
return (cfg_parse_enum_or_other(pctx, type, &cfg_type_duration, ret));
}
static void
doc_maxduration(cfg_printer_t *pctx, const cfg_type_t *type) {
cfg_doc_enum_or_other(pctx, type, &cfg_type_duration);
}
/*%
* A duration or "unlimited", but not "default".
*/
static const char *maxduration_enums[] = { "unlimited", NULL };
static cfg_type_t cfg_type_maxduration = {
"maxduration_no_default", parse_maxduration, cfg_print_ustring,
doc_maxduration, &cfg_rep_duration, maxduration_enums
};
/*% /*%
* A dnssec key, as used in the "trusted-keys" statement. * A dnssec key, as used in the "trusted-keys" statement.
@@ -509,7 +527,8 @@ static cfg_type_t cfg_type_algorithm = {
doc_keyvalue, &cfg_rep_uint32, &algorithm_kw doc_keyvalue, &cfg_rep_uint32, &algorithm_kw
}; };
static keyword_type_t lifetime_kw = { "lifetime", &cfg_type_duration }; static keyword_type_t lifetime_kw = { "lifetime",
&cfg_type_duration_or_unlimited };
static cfg_type_t cfg_type_lifetime = { static cfg_type_t cfg_type_lifetime = {
"lifetime", parse_keyvalue, print_keyvalue, "lifetime", parse_keyvalue, print_keyvalue,
doc_keyvalue, &cfg_rep_duration, &lifetime_kw doc_keyvalue, &cfg_rep_duration, &lifetime_kw
@@ -2227,7 +2246,7 @@ zone_clauses[] = {
{ "max-transfer-time-out", &cfg_type_uint32, { "max-transfer-time-out", &cfg_type_uint32,
CFG_ZONE_MASTER | CFG_ZONE_MIRROR | CFG_ZONE_SLAVE CFG_ZONE_MASTER | CFG_ZONE_MIRROR | CFG_ZONE_SLAVE
}, },
{ "max-zone-ttl", &cfg_type_maxttl, { "max-zone-ttl", &cfg_type_maxduration,
CFG_ZONE_MASTER | CFG_ZONE_REDIRECT CFG_ZONE_MASTER | CFG_ZONE_REDIRECT
}, },
{ "min-refresh-time", &cfg_type_uint32, { "min-refresh-time", &cfg_type_uint32,
@@ -3867,25 +3886,6 @@ static cfg_type_t cfg_type_masterselement = {
doc_masterselement, NULL, NULL doc_masterselement, NULL, NULL
}; };
static isc_result_t
parse_maxttl(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
return (cfg_parse_enum_or_other(pctx, type, &cfg_type_duration, ret));
}
static void
doc_maxttl(cfg_printer_t *pctx, const cfg_type_t *type) {
cfg_doc_enum_or_other(pctx, type, &cfg_type_duration);
}
/*%
* A size or "unlimited", but not "default".
*/
static const char *maxttl_enums[] = { "unlimited", NULL };
static cfg_type_t cfg_type_maxttl = {
"maxttl_no_default", parse_maxttl, cfg_print_ustring, doc_maxttl,
&cfg_rep_string, maxttl_enums
};
static int cmp_clause(const void *ap, const void *bp) { static int cmp_clause(const void *ap, const void *bp) {
const cfg_clausedef_t *a = (const cfg_clausedef_t *)ap; const cfg_clausedef_t *a = (const cfg_clausedef_t *)ap;
const cfg_clausedef_t *b = (const cfg_clausedef_t *)bp; const cfg_clausedef_t *b = (const cfg_clausedef_t *)bp;

View File

@@ -1088,6 +1088,22 @@ cfg_print_duration(cfg_printer_t *pctx, const cfg_obj_t *obj) {
cfg_print_chars(pctx, buf, strlen(buf)); cfg_print_chars(pctx, buf, strlen(buf));
} }
void
cfg_print_duration_or_unlimited(cfg_printer_t *pctx, const cfg_obj_t *obj) {
cfg_duration_t duration;
REQUIRE(pctx != NULL);
REQUIRE(obj != NULL);
duration = obj->value.duration;
if (duration.unlimited) {
cfg_print_cstr(pctx, "unlimited");
} else {
cfg_print_duration(pctx, obj);
}
}
bool bool
cfg_obj_isduration(const cfg_obj_t *obj) { cfg_obj_isduration(const cfg_obj_t *obj) {
REQUIRE(obj != NULL); REQUIRE(obj != NULL);
@@ -1250,21 +1266,14 @@ duration_fromtext(isc_textregion_t *source, cfg_duration_t *duration) {
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
isc_result_t static isc_result_t
cfg_parse_duration(cfg_parser_t *pctx, const cfg_type_t *type, cfg__parse_duration(cfg_parser_t *pctx, cfg_obj_t **ret)
cfg_obj_t **ret)
{ {
isc_result_t result; isc_result_t result;
cfg_obj_t *obj = NULL; cfg_obj_t *obj = NULL;
cfg_duration_t duration; cfg_duration_t duration;
UNUSED(type); duration.unlimited = false;
CHECK(cfg_gettoken(pctx, 0));
if (pctx->token.type != isc_tokentype_string) {
result = ISC_R_UNEXPECTEDTOKEN;
goto cleanup;
}
if (TOKEN_STRING(pctx)[0] == 'P') { if (TOKEN_STRING(pctx)[0] == 'P') {
result = duration_fromtext(&pctx->token.value.as_textregion, result = duration_fromtext(&pctx->token.value.as_textregion,
@@ -1278,12 +1287,9 @@ cfg_parse_duration(cfg_parser_t *pctx, const cfg_type_t *type,
* With dns_ttl_fromtext() the information on optional units. * With dns_ttl_fromtext() the information on optional units.
* is lost, and is treated as seconds from now on. * is lost, and is treated as seconds from now on.
*/ */
duration.parts[0] = 0; for (int i = 0; i < 6; i++) {
duration.parts[1] = 0; duration.parts[i] = 0;
duration.parts[2] = 0; }
duration.parts[3] = 0;
duration.parts[4] = 0;
duration.parts[5] = 0;
duration.parts[6] = ttl; duration.parts[6] = ttl;
duration.iso8601 = false; duration.iso8601 = false;
} }
@@ -1305,6 +1311,66 @@ cleanup:
return (result); return (result);
} }
isc_result_t
cfg_parse_duration(cfg_parser_t *pctx, const cfg_type_t *type,
cfg_obj_t **ret)
{
isc_result_t result;
UNUSED(type);
CHECK(cfg_gettoken(pctx, 0));
if (pctx->token.type != isc_tokentype_string) {
result = ISC_R_UNEXPECTEDTOKEN;
goto cleanup;
}
return cfg__parse_duration(pctx, ret);
cleanup:
cfg_parser_error(pctx, CFG_LOG_NEAR,
"expected ISO 8601 duration or TTL value");
return (result);
}
isc_result_t
cfg_parse_duration_or_unlimited(cfg_parser_t *pctx, const cfg_type_t *type,
cfg_obj_t **ret)
{
isc_result_t result;
cfg_obj_t *obj = NULL;
cfg_duration_t duration;
UNUSED(type);
CHECK(cfg_gettoken(pctx, 0));
if (pctx->token.type != isc_tokentype_string) {
result = ISC_R_UNEXPECTEDTOKEN;
goto cleanup;
}
if (strcmp(TOKEN_STRING(pctx), "unlimited") == 0) {
for (int i = 0; i < 7; i++) {
duration.parts[i] = 0;
}
duration.iso8601 = false;
duration.unlimited = true;
CHECK(cfg_create_obj(pctx, &cfg_type_duration, &obj));
obj->value.duration = duration;
*ret = obj;
return (ISC_R_SUCCESS);
}
return cfg__parse_duration(pctx, ret);
cleanup:
cfg_parser_error(pctx, CFG_LOG_NEAR,
"expected ISO 8601 duration, TTL value, or unlimited");
return (result);
}
/*% /*%
* A duration as defined by ISO 8601 (P[n]Y[n]M[n]DT[n]H[n]M[n]S). * A duration as defined by ISO 8601 (P[n]Y[n]M[n]DT[n]H[n]M[n]S).
* - P is the duration indicator ("period") placed at the start. * - P is the duration indicator ("period") placed at the start.
@@ -1324,6 +1390,11 @@ LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_duration = {
"duration", cfg_parse_duration, cfg_print_duration, cfg_doc_terminal, "duration", cfg_parse_duration, cfg_print_duration, cfg_doc_terminal,
&cfg_rep_duration, NULL &cfg_rep_duration, NULL
}; };
LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_duration_or_unlimited = {
"duration_or_unlimited", cfg_parse_duration_or_unlimited,
cfg_print_duration_or_unlimited, cfg_doc_terminal,
&cfg_rep_duration, NULL
};
/* /*
* qstring (quoted string), ustring (unquoted string), astring * qstring (quoted string), ustring (unquoted string), astring

View File

@@ -72,6 +72,7 @@ cfg_parse_bracketed_list
cfg_parse_buffer cfg_parse_buffer
cfg_parse_dscp cfg_parse_dscp
cfg_parse_duration cfg_parse_duration
cfg_parse_duration_or_unlimited
cfg_parse_enum cfg_parse_enum
cfg_parse_enum_or_other cfg_parse_enum_or_other
cfg_parse_file cfg_parse_file
@@ -112,6 +113,7 @@ cfg_print_chars
cfg_print_clauseflags cfg_print_clauseflags
cfg_print_cstr cfg_print_cstr
cfg_print_duration cfg_print_duration
cfg_print_duration_or_unlimited
cfg_print_fixedpoint cfg_print_fixedpoint
cfg_print_grammar cfg_print_grammar
cfg_print_indent cfg_print_indent