From: Arran Cudbard-Bell Date: Sun, 15 May 2016 01:02:22 +0000 (-0400) Subject: Add support for writing out whether CONF_PAIRs were provided X-Git-Tag: branch_3_1_x~380 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a035880dfc731244a77750cf0240778da9c32a4d;p=thirdparty%2Ffreeradius-server.git Add support for writing out whether CONF_PAIRs were provided --- diff --git a/src/include/conffile.h b/src/include/conffile.h index 9f4fad507e8..0cd77f2b8b6 100644 --- a/src/include/conffile.h +++ b/src/include/conffile.h @@ -196,20 +196,30 @@ typedef struct timeval _timeval_t; * correctly by the config parser. * @{ */ -#define PW_TYPE_DEPRECATED (1 << 10) //!< If a matching #CONF_PAIR is found, error out with a deprecated message. -#define PW_TYPE_REQUIRED (1 << 11) //!< Error out if no matching #CONF_PAIR is found, and no dflt value is set. -#define PW_TYPE_ATTRIBUTE (1 << 12) //!< Value must resolve to attribute in dict (deprecated, use #PW_TYPE_TMPL). -#define PW_TYPE_SECRET (1 << 13) //!< Only print value if debug level >= 3. - -#define PW_TYPE_FILE_INPUT ((1 << 14) | PW_TYPE_STRING) //!< File matching value must exist, and must be readable. -#define PW_TYPE_FILE_OUTPUT ((1 << 15) | PW_TYPE_STRING) //!< File matching value must exist, and must be writeable. - -#define PW_TYPE_XLAT (1 << 16) //!< string will be dynamically expanded. -#define PW_TYPE_TMPL (1 << 17) //!< CONF_PAIR should be parsed as a template. - -#define PW_TYPE_MULTI (1 << 18) //!< CONF_PAIR can have multiple copies. -#define PW_TYPE_NOT_EMPTY (1 << 19) //!< CONF_PAIR is required to have a non zero length value. -#define PW_TYPE_FILE_EXISTS ((1 << 20) | PW_TYPE_STRING) //!< File matching value must exist +#define PW_TYPE_DEPRECATED (1 << 10) //!< If a matching #CONF_PAIR is found, + //!< error out with a deprecated message. +#define PW_TYPE_REQUIRED (1 << 11) //!< Error out if no matching #CONF_PAIR + //!< is found, and no dflt value is set. +#define PW_TYPE_ATTRIBUTE (1 << 12) //!< Value must resolve to attribute in dict + //!< (deprecated, use #PW_TYPE_TMPL). +#define PW_TYPE_SECRET (1 << 13) //!< Only print value if debug level >= 3. + +#define PW_TYPE_FILE_INPUT ((1 << 14) | PW_TYPE_STRING) //!< File matching value must exist, + //!< and must be readable. +#define PW_TYPE_FILE_OUTPUT ((1 << 15) | PW_TYPE_STRING) //!< File matching value must exist, + //!< and must be writeable. + +#define PW_TYPE_XLAT (1 << 16) //!< string will be dynamically expanded. +#define PW_TYPE_TMPL (1 << 17) //!< CONF_PAIR should be parsed as a template. + +#define PW_TYPE_MULTI (1 << 18) //!< CONF_PAIR can have multiple copies. +#define PW_TYPE_NOT_EMPTY (1 << 19) //!< CONF_PAIR is required to have a non zero + //!< length value. +#define PW_TYPE_FILE_EXISTS ((1 << 20) | PW_TYPE_STRING) //!< File matching value must exist + +#define PW_TYPE_IS_SET (1 << 21) //!< Write whether this config item was + //!< left as the default to is_set_offset + //!< or is_set_ptr. /* @} **/ #define FR_INTEGER_COND_CHECK(_name, _var, _cond, _new)\ @@ -279,6 +289,18 @@ typedef struct CONF_PARSER { void *data; //!< Pointer to a static variable to write the parsed value to. //!< @note Must be used exclusively to #offset. + /** Where to write status if PW_TYPE_IS_DEFAULT is set + * + * @note Which field is used, is determined by whether + * data ptr is set. + */ + union { + size_t is_set_offset; //!< If type contains PW_TYPE_IS_DEFAULT write status to bool. + //!< at this address. + void *is_set_ptr; //!< If type contains PW_TYPE_IS_DEFAULT write status to ptr + //!< at this address. + }; + union { char const *dflt; //!< Default as it would appear in radiusd.conf. diff --git a/src/main/conffile.c b/src/main/conffile.c index deb31852ba3..45d33cccb67 100644 --- a/src/main/conffile.c +++ b/src/main/conffile.c @@ -2020,6 +2020,7 @@ static int cf_pair_default(CONF_PAIR **out, CONF_SECTION *cs, char const *name, * - ``flag`` #PW_TYPE_FILE_INPUT - @copybrief PW_TYPE_FILE_INPUT * - ``flag`` #PW_TYPE_NOT_EMPTY - @copybrief PW_TYPE_NOT_EMPTY * - ``flag`` #PW_TYPE_MULTI - @copybrief PW_TYPE_MULTI + * - ``flag`` #PW_TYPE_IS_SET - @copybrief PW_TYPE_IS_SET * @param data Pointer to a global variable, or pointer to a field in the struct being populated with values. * @param dflt value to use, if no #CONF_PAIR is found. * @param dflt_quote around the dflt value. @@ -2292,6 +2293,7 @@ int cf_section_parse(CONF_SECTION *cs, void *base, CONF_PARSER const *variables) int ret = 0; int i; void *data; + bool *is_set; cs->variables = variables; /* this doesn't hurt anything */ @@ -2333,24 +2335,35 @@ int cf_section_parse(CONF_SECTION *cs, void *base, CONF_PARSER const *variables) if (variables[i].data) { data = variables[i].data; /* prefer this. */ } else if (base) { - data = ((char *)base) + variables[i].offset; + data = ((uint8_t *)base) + variables[i].offset; } else { ERROR("Internal sanity check 2 failed in cf_section_parse"); ret = -1; goto finish; } + /* + * Get pointer to where we need to write out + * whether the pointer was set. + */ + if (variables[i].type & PW_TYPE_IS_SET) { + is_set = variables[i].data ? variables[i].is_set_ptr : + ((uint8_t *)base) + variables[i].is_set_offset; + } + /* * Parse the pair we found, or a default value. */ ret = cf_pair_parse(cs, variables[i].name, variables[i].type, data, variables[i].dflt, variables[i].quote); switch (ret) { - case 1: /* Used default */ + case 1: /* Used default (or not present) */ + if (is_set) *is_set = false; ret = 0; break; case 0: /* OK */ + if (is_set) *is_set = true; break; case -1: /* Parse error */