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: 4dc328019e1dde737efac8a93a36943c05a063af $
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: 4dc328019e1dde737efac8a93a36943c05a063af $")
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" },
55 { NULL }
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 <raddb> Set user dictionary directory (defaults to " RADDBDIR ").\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) < 0) || (cf_section_pass2(config->root_cs) < 0)) {
101 fprintf(stderr, "unit_test_map: Failed parsing %s\n", filename);
102 return EXIT_FAILURE;
103 }
104
105 main_config_name_set_default(config, "unit_test_map", false);
106
107 /*
108 * Always has to be an "update" section.
109 */
110 cs = cf_section_find(config->root_cs, "update", CF_IDENT_ANY);
111 if (!cs) {
112 talloc_free(config->root_cs);
113 return EXIT_FAILURE;
114 }
115
116 /*
117 * Convert the update section to a list of maps.
118 */
119 rcode = map_afrom_cs(cs, &list, cs, &parse_rules, &parse_rules, unlang_fixup_update, NULL, 128);
120 if (rcode < 0) {
121 cf_log_perr(cs, "map_afrom_cs failed");
122 return EXIT_FAILURE; /* message already printed */
123 }
124 if (map_list_empty(&list)) {
125 cf_log_err(cs, "'update' sections cannot be empty");
126 return EXIT_FAILURE;
127 }
128
129 buffer[0] = '\t';
130
131 name1 = cf_section_name1(cs);
132 name2 = cf_section_name2(cs);
133
134 /*
135 * And print it all out.
136 */
137 if (!name2) {
138 printf("%s {\n", name1);
139 } else {
140 printf("%s %s {\n", name1, name2);
141 }
142
143 while ((map = map_list_next(&list, map))) {
144 map_print(&FR_SBUFF_OUT(buffer + 1, sizeof(buffer) - 1), map);
145 puts(buffer);
146 }
147 printf("}\n");
148
149 talloc_free(config->root_cs);
151
152 return EXIT_SUCCESS;
153}
154
155/**
156 *
157 * @hidecallgraph
158 */
159int main(int argc, char *argv[])
160{
161 int c, ret = EXIT_SUCCESS;
162 char const *raddb_dir = RADDBDIR;
163 char const *dict_dir = DICTDIR;
164 fr_dict_t *dict = NULL;
165 char const *receipt_file = NULL;
166
167 TALLOC_CTX *autofree;
168
169 /*
170 * Must be called first, so the handler is called last
171 */
173
175
176#ifndef NDEBUG
177 if (fr_fault_setup(autofree, getenv("PANIC_ACTION"), argv[0]) < 0) {
178 fr_perror("unit_test_map");
179 fr_exit(EXIT_FAILURE);
180 }
181#else
183#endif
184
185 /*
186 * Sync wallclock and cpu time so that we can find
187 * uses of fr_time_[to|from]_* where
188 * fr_unix_time_[to|from]_* should be used.
189 *
190 * If the wallclock/cpu offset is 0, then both sets
191 * of macros produce the same result.
192 */
194
195 while ((c = getopt(argc, argv, "d:D:xMhr:")) != -1) switch (c) {
196 case 'd':
197 raddb_dir = optarg;
198 break;
199
200 case 'D':
201 dict_dir = optarg;
202 break;
203
204 case 'x':
205 fr_debug_lvl++;
206 break;
207
208 case 'M':
209 talloc_enable_leak_report();
210 break;
211
212 case 'r':
213 receipt_file = optarg;
214 break;
215
216 case 'h':
217 default:
218 usage(argv);
219 }
220 argc -= (optind - 1);
221 argv += (optind - 1);
222
223 if (receipt_file && (fr_unlink(receipt_file) < 0)) {
224 fr_perror("unit_test_map");
226 }
227
228 /*
229 * Mismatch between the binary and the libraries it depends on
230 */
232 fr_perror("unit_test_map");
234 }
235
236 if (!fr_dict_global_ctx_init(NULL, true, dict_dir)) {
237 fr_perror("unit_test_map");
239 }
240
242 fr_perror("unit_test_map");
244 }
245
246 /*
247 * Load the custom dictionary
248 */
249 if (fr_dict_read(dict, raddb_dir, FR_DICTIONARY_FILE) == -1) {
250 fr_strerror_const_push("Failed to initialize the dictionaries");
251 fr_perror("unit_test_map");
253 }
254
256 fr_perror("unit_test_map");
258 }
259
260 if (request_global_init() < 0) {
261 fr_perror("unit_test_module");
263 }
264
265 if (argc < 2) {
266 ret = process_file("-");
267
268 } else {
269 ret = process_file(argv[1]);
270 }
271
272 if (ret < 0) ret = 1; /* internal to Unix process return code */
273
274cleanup:
275 /*
276 * Ensure all thread local memory is cleaned up
277 * at the appropriate time. This emulates what's
278 * done with worker/network threads in the
279 * scheduler.
280 */
282
283 /*
284 * Free any autoload dictionaries
285 */
287 fr_perror("unit_test_map");
288 ret = EXIT_FAILURE;
289 }
290
291 if (fr_dict_free(&dict, __FILE__) < 0) {
292 fr_perror("unit_test_map");
293 ret = EXIT_FAILURE;
294 }
295
296 if (receipt_file && (ret == EXIT_SUCCESS) && (fr_touch(NULL, receipt_file, 0644, true, 0755) <= 0)) {
297 fr_perror("unit_test_map");
298 ret = EXIT_FAILURE;
299 }
300
301 /*
302 * Ensure our atexit handlers run before any other
303 * atexit handlers registered by third party libraries.
304 */
306
307 return ret;
308}
static int const char char buffer[256]
Definition acutest.h:576
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
#define RCSID(id)
Definition build.h:483
#define NEVER_RETURNS
Should be placed before the function return type.
Definition build.h:313
void cf_section_set_unlang(CONF_SECTION *cs)
Definition cf_file.c:3752
int cf_file_read(CONF_SECTION *cs, char const *filename)
Definition cf_file.c:3423
int cf_section_pass2(CONF_SECTION *cs)
Definition cf_file.c:755
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:1185
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1171
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:1028
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:289
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:296
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition cf_util.h:140
#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:1207
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:1242
#define fr_exit(_x)
Exit, producing a log message in debug builds.
Definition debug.h:228
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
Definition debug.h:234
static NEVER_RETURNS void usage(void)
Definition dhcpclient.c:114
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:4392
int fr_dict_internal_afrom_file(fr_dict_t **out, char const *internal_name, char const *dependent)
(Re-)Initialize the special internal dictionary
#define fr_dict_autofree(_to_free)
Definition dict.h:853
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:281
int fr_dict_free(fr_dict_t **dict, char const *dependent)
Decrement the reference count on a previously loaded dictionary.
Definition dict_util.c:4024
#define fr_dict_autoload(_to_load)
Definition dict.h:850
int fr_dict_read(fr_dict_t *dict, char const *dict_dir, char const *filename)
Read supplementary attribute definitions into an existing dictionary.
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:280
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 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:1014
ssize_t map_print(fr_sbuff_t *out, map_t const *map)
Print a map to a string.
Definition map.c:2295
talloc_free(reap)
int fr_debug_lvl
Definition log.c:43
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:470
static const conf_parser_t config[]
Definition base.c:183
static TALLOC_CTX * autofree
static bool cleanup
Definition radsniff.c:60
fr_dict_attr_t const * request_attr_request
Definition request.c:45
int request_global_init(void)
Definition request.c:722
#define FR_SBUFF_OUT(_start, _len_or_end)
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition tmpl.h:344
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:341
Value pair map.
Definition map.h:77
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Definition tmpl.h:285
#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
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:733
#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