From: Arran Cudbard-Bell Date: Mon, 5 Jan 2015 01:29:43 +0000 (-0500) Subject: Expose core library versions and features in ${feature.*} and ${version.*} X-Git-Tag: release_3_0_7~351 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3acb3210c4ad06206d0a5dc166f7d7b3c9eb9cb4;p=thirdparty%2Ffreeradius-server.git Expose core library versions and features in ${feature.*} and ${version.*} This is mainly needed so that the regex flavour is available for shipped policies, but can also be used for the canonical store of module dependency version numbers. That in itself isn't useful for the server config, as we'd need some sort of 'pass2' for the config sections, but it is useful for querying via radmin. --- diff --git a/src/include/radiusd.h b/src/include/radiusd.h index 8d3778dda5d..a3970bd7134 100644 --- a/src/include/radiusd.h +++ b/src/include/radiusd.h @@ -502,6 +502,7 @@ extern char const *radlog_dir; extern char const *radlib_dir; extern bool log_stripped_names; extern char const *radiusd_version; +extern char const *radiusd_version_short; void radius_signal_self(int flag); typedef enum { @@ -624,9 +625,14 @@ void pairlist_free(PAIR_LIST **); int rad_check_lib_magic(uint64_t magic); int ssl_check_consistency(void); char const *ssl_version_by_num(uint32_t version); +char const *ssl_version_num(void); char const *ssl_version_range(uint32_t low, uint32_t high); char const *ssl_version(void); -void version(void); +int version_add_feature(CONF_SECTION *cs, char const *name, bool enabled); +int version_add_number(CONF_SECTION *cs, char const *name, char const *version); +void version_init_features(CONF_SECTION *cs); +void version_init_numbers(CONF_SECTION *cs); +void version_print(void); /* auth.c */ char *auth_name(char *buf, size_t buflen, REQUEST *request, bool do_cli); diff --git a/src/main/libfreeradius-server.mk b/src/main/libfreeradius-server.mk index c40b1dd46e8..7c4372267bb 100644 --- a/src/main/libfreeradius-server.mk +++ b/src/main/libfreeradius-server.mk @@ -10,5 +10,6 @@ SOURCES := conffile.c \ regex.c \ tmpl.c \ util.c \ + version.c \ pair.c \ xlat.c diff --git a/src/main/mainconfig.c b/src/main/mainconfig.c index 08a1eb889e7..5bd1a33347a 100644 --- a/src/main/mainconfig.c +++ b/src/main/mainconfig.c @@ -702,7 +702,7 @@ char const *get_radius_dir(void) int main_config_init(void) { char const *p = NULL; - CONF_SECTION *cs; + CONF_SECTION *cs, *subcs; struct stat statbuf; cached_config_t *cc; char buffer[1024]; @@ -782,6 +782,38 @@ do {\ */ DICT_READ_OPTIONAL(radius_dir, RADIUS_DICTIONARY); + cs = cf_section_alloc(NULL, "main", NULL); + if (!cs) return -1; + + /* + * Add a 'feature' subsection off the main config + * We check if it's defined first, as the user may + * have defined their own feature flags, or want + * to manually override the ones set by modules + * or the server. + */ + subcs = cf_section_sub_find(cs, "feature"); + if (!subcs) { + subcs = cf_section_alloc(cs, "feature", NULL); + if (!subcs) return -1; + + cf_section_add(cs, subcs); + } + version_init_features(subcs); + + /* + * Add a 'version' subsection off the main config + * We check if it's defined first, this is for + * backwards compatibility. + */ + subcs = cf_section_sub_find(cs, "version"); + if (!subcs) { + subcs = cf_section_alloc(cs, "version", NULL); + if (!subcs) return -1; + cf_section_add(cs, subcs); + } + version_init_numbers(subcs); + /* Read the configuration file */ snprintf(buffer, sizeof(buffer), "%.200s/%.50s.conf", radius_dir, main_config.name); diff --git a/src/main/radiusd.c b/src/main/radiusd.c index b8b0a550901..1a2df8dcf54 100644 --- a/src/main/radiusd.c +++ b/src/main/radiusd.c @@ -311,11 +311,12 @@ int main(int argc, char *argv[]) default_log.dst = L_DST_STDOUT; default_log.fd = STDOUT_FILENO; - version(); + INFO("%s: %s", progname, radiusd_version); + version_print(); exit(EXIT_SUCCESS); } - if (debug_flag) version(); + if (debug_flag) version_print(); /* * Under linux CAP_SYS_PTRACE is usually only available before setuid/setguid, diff --git a/src/main/radiusd.mk b/src/main/radiusd.mk index 1ff95a4f8f2..15f856caa48 100644 --- a/src/main/radiusd.mk +++ b/src/main/radiusd.mk @@ -2,7 +2,7 @@ TARGET := radiusd SOURCES := acct.c auth.c client.c crypt.c files.c \ listen.c mainconfig.c modules.c modcall.c \ radiusd.c state.c stats.c soh.c connection.c \ - session.c threads.c version.c \ + session.c threads.c \ process.c realms.c detail.c ifneq ($(OPENSSL_LIBS),) SOURCES += cb.c tls.c tls_listen.c diff --git a/src/main/unittest.c b/src/main/unittest.c index ffcf71392e0..906ac6d2f25 100644 --- a/src/main/unittest.c +++ b/src/main/unittest.c @@ -612,9 +612,7 @@ int main(int argc, char *argv[]) } } - if (debug_flag) { - version(); - } + if (debug_flag) version_print(); fr_debug_flag = debug_flag; /* diff --git a/src/main/version.c b/src/main/version.c index d4764436736..21f06f19118 100644 --- a/src/main/version.c +++ b/src/main/version.c @@ -27,7 +27,8 @@ RCSID("$Id$") #include USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */ -static uint64_t libmagic = RADIUSD_MAGIC_NUMBER; +static uint64_t libmagic = RADIUSD_MAGIC_NUMBER; +char const *radiusd_version_short = RADIUSD_VERSION_STRING; #ifdef HAVE_OPENSSL_CRYPTO_H # include @@ -123,6 +124,18 @@ char const *ssl_version_by_num(uint32_t v) return buffer; } +/** Return the linked SSL version number as a string + * + * @return pointer to a static buffer containing the version string. + */ +char const *ssl_version_num(void) +{ + long ssl_linked; + + ssl_linked = SSLeay(); + return ssl_version_by_num((uint32_t)ssl_linked); +} + /** Convert two openssl version numbers into a range string * * @note Not thread safe. @@ -169,13 +182,17 @@ int ssl_check_consistency(void) { return 0; } +char const *ssl_version_num(void) +{ + return "not linked"; +} + char const *ssl_version() { return "not linked"; } #endif /* ifdef HAVE_OPENSSL_CRYPTO_H */ - /** Check if the application linking to the library has the correct magic number * * @param magic number as defined by RADIUSD_MAGIC_NUMBER @@ -207,113 +224,357 @@ int rad_check_lib_magic(uint64_t magic) return 0; } -/* - * Display the revision number for this program +/** Add a feature flag to the main configuration + * + * Add a feature flag (yes/no) to the 'feature' subsection + * off the main config. + * + * This allows the user to create configurations that work with + * across multiple environments. + * + * @param cs to add feature pair to. + * @param name of feature. + * @param enabled Whether the feature is present/enabled. + * @return 0 on success else -1. + */ +int version_add_feature(CONF_SECTION *cs, char const *name, bool enabled) +{ + if (!cs) return -1; + + if (!cf_pair_find(cs, name)) { + CONF_PAIR *cp; + + cp = cf_pair_alloc(cs, name, enabled ? "yes" : "no", + T_OP_SET, T_BARE_WORD, T_BARE_WORD); + if (!cp) return -1; + cf_pair_add(cs, cp); + } + + return 0; +} + +/** Add a library/server version pair to the main configuration + * + * Add a version number to the 'version' subsection off the main + * config. + * + * Because of the optimisations in the configuration parser, these + * may be checked using regular expressions without a performance + * penalty. + * + * The version pairs are there primarily to work around defects + * in libraries or the server. + * + * @param cs to add feature pair to. + * @param name of library or feature. + * @param version Humanly readable version text. + * @return 0 on success else -1. */ -void version(void) +int version_add_number(CONF_SECTION *cs, char const *name, char const *version) { - INFO("%s: %s", progname, radiusd_version); + CONF_PAIR *old; + + if (!cs) return -1; - DEBUG3("Server was built with: "); + old = cf_pair_find(cs, name); + if (!old) { + CONF_PAIR *cp; + cp = cf_pair_alloc(cs, name, version, T_OP_SET, T_BARE_WORD, T_SINGLE_QUOTED_STRING); + if (!cp) return -1; + + cf_pair_add(cs, cp); + } else { + WARN("Replacing user version.%s (%s) with %s", name, cf_pair_value(old), version); + + cf_pair_replace(cs, old, version); + } + + return 0; +} + + +/** Initialise core feature flags + * + * @param cs Where to add the CONF_PAIRS, if null pairs will be added + * to the 'feature' section of the main config. + */ +void version_init_features(CONF_SECTION *cs) +{ + version_add_feature(cs, "accounting", #ifdef WITH_ACCOUNTING - DEBUG3(" accounting"); + true +#else + false #endif - DEBUG3(" authentication"); /* always enabled */ + ); + version_add_feature(cs, "authentication", true); + + version_add_feature(cs, "ascend-binary-attributes", #ifdef WITH_ASCEND_BINARY - DEBUG3(" ascend binary attributes"); + true +#else + false #endif + ); + + version_add_feature(cs, "coa", #ifdef WITH_COA - DEBUG3(" coa"); + true +#else + false #endif + ); + + + version_add_feature(cs, "control-socket", #ifdef WITH_COMMAND_SOCKET - DEBUG3(" control-socket"); + true +#else + false #endif + ); + + + version_add_feature(cs, "detail", #ifdef WITH_DETAIL - DEBUG3(" detail"); + true +#else + false #endif + ); + + version_add_feature(cs, "dhcp", #ifdef WITH_DHCP - DEBUG3(" dhcp"); + true +#else + false #endif + ); + + version_add_feature(cs, "dynamic-clients", #ifdef WITH_DYNAMIC_CLIENTS - DEBUG3(" dynamic clients"); + true +#else + false #endif + ); + + version_add_feature(cs, "osfc2", #ifdef OSFC2 - DEBUG3(" OSFC2"); + true +#else + false #endif + ); + + version_add_feature(cs, "proxy", #ifdef WITH_PROXY - DEBUG3(" proxy"); + true +#else + false #endif + ); + + version_add_feature(cs, "regex-pcre", #ifdef HAVE_PCRE - DEBUG3(" regex-pcre"); + true #else -# ifdef HAVE_REGEX -# ifdef HAVE_REG_EXTENDED - DEBUG3(" regex-posix-extended"); -# else - DEBUG3(" regex-posix"); -# endif + false +#endif + ); + +#if !defined(HAVE_PCRE) && defined(HAVE_REGEX) + version_add_feature(cs, "regex-posix", true); + version_add_feature(cs, "regex-posix-extended", +# ifdef HAVE_REG_EXTENDED + true +# else + false # endif + ); +#else + version_add_feature(cs, "regex-posix", false); + version_add_feature(cs, "regex-posix-extended", false); #endif + version_add_feature(cs, "session-management", #ifdef WITH_SESSION_MGMT - DEBUG3(" session-management"); + true +#else + false #endif + ); + + version_add_feature(cs, "stats", #ifdef WITH_STATS - DEBUG3(" stats"); + true +#else + false #endif + ); + + version_add_feature(cs, "tcp", #ifdef WITH_TCP - DEBUG3(" tcp"); + true +#else + false #endif + ); + + version_add_feature(cs, "threads", #ifdef WITH_THREADS - DEBUG3(" threads"); + true +#else + false #endif + ); + + version_add_feature(cs, "tls", #ifdef WITH_TLS - DEBUG3(" tls"); + true +#else + false #endif + ); + + version_add_feature(cs, "unlang", #ifdef WITH_UNLANG - DEBUG3(" unlang"); + true +#else + false #endif + ); + + version_add_feature(cs, "vmps", #ifdef WITH_VMPS - DEBUG3(" vmps"); + true +#else + false #endif + ); + + version_add_feature(cs, "developer", #ifndef NDEBUG - DEBUG3(" developer"); + true +#else + false #endif + ); +} - DEBUG3("Server core libs:"); - DEBUG3(" talloc : %i.%i.*", talloc_version_major(), talloc_version_minor()); - DEBUG3(" ssl : %s", ssl_version()); +/** Initialise core version flags + * + * @param cs Where to add the CONF_PAIRS, if null pairs will be added + * to the 'version' section of the main config. + */ +void version_init_numbers(CONF_SECTION *cs) +{ + char buffer[128]; + + version_add_number(cs, "freeradius-server", radiusd_version_short); + + snprintf(buffer, sizeof(buffer), "%i.%i.*", talloc_version_major(), talloc_version_minor()); + version_add_number(cs, "talloc", buffer); + + version_add_number(cs, "ssl", ssl_version_num()); #if defined(HAVE_REGEX) && defined(HAVE_PCRE) - DEBUG3(" pcre : %s", pcre_version()); + version_add_number(cs, "pcre", pcre_version()); #endif - DEBUG3("Library magic number:"); - DEBUG3(" 0x%llx", (unsigned long long) libmagic); +} + +static char const *spaces = " "; /* 40 */ + +/* + * Display the revision number for this program + */ +void version_print(void) +{ + CONF_SECTION *features, *versions; + CONF_ITEM *ci; + CONF_PAIR *cp; + + if (DEBUG_ENABLED2) { + int max = 0, len; + + MEM(features = cf_section_alloc(NULL, "feature", NULL)); + version_init_features(features); + + MEM(versions = cf_section_alloc(NULL, "version", NULL)); + version_init_numbers(versions); - DEBUG3("Endianess:"); + DEBUG3("Server was built with: "); + + for (ci = cf_item_find_next(features, NULL); + ci; + ci = cf_item_find_next(features, ci)) { + len = talloc_array_length(cf_pair_attr(cf_item_to_pair(ci))); + if (max < len) max = len; + } + + for (ci = cf_item_find_next(versions, NULL); + ci; + ci = cf_item_find_next(versions, ci)) { + len = talloc_array_length(cf_pair_attr(cf_item_to_pair(ci))); + if (max < len) max = len; + } + + + for (ci = cf_item_find_next(features, NULL); + ci; + ci = cf_item_find_next(features, ci)) { + char const *attr; + + cp = cf_item_to_pair(ci); + attr = cf_pair_attr(cp); + + DEBUG3(" %s%.*s : %s", attr, + (int)(max - talloc_array_length(attr)), spaces, cf_pair_value(cp)); + } + + talloc_free(features); + + DEBUG3("Server core libs:"); + + for (ci = cf_item_find_next(versions, NULL); + ci; + ci = cf_item_find_next(versions, ci)) { + char const *attr; + + cp = cf_item_to_pair(ci); + attr = cf_pair_attr(cp); + + DEBUG3(" %s%.*s : %s", attr, + (int)(max - talloc_array_length(attr)), spaces, cf_pair_value(cp)); + } + + talloc_free(versions); + + DEBUG3("Endianess:"); #if defined(RADIUS_LITTLE_ENDIAN) - DEBUG3(" little"); + DEBUG3(" little"); #elif defined(RADIUS_BIG_ENDIAN) - DEBUG3(" big"); + DEBUG3(" big"); #else - DEBUG3(" unknown"); + DEBUG3(" unknown"); #endif - DEBUG3("Compilation flags:"); + DEBUG3("Compilation flags:"); #ifdef BUILT_WITH_CPPFLAGS - DEBUG3(" cppflags : " BUILT_WITH_CPPFLAGS); + DEBUG3(" cppflags : " BUILT_WITH_CPPFLAGS); #endif #ifdef BUILT_WITH_CFLAGS - DEBUG3(" cflags : " BUILT_WITH_CFLAGS); + DEBUG3(" cflags : " BUILT_WITH_CFLAGS); #endif #ifdef BUILT_WITH_LDFLAGS - DEBUG3(" ldflags : " BUILT_WITH_LDFLAGS); + DEBUG3(" ldflags : " BUILT_WITH_LDFLAGS); #endif #ifdef BUILT_WITH_LIBS - DEBUG3(" libs : " BUILT_WITH_LIBS); + DEBUG3(" libs : " BUILT_WITH_LIBS); #endif + } INFO("Copyright (C) 1999-2015 The FreeRADIUS server project and contributors"); INFO("There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A"); INFO("PARTICULAR PURPOSE"); diff --git a/src/main/xlat.c b/src/main/xlat.c index 30a7852e264..9a4b580bbfc 100644 --- a/src/main/xlat.c +++ b/src/main/xlat.c @@ -92,8 +92,6 @@ static char const * const xlat_foreach_names[] = {"Foreach-Variable-0", static int xlat_inst[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; /* up to 10 for foreach */ -static char const *radiusd_short_version = RADIUSD_VERSION_STRING; - /** Print length of its RHS. * */ @@ -2151,7 +2149,8 @@ static char *xlat_aprint(TALLOC_CTX *ctx, REQUEST *request, xlat_exp_t const * c break; case 'v': /* Version of code */ - snprintf(str, freespace, "%s", radiusd_short_version); + RWDEBUG("%%v is deprecated and will be removed. Use ${version.freeradius-server}"); + snprintf(str, freespace, "%s", radiusd_version_short); break; default: