]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Move duration structure to libisccfg/duration
authorMatthijs Mekking <matthijs@isc.org>
Tue, 21 Jun 2022 10:22:36 +0000 (12:22 +0200)
committerMatthijs Mekking <matthijs@isc.org>
Tue, 28 Jun 2022 09:56:31 +0000 (11:56 +0200)
Having the duration structure and parsing code here, it becomes
more accessible to be used in other places.

lib/isccfg/Makefile.am
lib/isccfg/duration.c [new file with mode: 0644]
lib/isccfg/include/isccfg/duration.h [new file with mode: 0644]
lib/isccfg/include/isccfg/grammar.h
lib/isccfg/parser.c

index 32e905aa96569eb9f76735fc4df1b221acf2d448..0c95c4f0d432011942ae01f99d203dc2f06f43df 100644 (file)
@@ -6,6 +6,7 @@ libisccfg_ladir = $(includedir)/isccfg
 libisccfg_la_HEADERS =                 \
        include/isccfg/aclconf.h        \
        include/isccfg/cfg.h            \
+       include/isccfg/duration.h       \
        include/isccfg/grammar.h        \
        include/isccfg/kaspconf.h       \
        include/isccfg/log.h            \
@@ -15,6 +16,7 @@ libisccfg_la_SOURCES =                        \
        $(libisccfg_la_HEADERS)         \
        aclconf.c                       \
        dnsconf.c                       \
+       duration.c                      \
        kaspconf.c                      \
        log.c                           \
        namedconf.c                     \
diff --git a/lib/isccfg/duration.c b/lib/isccfg/duration.c
new file mode 100644 (file)
index 0000000..30d110a
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <ctype.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/parseint.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <isccfg/duration.h>
+
+/*
+ * isccfg_duration_fromtext initially taken from OpenDNSSEC code base.
+ * Modified to fit the BIND 9 code.
+ */
+isc_result_t
+isccfg_duration_fromtext(isc_textregion_t *source,
+                        isccfg_duration_t *duration) {
+       char buf[DURATION_MAXLEN];
+       char *P, *X, *T, *W, *str;
+       bool not_weeks = false;
+       int i;
+
+       /*
+        * Copy the buffer as it may not be NULL terminated.
+        * Anyone having a duration longer than 63 characters is crazy.
+        */
+       if (source->length > sizeof(buf) - 1) {
+               return (ISC_R_BADNUMBER);
+       }
+       /* Copy source->length bytes and NULL terminate. */
+       snprintf(buf, sizeof(buf), "%.*s", (int)source->length, source->base);
+       str = buf;
+
+       /* Clear out duration. */
+       for (i = 0; i < 7; i++) {
+               duration->parts[i] = 0;
+       }
+       duration->iso8601 = false;
+       duration->unlimited = false;
+
+       /* Every duration starts with 'P' */
+       P = strpbrk(str, "Pp");
+       if (P == NULL) {
+               return (ISC_R_BADNUMBER);
+       }
+
+       /* Record the time indicator. */
+       T = strpbrk(str, "Tt");
+
+       /* Record years. */
+       X = strpbrk(str, "Yy");
+       if (X != NULL) {
+               duration->parts[0] = atoi(str + 1);
+               str = X;
+               not_weeks = true;
+       }
+
+       /* Record months. */
+       X = strpbrk(str, "Mm");
+
+       /*
+        * M could be months or minutes. This is months if there is no time
+        * part, or this M indicator is before the time indicator.
+        */
+       if (X != NULL && (T == NULL || (size_t)(X - P) < (size_t)(T - P))) {
+               duration->parts[1] = atoi(str + 1);
+               str = X;
+               not_weeks = true;
+       }
+
+       /* Record days. */
+       X = strpbrk(str, "Dd");
+       if (X != NULL) {
+               duration->parts[3] = atoi(str + 1);
+               str = X;
+               not_weeks = true;
+       }
+
+       /* Time part? */
+       if (T != NULL) {
+               str = T;
+               not_weeks = true;
+       }
+
+       /* Record hours. */
+       X = strpbrk(str, "Hh");
+       if (X != NULL && T != NULL) {
+               duration->parts[4] = atoi(str + 1);
+               str = X;
+               not_weeks = true;
+       }
+
+       /* Record minutes. */
+       X = strpbrk(str, "Mm");
+
+       /*
+        * M could be months or minutes. This is minutes if there is a time
+        * part and the M indicator is behind the time indicator.
+        */
+       if (X != NULL && T != NULL && (size_t)(X - P) > (size_t)(T - P)) {
+               duration->parts[5] = atoi(str + 1);
+               str = X;
+               not_weeks = true;
+       }
+
+       /* Record seconds. */
+       X = strpbrk(str, "Ss");
+       if (X != NULL && T != NULL) {
+               duration->parts[6] = atoi(str + 1);
+               str = X;
+               not_weeks = true;
+       }
+
+       /* Or is the duration configured in weeks? */
+       W = strpbrk(buf, "Ww");
+       if (W != NULL) {
+               if (not_weeks) {
+                       /* Mix of weeks and other indicators is not allowed */
+                       return (ISC_R_BADNUMBER);
+               } else {
+                       duration->parts[2] = atoi(str + 1);
+                       str = W;
+               }
+       }
+
+       /* Deal with trailing garbage. */
+       if (str[1] != '\0') {
+               return (ISC_R_BADNUMBER);
+       }
+
+       duration->iso8601 = true;
+       return (ISC_R_SUCCESS);
+}
diff --git a/lib/isccfg/include/isccfg/duration.h b/lib/isccfg/include/isccfg/duration.h
new file mode 100644 (file)
index 0000000..32b23e4
--- /dev/null
@@ -0,0 +1,58 @@
+
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file */
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+#define DURATION_MAXLEN 64
+
+/*%
+ * A configuration object to store ISO 8601 durations.
+ */
+typedef struct isccfg_duration {
+       /*
+        * The duration is stored in multiple parts:
+        * [0] Years
+        * [1] Months
+        * [2] Weeks
+        * [3] Days
+        * [4] Hours
+        * [5] Minutes
+        * [6] Seconds
+        */
+       uint32_t parts[7];
+       bool     iso8601;
+       bool     unlimited;
+} isccfg_duration_t;
+
+isc_result_t
+isccfg_duration_fromtext(isc_textregion_t *source, isccfg_duration_t *duration);
+/*%<
+ * Converts an ISO 8601 duration style value.
+ *
+ * Returns:
+ *\li  ISC_R_SUCCESS
+ *\li  DNS_R_BADNUMBER
+ */
+
+ISC_LANG_ENDDECLS
index 2f1b54673d04285f3f1acce98eea81f1f718cd9d..9c5e5dfa26b3001ce725c53af24b744812f31eb0 100644 (file)
@@ -25,6 +25,7 @@
 #include <isc/types.h>
 
 #include <isccfg/cfg.h>
+#include <isccfg/duration.h>
 
 /*
  * Definitions shared between the configuration parser
@@ -77,11 +78,8 @@ typedef struct cfg_clausedef  cfg_clausedef_t;
 typedef struct cfg_tuplefielddef cfg_tuplefielddef_t;
 typedef struct cfg_printer      cfg_printer_t;
 typedef ISC_LIST(cfg_listelt_t) cfg_list_t;
-typedef struct cfg_map     cfg_map_t;
-typedef struct cfg_rep     cfg_rep_t;
-typedef struct cfg_duration cfg_duration_t;
-
-#define CFG_DURATION_MAXLEN 64
+typedef struct cfg_map cfg_map_t;
+typedef struct cfg_rep cfg_rep_t;
 
 /*
  * Function types for configuration object methods
@@ -125,17 +123,17 @@ struct cfg_tuplefielddef {
 
 /*% A configuration object type definition. */
 struct cfg_type {
-       const char     *name; /*%< For debugging purposes only */
+       const char         *name; /*%< For debugging purposes only */
        cfg_parsefunc_t parse;
        cfg_printfunc_t print;
        cfg_docfunc_t   doc; /*%< Print grammar description */
-       cfg_rep_t      *rep; /*%< Data representation */
-       const void     *of;  /*%< Additional data for meta-types */
+       cfg_rep_t         *rep; /*%< Data representation */
+       const void         *of;  /*%< Additional data for meta-types */
 };
 
 /*% A keyword-type definition, for things like "port <integer>". */
 typedef struct {
-       const char       *name;
+       const char         *name;
        const cfg_type_t *type;
 } keyword_type_t;
 
@@ -155,30 +153,11 @@ struct cfg_netprefix {
        unsigned int  prefixlen;
 };
 
-/*%
- * A configuration object to store ISO 8601 durations.
- */
-struct cfg_duration {
-       /*
-        * The duration is stored in multiple parts:
-        * [0] Years
-        * [1] Months
-        * [2] Weeks
-        * [3] Days
-        * [4] Hours
-        * [5] Minutes
-        * [6] Seconds
-        */
-       uint32_t parts[7];
-       bool     iso8601;
-       bool     unlimited;
-};
-
 /*%
  * A configuration data representation.
  */
 struct cfg_rep {
-       const char    *name; /*%< For debugging only */
+       const char         *name; /*%< For debugging only */
        cfg_freefunc_t free; /*%< How to free this kind of data. */
 };
 
@@ -196,17 +175,17 @@ struct cfg_obj {
                bool             boolean;
                cfg_map_t        map;
                cfg_list_t       list;
-               cfg_obj_t      **tuple;
+               cfg_obj_t         **tuple;
                isc_sockaddr_t   sockaddr;
                struct {
                        isc_sockaddr_t sockaddr;
                        isc_dscp_t     dscp;
                } sockaddrdscp;
-               cfg_netprefix_t netprefix;
-               cfg_duration_t  duration;
+               cfg_netprefix_t   netprefix;
+               isccfg_duration_t duration;
        } value;
        isc_refcount_t references; /*%< reference counter */
-       const char    *file;
+       const char         *file;
        unsigned int   line;
        cfg_parser_t  *pctx;
 };
@@ -219,9 +198,9 @@ struct cfg_listelt {
 
 /*% The parser object. */
 struct cfg_parser {
-       isc_mem_t   *mctx;
-       isc_log_t   *lctx;
-       isc_lex_t   *lexer;
+       isc_mem_t         *mctx;
+       isc_log_t         *lctx;
+       isc_lex_t         *lexer;
        unsigned int errors;
        unsigned int warnings;
        isc_token_t  token;
@@ -275,7 +254,7 @@ struct cfg_parser {
        isc_refcount_t references;
 
        cfg_parsecallback_t callback;
-       void               *callbackarg;
+       void           *callbackarg;
 };
 
 /* Parser context flags */
index eeea6e779043a26a414dec5468beca58c97b348b..db2a328c2a00ca3fd1205f682753247db0d56aea 100644 (file)
@@ -12,9 +12,6 @@
  */
 
 /*
- * duration_fromtext initially taken from OpenDNSSEC code base.
- * Modified to fit the BIND 9 code.
- *
  * Copyright (c) 2009-2018 NLNet Labs.
  * All rights reserved.
  *
@@ -1033,12 +1030,12 @@ numlen(uint32_t num) {
  */
 void
 cfg_print_duration(cfg_printer_t *pctx, const cfg_obj_t *obj) {
-       char buf[CFG_DURATION_MAXLEN];
+       char buf[DURATION_MAXLEN];
        char *str;
        const char *indicators = "YMWDHMS";
        int count, i;
        int durationlen[7];
-       cfg_duration_t duration;
+       isccfg_duration_t duration;
        /*
         * D ? The duration has a date part.
         * T ? The duration has a time part.
@@ -1090,7 +1087,7 @@ cfg_print_duration(cfg_printer_t *pctx, const cfg_obj_t *obj) {
        if (T) {
                count++;
        }
-       INSIST(count < CFG_DURATION_MAXLEN);
+       INSIST(count < DURATION_MAXLEN);
 
        /* Now print the duration. */
        for (i = 0; i < 6; i++) {
@@ -1119,7 +1116,7 @@ cfg_print_duration(cfg_printer_t *pctx, const cfg_obj_t *obj) {
 
 void
 cfg_print_duration_or_unlimited(cfg_printer_t *pctx, const cfg_obj_t *obj) {
-       cfg_duration_t duration;
+       isccfg_duration_t duration;
 
        REQUIRE(pctx != NULL);
        REQUIRE(obj != NULL);
@@ -1157,149 +1154,30 @@ cfg_obj_asduration(const cfg_obj_t *obj) {
        return (duration);
 }
 
-static isc_result_t
-duration_fromtext(isc_textregion_t *source, cfg_duration_t *duration) {
-       char buf[CFG_DURATION_MAXLEN];
-       char *P, *X, *T, *W, *str;
-       bool not_weeks = false;
-       int i;
-
-       /*
-        * Copy the buffer as it may not be NULL terminated.
-        * Anyone having a duration longer than 63 characters is crazy.
-        */
-       if (source->length > sizeof(buf) - 1) {
-               return (ISC_R_BADNUMBER);
-       }
-       /* Copy source->length bytes and NULL terminate. */
-       snprintf(buf, sizeof(buf), "%.*s", (int)source->length, source->base);
-       str = buf;
-
-       /* Clear out duration. */
-       for (i = 0; i < 7; i++) {
-               duration->parts[i] = 0;
-       }
-
-       /* Every duration starts with 'P' */
-       P = strpbrk(str, "Pp");
-       if (P == NULL) {
-               return (ISC_R_BADNUMBER);
-       }
-
-       /* Record the time indicator. */
-       T = strpbrk(str, "Tt");
-
-       /* Record years. */
-       X = strpbrk(str, "Yy");
-       if (X != NULL) {
-               duration->parts[0] = atoi(str + 1);
-               str = X;
-               not_weeks = true;
-       }
-
-       /* Record months. */
-       X = strpbrk(str, "Mm");
-
-       /*
-        * M could be months or minutes. This is months if there is no time
-        * part, or this M indicator is before the time indicator.
-        */
-       if (X != NULL && (T == NULL || (size_t)(X - P) < (size_t)(T - P))) {
-               duration->parts[1] = atoi(str + 1);
-               str = X;
-               not_weeks = true;
-       }
-
-       /* Record days. */
-       X = strpbrk(str, "Dd");
-       if (X != NULL) {
-               duration->parts[3] = atoi(str + 1);
-               str = X;
-               not_weeks = true;
-       }
-
-       /* Time part? */
-       if (T != NULL) {
-               str = T;
-               not_weeks = true;
-       }
-
-       /* Record hours. */
-       X = strpbrk(str, "Hh");
-       if (X != NULL && T != NULL) {
-               duration->parts[4] = atoi(str + 1);
-               str = X;
-               not_weeks = true;
-       }
-
-       /* Record minutes. */
-       X = strpbrk(str, "Mm");
-
-       /*
-        * M could be months or minutes. This is minutes if there is a time
-        * part and the M indicator is behind the time indicator.
-        */
-       if (X != NULL && T != NULL && (size_t)(X - P) > (size_t)(T - P)) {
-               duration->parts[5] = atoi(str + 1);
-               str = X;
-               not_weeks = true;
-       }
-
-       /* Record seconds. */
-       X = strpbrk(str, "Ss");
-       if (X != NULL && T != NULL) {
-               duration->parts[6] = atoi(str + 1);
-               str = X;
-               not_weeks = true;
-       }
-
-       /* Or is the duration configured in weeks? */
-       W = strpbrk(buf, "Ww");
-       if (W != NULL) {
-               if (not_weeks) {
-                       /* Mix of weeks and other indicators is not allowed */
-                       return (ISC_R_BADNUMBER);
-               } else {
-                       duration->parts[2] = atoi(str + 1);
-                       str = W;
-               }
-       }
-
-       /* Deal with trailing garbage. */
-       if (str[1] != '\0') {
-               return (ISC_R_BADNUMBER);
-       }
-
-       return (ISC_R_SUCCESS);
-}
-
 static isc_result_t
 parse_duration(cfg_parser_t *pctx, cfg_obj_t **ret) {
        isc_result_t result;
        cfg_obj_t *obj = NULL;
-       cfg_duration_t duration;
+       isccfg_duration_t duration;
 
        duration.unlimited = false;
 
-       if (toupper((unsigned char)TOKEN_STRING(pctx)[0]) == 'P') {
-               result = duration_fromtext(&pctx->token.value.as_textregion,
-                                          &duration);
-               duration.iso8601 = true;
-       } else {
+       result = isccfg_duration_fromtext(&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);
-               /*
-                * With dns_ttl_fromtext() the information on optional units.
-                * is lost, and is treated as seconds from now on.
-                */
-               for (int i = 0; i < 6; i++) {
-                       duration.parts[i] = 0;
+               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;
                }
-               duration.parts[6] = ttl;
-               duration.iso8601 = false;
        }
-
        if (result == ISC_R_RANGE) {
                cfg_parser_error(pctx, CFG_LOG_NEAR,
                                 "duration or TTL out of range");
@@ -1346,7 +1224,7 @@ 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;
+       isccfg_duration_t duration;
 
        UNUSED(type);