The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
unit_test_map.c
Go to the documentation of this file.
1/*
2 * unit_test_map.c Map debugging tool.
3 *
4 * Version: $Id: 312836e002a4b7c7f9c8199d1bf8e54c81d35b13 $
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 *
20 * @copyright 2015 Alan DeKok (aland@freeradius.org)
21 */
22
23RCSID("$Id: 312836e002a4b7c7f9c8199d1bf8e54c81d35b13 $")
24
25#include <freeradius-devel/server/cf_file.h>
26#include <freeradius-devel/server/main_config.h>
27#include <freeradius-devel/server/modpriv.h>
28#include <freeradius-devel/server/module_rlm.h>
29#include <freeradius-devel/util/atexit.h>
30#include <freeradius-devel/util/file.h>
31
32#include <freeradius-devel/util/conf.h>
33
34#ifdef HAVE_GETOPT_H
35# include <getopt.h>
36#endif
37
38#include <assert.h>
39
40#include <freeradius-devel/server/log.h>
41
42#define EXIT_WITH_FAILURE \
43do { \
44 ret = EXIT_FAILURE; \
45 goto cleanup; \
46} while (0)
47
49static fr_dict_t const *dict_radius;
50
53 { .out = &dict_freeradius, .proto = "freeradius" },
54 { .out = &dict_radius, .proto = "radius" },
56};
57
58
59static NEVER_RETURNS void usage(char *argv[])
60{
61 fprintf(stderr, "usage: %s [OPTS] filename ...\n", argv[0]);
62 fprintf(stderr, " -d <confdir> Set user dictionary directory (defaults to " CONFDIR ").\n");
63 fprintf(stderr, " -D <dictdir> Set main dictionary directory (defaults to " DICTDIR ").\n");
64 fprintf(stderr, " -x Debugging mode.\n");
65 fprintf(stderr, " -M Show program version information.\n");
66 fprintf(stderr, " -r <receipt_file> Create the <receipt_file> as a 'success' exit.\n");
67
68 fr_exit_now(EXIT_SUCCESS);
69}
70
71static int process_file(char const *filename)
72{
73 int rcode;
74 char const *name1, *name2;
75 CONF_SECTION *cs;
76 map_list_t list;
77 map_t *map = NULL;
78 char buffer[8192];
79
81
82 tmpl_rules_t parse_rules = {
83 .attr = {
85 .list_def = request_attr_request,
86 .allow_foreign = false, /* tests are in the RADIUS dictionary */
87 }
88 };
89
90 map_list_init(&list);
91
93 if (!config) {
94 fprintf(stderr, "Failed allocating main config");
95 return EXIT_FAILURE;
96 }
97 config->root_cs = cf_section_alloc(config, NULL, "main", NULL);
99
100 if ((cf_file_read(config->root_cs, filename, true) < 0) || (cf_section_pass2(config->root_cs) < 0)) {
101 fprintf(stderr, "unit_test_map: Failed parsing %s\n", filename);
102 fail:
104 return EXIT_FAILURE;
105 }
106
107 main_config_name_set_default(config, "unit_test_map", false);
108
109 /*
110 * Always has to be an "update" section.
111 */
112 cs = cf_section_find(config->root_cs, "update", CF_IDENT_ANY);
113 if (!cs) goto fail;
114
115 /*
116 * Convert the update section to a list of maps.
117 */
118 rcode = map_afrom_cs(cs, &list, cs, &parse_rules, &parse_rules, unlang_fixup_update, NULL, 128);
119 if (rcode < 0) {
120 cf_log_perr(cs, "map_afrom_cs failed");
121 goto fail;
122 }
123 if (map_list_empty(&list)) {
124 cf_log_err(cs, "'update' sections cannot be empty");
125 goto fail;
126 }
127
128 buffer[0] = '\t';
129
130 name1 = cf_section_name1(cs);
131 name2 = cf_section_name2(cs);
132
133 /*
134 * And print it all out.
135 */
136 if (!name2) {
137 printf("%s {\n", name1);
138 } else {
139 printf("%s %s {\n", name1, name2);
140 }
141
142 while ((map = map_list_next(&list, map))) {
143 map_print(&FR_SBUFF_OUT(buffer + 1, sizeof(buffer) - 1), map);
144 puts(buffer);
145 }
146 printf("}\n");
147
148 talloc_free(config->root_cs);
150
151 return EXIT_SUCCESS;
152}
153
154/**
155 *
156 * @hidecallgraph
157 */
158int main(int argc, char *argv[])
159{
160 int c, ret = EXIT_SUCCESS;
161 char const *confdir = CONFDIR;
162 char const *dict_dir = DICTDIR;
163 fr_dict_t *dict = NULL;
164 char const *receipt_file = NULL;
165
166 TALLOC_CTX *autofree;
167
168 /*
169 * Must be called first, so the handler is called last
170 */
172
174
175#ifndef NDEBUG
176 if (fr_fault_setup(autofree, getenv("PANIC_ACTION"), argv[0]) < 0) {
177 fr_perror("unit_test_map");
178 fr_exit(EXIT_FAILURE);
179 }
180#else
182#endif
183
184 /*
185 * Sync wallclock and cpu time so that we can find
186 * uses of fr_time_[to|from]_* where
187 * fr_unix_time_[to|from]_* should be used.
188 *
189 * If the wallclock/cpu offset is 0, then both sets
190 * of macros produce the same result.
191 */
193
194 while ((c = getopt(argc, argv, "d:D:xMhr:")) != -1) switch (c) {
195 case 'd':
196 confdir = optarg;
197 break;
198
199 case 'D':
200 dict_dir = optarg;
201 break;
202
203 case 'x':
204 fr_debug_lvl++;
205 break;
206
207 case 'M':
208 talloc_enable_leak_report();
209 break;
210
211 case 'r':
212 receipt_file = optarg;
213 break;
214
215 case 'h':
216 default:
217 usage(argv);
218 }
219 argc -= (optind - 1);
220 argv += (optind - 1);
221
222 if (receipt_file && (fr_unlink(receipt_file) < 0)) {
223 fr_perror("unit_test_map");
225 }
226
227 /*
228 * Mismatch between the binary and the libraries it depends on
229 */
231 fr_perror("unit_test_map");
233 }
234
235 if (!fr_dict_global_ctx_init(NULL, true, dict_dir)) {
236 fr_perror("unit_test_map");
238 }
239
241 fr_perror("unit_test_map");
243 }
244
245 /*
246 * Load the custom dictionary
247 */
248 if (fr_dict_read(dict, confdir, FR_DICTIONARY_FILE) == -1) {
249 fr_strerror_const_push("Failed to initialize the dictionaries");
250 fr_perror("unit_test_map");
252 }
253
255 fr_perror("unit_test_map");
257 }
258
259 if (request_global_init() < 0) {
260 fr_perror("unit_test_module");
262 }
263
264 if (argc < 2) {
265 ret = process_file("-");
266
267 } else {
268 int i;
269
270 for (i = 1; i < argc; i++) {
271 ret = process_file(argv[i]);
272 if (ret < 0) break;
273 }
274 }
275
276 if (ret < 0) ret = 1; /* internal to Unix process return code */
277
278cleanup:
279 /*
280 * Ensure all thread local memory is cleaned up
281 * at the appropriate time. This emulates what's
282 * done with worker/network threads in the
283 * scheduler.
284 */
286
287 /*
288 * Free any autoload dictionaries
289 */
291 fr_perror("unit_test_map");
292 ret = EXIT_FAILURE;
293 }
294
295 if (fr_dict_free(&dict, __FILE__) < 0) {
296 fr_perror("unit_test_map");
297 ret = EXIT_FAILURE;
298 }
299
300 if (receipt_file && (ret == EXIT_SUCCESS) && (fr_touch(NULL, receipt_file, 0644, true, 0755) <= 0)) {
301 fr_perror("unit_test_map");
302 ret = EXIT_FAILURE;
303 }
304
305 /*
306 * Ensure our atexit handlers run before any other
307 * atexit handlers registered by third party libraries.
308 */
310
311 return ret;
312}
static int const char char buffer[256]
Definition acutest.h:578
int fr_atexit_global_setup(void)
Setup the atexit handler, should be called at the start of a program's execution.
Definition atexit.c:160
int fr_atexit_global_trigger_all(void)
Cause all global free triggers to fire.
Definition atexit.c:286
#define fr_atexit_thread_trigger_all(...)
Definition atexit.h:233
static TALLOC_CTX * autofree
Definition fuzzer.c:46
#define RCSID(id)
Definition build.h:487
#define NEVER_RETURNS
Should be placed before the function return type.
Definition build.h:315
void cf_section_set_unlang(CONF_SECTION *cs)
Definition cf_file.c:4065
int cf_file_read(CONF_SECTION *cs, char const *filename, bool root)
Definition cf_file.c:3637
int cf_section_pass2(CONF_SECTION *cs)
Definition cf_file.c:982
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1184
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1170
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition cf_util.c:1027
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:288
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:295
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition cf_util.h:146
#define CF_IDENT_ANY
Definition cf_util.h:78
void fr_disable_null_tracking_on_free(TALLOC_CTX *ctx)
Disable the null tracking context when a talloc chunk is freed.
Definition debug.c:1021
int fr_fault_setup(TALLOC_CTX *ctx, char const *cmd, char const *program)
Registers signal handlers to execute panic_action on fatal signal.
Definition debug.c:1056
#define fr_exit(_x)
Exit, producing a log message in debug builds.
Definition debug.h:220
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
Definition debug.h:226
static NEVER_RETURNS void usage(void)
Definition dhcpclient.c:114
#define fr_dict_autofree(_to_free)
Definition dict.h:917
int fr_dict_internal_afrom_file(fr_dict_t **out, char const *dict_subdir, char const *dependent))
(Re-)Initialize the special internal dictionary
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:307
int fr_dict_read(fr_dict_t *dict, char const *dict_dir, char const *filename))
Read supplementary attribute definitions into an existing dictionary.
int fr_dict_free(fr_dict_t **dict, char const *dependent)
Decrement the reference count on a previously loaded dictionary.
Definition dict_util.c:4330
#define fr_dict_autoload(_to_load)
Definition dict.h:914
#define DICT_AUTOLOAD_TERMINATOR
Definition dict.h:313
fr_dict_gctx_t * fr_dict_global_ctx_init(TALLOC_CTX *ctx, bool free_at_exit, char const *dict_dir))
Initialise the global protocol hashes.
Definition dict_util.c:4714
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:306
talloc_free(hp)
int map_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, CONF_SECTION *cs, tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules, map_validate_t validate, void *uctx, unsigned int max)
Convert a config section into an attribute map.
Definition map.c:1136
ssize_t map_print(fr_sbuff_t *out, map_t const *map)
Print a map to a string.
Definition map.c:2387
int fr_unlink(char const *filename)
Remove a regular file from the filesystem.
Definition file.c:367
ssize_t fr_touch(int *fd_out, char const *filename, mode_t mode, bool mkdir, mode_t dir_mode)
Create an empty file.
Definition file.c:323
int fr_debug_lvl
Definition log.c:40
main_config_t * main_config_alloc(TALLOC_CTX *ctx)
Allocate a main_config_t struct, setting defaults.
void main_config_name_set_default(main_config_t *config, char const *name, bool overwrite_config)
Set the server name.
Main server configuration.
Definition main_config.h:51
int unlang_fixup_update(map_t *map, void *ctx)
Validate and fixup a map that's part of an update section.
Definition compile.c:352
static const conf_parser_t config[]
Definition base.c:169
static bool cleanup
Definition radsniff.c:60
fr_dict_attr_t const * request_attr_request
Definition request.c:43
int request_global_init(void)
Definition request.c:596
#define FR_SBUFF_OUT(_start, _len_or_end)
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition tmpl.h:339
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:336
Value pair map.
Definition map.h:77
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Definition tmpl.h:273
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
Definition talloc.h:51
int fr_time_start(void)
Initialize the local time.
Definition time.c:150
static char const * receipt_file
int main(int argc, char *argv[])
fr_dict_autoload_t unit_test_module_dict[]
static fr_dict_t const * dict_freeradius
static int process_file(char const *filename)
static fr_dict_t const * dict_radius
#define EXIT_WITH_FAILURE
#define FR_DICTIONARY_FILE
Definition conf.h:7
#define FR_DICTIONARY_INTERNAL_DIR
Definition conf.h:8
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
Definition strerror.c:732
#define fr_strerror_const_push(_msg)
Definition strerror.h:227
int fr_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
Definition version.c:40
#define RADIUSD_MAGIC_NUMBER
Definition version.h:81