From: Alan T. DeKok Date: Tue, 13 Jan 2026 12:55:21 +0000 (-0500) Subject: add libfreeradius-radius-stats.la along with framework X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0014f08f107d05dd99c7fbd260cfa45928587ae7;p=thirdparty%2Ffreeradius-server.git add libfreeradius-radius-stats.la along with framework --- diff --git a/src/all.mk b/src/all.mk index 716cd459276..a108ab3de25 100644 --- a/src/all.mk +++ b/src/all.mk @@ -7,7 +7,8 @@ SUBMAKEFILES := include/all.mk \ listen/all.mk \ process/all.mk \ modules/all.mk \ - bin/all.mk + bin/all.mk \ + stats/all.mk # # The default is to just build the source code. We skip running the diff --git a/src/bin/radict.c b/src/bin/radict.c index e13deea0bab..bbfd5928108 100644 --- a/src/bin/radict.c +++ b/src/bin/radict.c @@ -44,7 +44,6 @@ typedef enum { RADICT_OUT_DICT, RADICT_OUT_STRUCT, RADICT_OUT_STATS_LINK, - RADICT_OUT_ATTRS_H, RADICT_OUT_BASE_C_DA_DEF, RADICT_OUT_ATTR_AUTOLOAD, RADICT_OUT_STATS_H, @@ -502,7 +501,7 @@ static void da_print_struct(FILE *fp, fr_dict_attr_t const *parent) fprintf(fp, "_t;\n"); } -static void da_print_attr_def(FILE *fp, fr_dict_attr_t const *parent, char const *prefix) +static void da_print_base_c_da_def(FILE *fp, fr_dict_attr_t const *parent) { int i; fr_dict_attr_t const *da; @@ -512,10 +511,10 @@ static void da_print_attr_def(FILE *fp, fr_dict_attr_t const *parent, char const da_normalize_name(parent, parent_name); - fprintf(fp, "%sfr_dict_attr_t const *attr_%s;\n", prefix, parent_name); + fprintf(fp, "static fr_dict_attr_t const *attr_%s;\n", parent_name); for (i = 1; (da = fr_dict_attr_child_by_num(parent, i)) != NULL; i++) { - fprintf(fp, "%sfr_dict_attr_t const *attr_%s_", prefix, parent_name); + fprintf(fp, "static fr_dict_attr_t const *attr_%s_", parent_name); da_print_name(fp, da); fprintf(fp, ";\n"); } @@ -523,15 +522,6 @@ static void da_print_attr_def(FILE *fp, fr_dict_attr_t const *parent, char const fprintf(fp, "\n\n"); } -static void da_print_attrs_h(FILE *fp, fr_dict_attr_t const *parent) -{ - da_print_attr_def(fp, parent, "extern HIDDEN "); -} - -static void da_print_base_c_da_def(FILE *fp, fr_dict_attr_t const *parent) -{ - da_print_attr_def(fp, parent, ""); -} /** Map data types to enum names representing those types */ @@ -606,7 +596,7 @@ static void da_print_stats_link(FILE *fp, fr_dict_attr_t const *parent) } fprintf(fp, "\t.num_elements = %d,\n", num_elements); - fprintf(fp, "\t.entry = (fr_stats_link_entry_t[]) { /* -Wgnu-flexible-array-initializer */\n"); + fprintf(fp, "\t.entry = {\n"); /* * For locality, also print out data type and size. That way we _can_ dereference the da, but we @@ -678,6 +668,8 @@ static void da_print_stats_h(FILE *fp, fr_dict_attr_t const *parent) fprintf(fp, "\n"); + fprintf(fp, "FR_STATS_TYPEDEF(%s_%s);\n\n", dict_name, parent_name); + fprintf(fp, "extern fr_stats_link_t const fr_stats_link_%s_%s;\n\n", dict_name, parent_name); } @@ -738,7 +730,6 @@ static fr_table_num_ordered_t const format_table[] = { { L("dict"), RADICT_OUT_DICT }, { L("struct"), RADICT_OUT_STRUCT }, { L("stats_link"), RADICT_OUT_STATS_LINK }, - { L("attrs.h"), RADICT_OUT_ATTRS_H }, { L("da_def"), RADICT_OUT_BASE_C_DA_DEF }, { L("attr_autoload"), RADICT_OUT_ATTR_AUTOLOAD }, { L("stats.h"), RADICT_OUT_STATS_H }, @@ -751,7 +742,6 @@ static fr_table_ptr_ordered_t const function_table[] = { { L("dict"), NULL }, { L("struct"), (void *) da_print_struct }, { L("stats_link"), (void *) da_print_stats_link }, - { L("attrs.h"), (void *) da_print_attrs_h }, { L("da_def"), (void *) da_print_base_c_da_def }, { L("attr_autoload"), (void *) da_print_attr_autoload }, { L("stats.h"), (void *) da_print_stats_h }, diff --git a/src/lib/util/stats.h b/src/lib/util/stats.h index ab482eed32e..6ee2d7cdd20 100644 --- a/src/lib/util/stats.h +++ b/src/lib/util/stats.h @@ -68,46 +68,76 @@ typedef struct { uint8_t stats[]; //!< generic statistics data } fr_stats_instance_t; -/** Macro to define a typedef for a particular kind of statistics +/** Iterator for a statistics structure. * + * This is used internally, and there's no real need for code outside of the statistics library to use it. */ -#define FR_STATS_TYPEDEF(_name, _type) \ +typedef struct { + fr_stats_instance_t const *inst; + unsigned int current; +} fr_stats_iter_t; + + +/** Macro to define a typedef for a particular instance of statistics + * + * Defines fr_stats_name_instance_t which contains an instance of the statistics for fr_stats_name_t, and + * which points to the linking structure fr_stats_link_name_t. + * + * Note that nothing needs to refer to the base statistics structure: fr_stats_name_t. All of that is + * wrapped in an instance definition. + * + * This is used internally, and there's no real need for code outside of the statistics library to use it. + */ +#define FR_STATS_TYPEDEF(_name) \ typedef struct { \ STATS_HEADER_COMMON; \ - _type stats; \ - } fr_stats_## _name ## _instance_t + fr_stats_ ## _name ## _t stats; \ + } fr_stats_ ## _name ## _instance_t -/** Macro used when declaring a variable which contains the statistics +/** Macro used when referencing a linking structure + * + * .def = FR_STATS_LINK_NAME(radius_auth_serv), * + * This is used internally, and there's no real need for code outside of the statistics library to use it. */ -#define FR_STATS_ENTRY_DECL(_name, _var) fr_stats_## _name ## _instance_t _var; +#define FR_STATS_LINK_NAME(_name) fr_stats_link_ ## _name ## _t -/** Macro used when initializing a variable which contains the statistics +/** Macro used when declaring a variable which contains an instance of the statistics + * + * Defines "fr_stats_name_instance_t var", which can be used in a structure * + * Code which needs to use some statistics can use this macro to declare a variable which contains stats for + * the local module / etc. + */ +#define FR_STATS_ENTRY_DECL(_name, _var) fr_stats_ ## _name ## _instance_t _var + +/** Macro used when initializing a variable which contains an instance of the statistics + * + * var = .... initializer for the stats instance ... + * + * Code which needs to use some statistics can use this macro to initialize a variable which contains stats + * for the local module / etc. */ #define FR_STATS_ENTRY_INIT(_name, _var, _mib) \ - _var = (fr_stats_## _name ## _instance_t) { \ + _var = (fr_stats_ ## _name ## _instance_t) { \ .def = fr_stats_link_ ## _name ## _t, \ .mib = _mib, \ - fr_stats_## _name ## _t stats = {}, \ + fr_stats_ ## _name ## _t stats = {}, \ } - -/** Macro used when referencing a linking structure - * - * .def = FR_STATS_LINK_NAME(radius_auth_serv), - */ -#define FR_STATS_LINK_NAME(_name) fr_stats_link_ ## _name ## _t /** Macro used to increment one field in the statistics structure * + * Code which needs to update some statistics can use this macro to increment a variable which contains + * stats for the local module / etc. */ -#define FR_STATS_INC(_var, _field) _var->stats._field++ +#define FR_STATS_INC(_var, _field) ((_var)->stats.(_field))++ -typedef struct { - fr_stats_instance_t const *inst; - unsigned int current; -} fr_stats_iter_t; +/** Macro used to reference a field in the statistics structure + * + * Code which needs to mangle a field of the statistics can use this macro to get the correct field name. + */ +#define FR_STATS_FIELD(_var, _field) (_var)->stats.(_field) int fr_stats_to_pairs(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_stats_instance_t const *in) CC_HINT(nonnull); int fr_stats_from_pairs(TALLOC_CTX *ctx, fr_stats_instance_t *out, fr_pair_list_t *in) CC_HINT(nonnull); diff --git a/src/stats/all.mk b/src/stats/all.mk new file mode 100644 index 00000000000..c5ee915836c --- /dev/null +++ b/src/stats/all.mk @@ -0,0 +1,56 @@ +RADICT := $(BUILD_DIR)/make/jlibtool --silent --mode=execute $(BUILD_DIR)/bin/local/radict -D share/dictionary + +# +# $(eval $(call DICT_STATS,radius,auth_serv,mib-2.radiusAuthServ,1.3.6.1.2.1.67.1.1.1.1)) +# +# We don't want the outputs to be updated if the build fails. So we use an intermediate filename. +# And we use ".cache", because that's ignored by the top level ".gitignore" +# +define DICT_STATS + +# +# Re-build the files if the dictionary changes. +# +# Ensure that the protocol library is built before the statistics +# library, as radict needs it. +# +# Ensure that radict is built before the statistics library, as we +# run radict to generate the output files. +# + +# +# Define the structures and declare the extern variables +# +src/stats/${1}/${2}_stats.h: share/dictionary/${1}/dictionary.stats $(BUILD_DIR)/lib/local/libfreeradius-${1}.la $(BUILD_DIR)/bin/local/radict$(E) + @echo STATS ${1} ${2} - structs + ${Q}$(RADICT) -F stats.h -M ${4} -p ${1} ${3} > $$@.cache && mv $$@.cache $$@ + +# +# define the "attr_foo" definitions for the dictionary autoload to populate +# +src/stats/${1}/${2}_da_def.c: share/dictionary/${1}/dictionary.stats $(BUILD_DIR)/lib/local/libfreeradius-${1}.la $(BUILD_DIR)/bin/local/radict$(E) + @echo STATS ${1} ${2} - define variables + ${Q}$(RADICT) -F da_def -M ${4} -p ${1} ${3} > $$@.cache && mv $$@.cache $$@ + +# +# define the autoload structures which point to the "attr_foo" defintions +# +src/stats/${1}/${2}_da_autoload.c: share/dictionary/${1}/dictionary.stats $(BUILD_DIR)/lib/local/libfreeradius-${1}.la $(BUILD_DIR)/bin/local/radict$(E) + @echo STATS ${1} ${2} - autoload + ${Q}$(RADICT) -F attr_autoload -M ${4} -p ${1} ${3} > $$@.cache && mv $$@.cache $$@ + +# +# define the linking structure between the statistics structure and the DAs. +# +src/stats/${1}/${2}_stats.c: share/dictionary/${1}/dictionary.stats $(BUILD_DIR)/lib/local/libfreeradius-${1}.la $(BUILD_DIR)/bin/local/radict$(E) + @echo STATS ${1} ${2} - link + ${Q}$(RADICT) -F stats_link -M ${4} -p ${1} ${3} > $$@.cache && mv $$@.cache $$@ + +# +# The output OBJ has to be rebuilt if any of the input files have changed. +# +$(BUILD_DIR)/objs/src/stats/${1}/base.${OBJ_EXT}: src/stats/${1}/${2}_stats.h src/stats/${1}/${2}_da_def.c src/stats/${1}/${2}_da_autoload.c src/stats/${1}/${2}_stats.c + +endef + +SUBMAKEFILES := $(wildcard ${top_srcdir}/src/stats/*/all.mk) diff --git a/src/stats/radius/all.mk b/src/stats/radius/all.mk new file mode 100644 index 00000000000..9ffa551043f --- /dev/null +++ b/src/stats/radius/all.mk @@ -0,0 +1,14 @@ +# +# Makefile +# +# Version: $Id$ +# +TARGET := libfreeradius-radius-stats$(L) + +SOURCES := base.c + +TGT_PREREQS := libfreeradius-util$(L) libfreeradius-radius$(L) + +TGT_POSTCLEAN := $(wildcard src/stats/radius/*.cache) + +$(eval $(call DICT_STATS,radius,auth_serv,mib-2.radiusAuthServ,1.3.6.1.2.1.67.1.1.1.1)) diff --git a/src/stats/radius/auth_serv_da_autoload.c b/src/stats/radius/auth_serv_da_autoload.c new file mode 100644 index 00000000000..b3fa91e6617 --- /dev/null +++ b/src/stats/radius/auth_serv_da_autoload.c @@ -0,0 +1,17 @@ +{ .out = &attr_auth_serv, .name = "mib-2.radiusAuthServ", .type = FR_TYPE_TLV, .dict = &dict_radius }, +{ .out = &attr_auth_serv_ident, .name = ".radiusAuthServIdent", .type = FR_TYPE_STRING, .dict = &dict_radius }, +{ .out = &attr_auth_serv_up_time, .name = ".radiusAuthServUpTime", .type = FR_TYPE_TIME_DELTA, .dict = &dict_radius }, +{ .out = &attr_auth_serv_reset_time, .name = ".radiusAuthServResetTime", .type = FR_TYPE_TIME_DELTA, .dict = &dict_radius }, +{ .out = &attr_auth_serv_config_reset, .name = ".radiusAuthServConfigReset", .type = FR_TYPE_UINT32, .dict = &dict_radius }, +{ .out = &attr_auth_serv_total_access_requests, .name = ".radiusAuthServTotalAccessRequests", .type = FR_TYPE_UINT32, .dict = &dict_radius }, +{ .out = &attr_auth_serv_total_invalid_requests, .name = ".radiusAuthServTotalInvalidRequests", .type = FR_TYPE_UINT32, .dict = &dict_radius }, +{ .out = &attr_auth_serv_total_dup_access_requests, .name = ".radiusAuthServTotalDupAccessRequests", .type = FR_TYPE_UINT32, .dict = &dict_radius }, +{ .out = &attr_auth_serv_total_access_accepts, .name = ".radiusAuthServTotalAccessAccepts", .type = FR_TYPE_UINT32, .dict = &dict_radius }, +{ .out = &attr_auth_serv_total_access_rejects, .name = ".radiusAuthServTotalAccessRejects", .type = FR_TYPE_UINT32, .dict = &dict_radius }, +{ .out = &attr_auth_serv_total_access_challenges, .name = ".radiusAuthServTotalAccessChallenges", .type = FR_TYPE_UINT32, .dict = &dict_radius }, +{ .out = &attr_auth_serv_total_malformed_access_requests, .name = ".radiusAuthServTotalMalformedAccessRequests", .type = FR_TYPE_UINT32, .dict = &dict_radius }, +{ .out = &attr_auth_serv_total_bad_authenticators, .name = ".radiusAuthServTotalBadAuthenticators", .type = FR_TYPE_UINT32, .dict = &dict_radius }, +{ .out = &attr_auth_serv_total_packets_dropped, .name = ".radiusAuthServTotalPacketsDropped", .type = FR_TYPE_UINT32, .dict = &dict_radius }, +{ .out = &attr_auth_serv_total_unknown_types, .name = ".radiusAuthServTotalUnknownTypes", .type = FR_TYPE_UINT32, .dict = &dict_radius }, + + diff --git a/src/stats/radius/auth_serv_da_def.c b/src/stats/radius/auth_serv_da_def.c new file mode 100644 index 00000000000..c5d82dc9bcf --- /dev/null +++ b/src/stats/radius/auth_serv_da_def.c @@ -0,0 +1,17 @@ +static fr_dict_attr_t const *attr_auth_serv; +static fr_dict_attr_t const *attr_auth_serv_ident; +static fr_dict_attr_t const *attr_auth_serv_up_time; +static fr_dict_attr_t const *attr_auth_serv_reset_time; +static fr_dict_attr_t const *attr_auth_serv_config_reset; +static fr_dict_attr_t const *attr_auth_serv_total_access_requests; +static fr_dict_attr_t const *attr_auth_serv_total_invalid_requests; +static fr_dict_attr_t const *attr_auth_serv_total_dup_access_requests; +static fr_dict_attr_t const *attr_auth_serv_total_access_accepts; +static fr_dict_attr_t const *attr_auth_serv_total_access_rejects; +static fr_dict_attr_t const *attr_auth_serv_total_access_challenges; +static fr_dict_attr_t const *attr_auth_serv_total_malformed_access_requests; +static fr_dict_attr_t const *attr_auth_serv_total_bad_authenticators; +static fr_dict_attr_t const *attr_auth_serv_total_packets_dropped; +static fr_dict_attr_t const *attr_auth_serv_total_unknown_types; + + diff --git a/src/stats/radius/auth_serv_stats.c b/src/stats/radius/auth_serv_stats.c new file mode 100644 index 00000000000..f1241664006 --- /dev/null +++ b/src/stats/radius/auth_serv_stats.c @@ -0,0 +1,94 @@ +fr_stats_link_t const fr_stats_link_radius_auth_serv = { + .name = "fr_stats_radius_auth_serv_t", + .root_p = &attr_auth_serv, + .mib = "1.3.6.1.2.1.67.1.1.1.1", + .size = sizeof(fr_stats_radius_auth_serv_t), + .num_elements = 14, + .entry = { + { + .da_p = &attr_auth_serv_ident, + .type = FR_TYPE_STRING, + .offset = offsetof(fr_stats_radius_auth_serv_t, ident), + .size = 0, + }, + { + .da_p = &attr_auth_serv_up_time, + .type = FR_TYPE_TIME_DELTA, + .offset = offsetof(fr_stats_radius_auth_serv_t, up_time), + .size = 4, + }, + { + .da_p = &attr_auth_serv_reset_time, + .type = FR_TYPE_TIME_DELTA, + .offset = offsetof(fr_stats_radius_auth_serv_t, reset_time), + .size = 4, + }, + { + .da_p = &attr_auth_serv_config_reset, + .type = FR_TYPE_UINT32, + .offset = offsetof(fr_stats_radius_auth_serv_t, config_reset), + .size = 4, + }, + { + .da_p = &attr_auth_serv_total_access_requests, + .type = FR_TYPE_UINT32, + .offset = offsetof(fr_stats_radius_auth_serv_t, total_access_requests), + .size = 4, + }, + { + .da_p = &attr_auth_serv_total_invalid_requests, + .type = FR_TYPE_UINT32, + .offset = offsetof(fr_stats_radius_auth_serv_t, total_invalid_requests), + .size = 4, + }, + { + .da_p = &attr_auth_serv_total_dup_access_requests, + .type = FR_TYPE_UINT32, + .offset = offsetof(fr_stats_radius_auth_serv_t, total_dup_access_requests), + .size = 4, + }, + { + .da_p = &attr_auth_serv_total_access_accepts, + .type = FR_TYPE_UINT32, + .offset = offsetof(fr_stats_radius_auth_serv_t, total_access_accepts), + .size = 4, + }, + { + .da_p = &attr_auth_serv_total_access_rejects, + .type = FR_TYPE_UINT32, + .offset = offsetof(fr_stats_radius_auth_serv_t, total_access_rejects), + .size = 4, + }, + { + .da_p = &attr_auth_serv_total_access_challenges, + .type = FR_TYPE_UINT32, + .offset = offsetof(fr_stats_radius_auth_serv_t, total_access_challenges), + .size = 4, + }, + { + .da_p = &attr_auth_serv_total_malformed_access_requests, + .type = FR_TYPE_UINT32, + .offset = offsetof(fr_stats_radius_auth_serv_t, total_malformed_access_requests), + .size = 4, + }, + { + .da_p = &attr_auth_serv_total_bad_authenticators, + .type = FR_TYPE_UINT32, + .offset = offsetof(fr_stats_radius_auth_serv_t, total_bad_authenticators), + .size = 4, + }, + { + .da_p = &attr_auth_serv_total_packets_dropped, + .type = FR_TYPE_UINT32, + .offset = offsetof(fr_stats_radius_auth_serv_t, total_packets_dropped), + .size = 4, + }, + { + .da_p = &attr_auth_serv_total_unknown_types, + .type = FR_TYPE_UINT32, + .offset = offsetof(fr_stats_radius_auth_serv_t, total_unknown_types), + .size = 4, + }, + }, +}; + diff --git a/src/stats/radius/auth_serv_stats.h b/src/stats/radius/auth_serv_stats.h new file mode 100644 index 00000000000..4005938ecbb --- /dev/null +++ b/src/stats/radius/auth_serv_stats.h @@ -0,0 +1,24 @@ +/* + * radiusAuthServ + */ +typedef struct { + char *ident; + fr_time_delta_t up_time; + fr_time_delta_t reset_time; + uint32_t config_reset; + uint32_t total_access_requests; + uint32_t total_invalid_requests; + uint32_t total_dup_access_requests; + uint32_t total_access_accepts; + uint32_t total_access_rejects; + uint32_t total_access_challenges; + uint32_t total_malformed_access_requests; + uint32_t total_bad_authenticators; + uint32_t total_packets_dropped; + uint32_t total_unknown_types; +} fr_stats_radius_auth_serv_t; + +FR_STATS_TYPEDEF(radius_auth_serv); + +extern fr_stats_link_t const fr_stats_link_radius_auth_serv; + diff --git a/src/stats/radius/base.c b/src/stats/radius/base.c new file mode 100644 index 00000000000..ee74183691b --- /dev/null +++ b/src/stats/radius/base.c @@ -0,0 +1,64 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * $Id$ + * + * @file protocols/radius/stats/stats.c + * @brief Functions for RADIUS statistics + * + * @copyright 2026 Network RADIUS SAS (legal@networkradius.com) + */ +RCSID("$Id$") + +#include +#include "stats.h" + +static fr_dict_t const *dict_radius; + +/* + * static fr_dict_attr_t const *attr_foo; + */ +#include "auth_serv_da_def.c" + +extern fr_dict_autoload_t libfreeradius_radius_stats_dict[]; +fr_dict_autoload_t libfreeradius_radius_stats_dict[] = { + { .out = &dict_radius, .proto = "radius" }, + + DICT_AUTOLOAD_TERMINATOR +}; + +extern fr_dict_attr_autoload_t libfreeradius_radius_stats_dict_attr[]; +fr_dict_attr_autoload_t libfreeradius_radius_stats_dict_attr[] = { + +#include "auth_serv_da_autoload.c" + + DICT_AUTOLOAD_TERMINATOR +}; + +/* + * Clang accepts this DIAG, but complains about the code unless we have it. + * + * GCC doesn't accept this DIAG, but doesn't complain about the code. + */ +#if defined(__clang__) +DIAG_OFF(gnu-flexible-array-initializer) +#endif + +/* + * Define the fr_stats_link_t for the statistics data structures. + */ +#include "auth_serv_stats.c" diff --git a/src/stats/radius/stats.h b/src/stats/radius/stats.h new file mode 100644 index 00000000000..9cb47ae387a --- /dev/null +++ b/src/stats/radius/stats.h @@ -0,0 +1,38 @@ +#pragma once +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* + * $Id$ + * + * @file protocols/radius/stats/stats.h + * @brief Structures and prototypes for RADIUS statistics + * + * @copyright 2026 Network RADIUS SAS (legal@networkradius.com) + */ +#include + +/* + * The included file defines: + * + * fr_stats_radius_auth_serv_t - the base statistics structure + * + * fr_stats_link_radius_auth_serv - the structure linking the base stats structure to the dictionary + * attributes. + * + * fr_stats_radius_auth_serv_t + */ +#include "auth_serv_stats.h"