The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
unit_test_module.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16/**
17 * $Id: 77df6d1b75938de60756e83fea402f4745cf737f $
18 *
19 * @file unit_test_module.c
20 * @brief Module test framework
21 *
22 * @copyright 2000-2018 The FreeRADIUS server project
23 * @copyright 2013 Alan DeKok (aland@freeradius.org)
24 * @copyright 2018 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
25 */
26RCSID("$Id: 77df6d1b75938de60756e83fea402f4745cf737f $")
27
28#include <freeradius-devel/server/base.h>
29#include <freeradius-devel/server/map_proc.h>
30#include <freeradius-devel/server/module_rlm.h>
31#include <freeradius-devel/util/debug.h>
32#include <freeradius-devel/util/rand.h>
33#include <freeradius-devel/util/value.h>
34#include <freeradius-devel/util/strerror.h>
35#include <freeradius-devel/util/sbuff.h>
36#include <freeradius-devel/io/listen.h>
37
38#include <freeradius-devel/tls/base.h>
39#include <freeradius-devel/tls/version.h>
40
41#include <freeradius-devel/unlang/base.h>
42
43#include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
44#include <freeradius-devel/radius/radius.h>
45
46#ifdef HAVE_GETOPT_H
47# include <getopt.h>
48#endif
49
50#define EXIT_WITH_FAILURE \
51do { \
52 ret = EXIT_FAILURE; \
53 goto cleanup; \
54} while (0)
55
56/*
57 * Global variables.
58 */
59static bool filedone = false;
60static int my_debug_lvl = 0;
61
62char const *radiusd_version = RADIUSD_VERSION_BUILD("unit_test_module");
63
66
67#define PROTOCOL_NAME unit_test_module_dict[1].proto
68
71 { .out = &dict_freeradius, .proto = "freeradius" },
72 { .out = &dict_protocol, .proto = "radius" }, /* hacked in-place with '-p protocol' */
73 { NULL }
74};
75
78
81 { .out = &attr_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_protocol },
82 { .out = &attr_net, .name = "Net", .type = FR_TYPE_TLV, .dict = &dict_freeradius },
83
84 { NULL }
85};
86
87/*
88 * Static functions.
89 */
90static void usage(main_config_t const *config, int status);
91
92static fr_client_t *client_alloc(TALLOC_CTX *ctx, char const *ip, char const *name)
93{
94 CONF_SECTION *cs;
95 fr_client_t *client;
96
97 cs = cf_section_alloc(ctx, NULL, "client", name);
98 MEM(cf_pair_alloc(cs, "ipaddr", ip, T_OP_EQ, T_BARE_WORD, T_BARE_WORD));
99 MEM(cf_pair_alloc(cs, "secret", "supersecret", T_OP_EQ, T_BARE_WORD, T_DOUBLE_QUOTED_STRING));
100 MEM(cf_pair_alloc(cs, "nas_type", "test", T_OP_EQ, T_BARE_WORD, T_DOUBLE_QUOTED_STRING));
101 MEM(cf_pair_alloc(cs, "shortname", "test", T_OP_EQ, T_BARE_WORD, T_DOUBLE_QUOTED_STRING));
105
106 client = client_afrom_cs(ctx, cs, NULL, 0);
107 if (!client) {
108 PERROR("Failed creating test client");
109 fr_assert(0);
110 }
111 talloc_steal(client, cs);
112 fr_assert(client);
113
114 return client;
115}
116
118{
119 if (fr_type_is_leaf(vp->vp_type)) {
120 vp->vp_immutable = false;
121
122 return;
123 }
124
125 fr_pair_list_foreach(&vp->vp_group, child) {
126 pair_mutable(child);
127 }
128}
129
130static request_t *request_from_internal(TALLOC_CTX *ctx)
131{
132 request_t *request;
133
134 /*
135 * Create and initialize the new request.
136 */
137 request = request_alloc_internal(ctx, NULL);
138 if (!request->packet) request->packet = fr_packet_alloc(request, false);
139 if (!request->reply) request->reply = fr_packet_alloc(request, false);
140
141 request->packet->socket = (fr_socket_t){
142 .type = SOCK_DGRAM,
143 .inet = {
144 .src_ipaddr = {
145 .af = AF_INET,
146 .prefix = 32,
147 .addr = {
148 .v4 = {
149 .s_addr = htonl(INADDR_LOOPBACK)
150 }
151 }
152 },
153 .src_port = 18120,
154 .dst_ipaddr = {
155 .af = AF_INET,
156 .prefix = 32,
157 .addr = {
158 .v4 = {
159 .s_addr = htonl(INADDR_LOOPBACK)
160 }
161 }
162 },
163 .dst_port = 1812
164 }
165 };
166
167 request->log.dst = talloc_zero(request, log_dst_t);
168 request->log.dst->func = vlog_request;
169 request->log.dst->uctx = &default_log;
170 request->log.dst->lvl = fr_debug_lvl;
171
172 request->master_state = REQUEST_ACTIVE;
173 request->log.lvl = fr_debug_lvl;
174 request->async = talloc_zero(request, fr_async_t);
175
176 if (fr_packet_pairs_from_packet(request->request_ctx, &request->request_pairs, request->packet) < 0) {
177 talloc_free(request);
178 fprintf(stderr, "Failed converting packet IPs to attributes");
179 return NULL;
180 }
181
182 return request;
183}
184
185static request_t *request_from_file(TALLOC_CTX *ctx, FILE *fp, fr_client_t *client, CONF_SECTION *server_cs)
186{
187 fr_pair_t *vp;
188 request_t *request;
189 fr_dcursor_t cursor;
190
191 static int number = 0;
192
193 /*
194 * Create and initialize the new request.
195 */
196 request = request_local_alloc_external(ctx, NULL);
197
198 /*
199 * FIXME - Should be less RADIUS centric, but everything
200 * else assumes RADIUS at the moment so we can fix this later.
201 */
202 request->dict = dict_protocol;
203 if (!request->dict) {
204 fr_strerror_printf_push("%s dictionary failed to load", PROTOCOL_NAME);
205 error:
206 talloc_free(request);
207 return NULL;
208 }
209
210 request->packet = fr_packet_alloc(request, false);
211 if (!request->packet) {
212 fr_strerror_const("No memory");
213 goto error;
214 }
215 request->packet->timestamp = fr_time();
216
217 request->reply = fr_packet_alloc(request, false);
218 if (!request->reply) {
219 fr_strerror_const("No memory");
220 goto error;
221 }
222
223 request->client = client;
224 request->number = number++;
225 request->name = talloc_typed_asprintf(request, "%" PRIu64, request->number);
226 request->master_state = REQUEST_ACTIVE;
227
228 /*
229 * Read packet from fp
230 */
231 if (fr_pair_list_afrom_file(request->request_ctx, dict_protocol, &request->request_pairs, fp, &filedone) < 0) {
232 goto error;
233 }
234
235 /*
236 * Pretend that the attributes came in "over the wire".
237 *
238 * @todo - do this only for protocol attributes, and not internal ones?
239 */
240 fr_pair_list_tainted(&request->request_pairs);
241
242 vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_packet_type);
243 if (!vp) {
244 fr_strerror_printf("Input packet does not specify a Packet-Type");
245 goto error;
246 }
247 /*
248 * Set the defaults for IPs, etc.
249 */
250 request->packet->code = vp->vp_uint32;
251
252 /*
253 * Now delete the packet-type to ensure
254 * the virtual attribute gets used in
255 * the tests.
256 */
257 fr_pair_delete_by_da(&request->request_pairs, attr_packet_type);
258
259 request->packet->socket = (fr_socket_t){
260 .type = SOCK_DGRAM,
261 .inet = {
262 .src_ipaddr = {
263 .af = AF_INET,
264 .prefix = 32,
265 .addr = {
266 .v4 = {
267 .s_addr = htonl(INADDR_LOOPBACK)
268 }
269 }
270 },
271 .src_port = 18120,
272 .dst_ipaddr = {
273 .af = AF_INET,
274 .prefix = 32,
275 .addr = {
276 .v4 = {
277 .s_addr = htonl(INADDR_LOOPBACK)
278 }
279 }
280 },
281 .dst_port = 1812
282 }
283 };
284
285 /*
286 * Fill in the packet header from attributes, and then
287 * re-realize the attributes.
288 */
289 vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_packet_type);
290 if (vp) request->packet->code = vp->vp_uint32;
291
292 fr_packet_net_from_pairs(request->packet, &request->request_pairs);
293
294 /*
295 * The input might have updated only some of the Net.*
296 * attributes. So for consistency, we create all of them
297 * from the packet header.
298 */
299 if (fr_packet_pairs_from_packet(request->request_ctx, &request->request_pairs, request->packet) < 0) {
300 fr_strerror_const("Failed converting packet IPs to attributes");
301 goto error;
302 }
303
304 /*
305 * For laziness in the tests, allow the Net.* to be mutable
306 */
307 for (vp = fr_pair_dcursor_by_ancestor_init(&cursor, &request->request_pairs, attr_net);
308 vp != NULL;
309 vp = fr_dcursor_next(&cursor)) {
311 }
312
313 if (fr_debug_lvl) {
314 for (vp = fr_pair_dcursor_init(&cursor, &request->request_pairs);
315 vp;
316 vp = fr_dcursor_next(&cursor)) {
317 /*
318 * Take this opportunity to verify all the fr_pair_ts are still valid.
319 */
320 if (!talloc_get_type(vp, fr_pair_t)) {
321 ERROR("Expected fr_pair_t pointer got \"%s\"", talloc_get_name(vp));
322
324 fr_assert(0);
325 }
326
327 fr_log(&default_log, L_DBG, __FILE__, __LINE__, "%pP", vp);
328 }
329 }
330
331 /*
332 * Build the reply template from the request.
333 */
334 fr_socket_addr_swap(&request->reply->socket, &request->packet->socket);
335
336 request->reply->id = request->packet->id;
337 request->reply->code = 0; /* UNKNOWN code */
338 memcpy(request->reply->vector, request->packet->vector, sizeof(request->reply->vector));
339 request->reply->data = NULL;
340 request->reply->data_len = 0;
341
342 /*
343 * Debugging
344 */
345 request->log.dst = talloc_zero(request, log_dst_t);
346 request->log.dst->func = vlog_request;
347 request->log.dst->uctx = &default_log;
348 request->log.dst->lvl = fr_debug_lvl;
349
350 request->master_state = REQUEST_ACTIVE;
351 request->log.lvl = fr_debug_lvl;
352 request->async = talloc_zero(request, fr_async_t);
353
354
355 /*
356 * New async listeners
357 */
358 request->async = talloc_zero(request, fr_async_t);
359 unlang_call_push(request, server_cs, UNLANG_TOP_FRAME);
360
361 return request;
362}
363
364
365static void print_packet(FILE *fp, fr_packet_t *packet, fr_pair_list_t *list)
366{
368 fr_log_t log;
369
370 (void) fr_log_init_fp(&log, fp);
371
373 if (dv) {
374 fr_log(&default_log, L_DBG, __FILE__, __LINE__, "Packet-Type = %s", dv->name);
375 } else {
376 fr_log(&default_log, L_DBG, __FILE__, __LINE__, "Packet-Type = %u", packet->code);
377 }
378
379 fr_pair_list_log(&default_log, 2, list);
380}
381
382/*
383 * A common function for reports of too much text when handling xlat
384 * and xlat_expr in do_xlats().
385 * The convolution deals with the edge case of the line being so long
386 * that it plus the surrounding text from the format could won't fit
387 * in the output sbuff, along with the fact that you don't print the
388 * %d or %.*s. OTOH it does include slen, but...
389 * * the format string is 41 characters minus 6 for %d and %.*s
390 * * given that slen reflects text read from line, once slen is
391 * large enough, we know line will fit
392 */
393static inline CC_HINT(always_inline) void too_much_text(fr_sbuff_t *out, ssize_t slen, fr_sbuff_t *line)
394{
395 char const *format = "ERROR offset %d 'Too much text' ::%.*s::";
396
397 (void) fr_sbuff_in_sprintf(out, format, (int) slen,
398 fr_sbuff_remaining(out) - (strlen(format) - 5),
400}
401
402/*
403 * Read a file composed of xlat's and expected results
404 */
405static bool do_xlats(fr_event_list_t *el, request_t *request, char const *filename, FILE *fp)
406{
407 int lineno = 0;
408 ssize_t len;
409 char line_buff[8192];
410 char output_buff[8192];
411 char unescaped[sizeof(output_buff)];
414
415 static fr_sbuff_escape_rules_t unprintables = {
416 .name = "unprintables",
417 .chr = '\\',
418 .esc = {
421 },
422 .do_utf8 = true,
423 .do_oct = true
424 };
425
426 while (fgets(line_buff, sizeof(line_buff), fp) != NULL) {
427 lineno++;
428
429 line = FR_SBUFF_IN(line_buff, sizeof(line_buff));
430 if (!fr_sbuff_adv_to_chr(&line, SIZE_MAX, '\n')) {
431 if (!feof(fp)) {
432 fprintf(stderr, "%s[%d] Line too long\n", filename, lineno);
433 return false;
434 }
435 } else {
436 fr_sbuff_terminate(&line);
437 }
438 line.end = line.p;
439 fr_sbuff_set_to_start(&line);
440
441 /*
442 * Ignore blank lines and comments
443 */
444 fr_sbuff_adv_past_whitespace(&line, SIZE_MAX, NULL);
445 if (*fr_sbuff_current(&line) < ' ') continue;
446 if (fr_sbuff_is_char(&line, '#')) continue;
447
448 /*
449 * Look for "match", as it needs the output_buffer to be left alone.
450 */
451 if (fr_sbuff_adv_past_str_literal(&line, "match ") > 0) {
452 size_t output_len = strlen(output_buff);
453
454 if (!fr_sbuff_is_str(&line, output_buff, output_len) || (output_len != fr_sbuff_remaining(&line))) {
455 fprintf(stderr, "Mismatch at %s[%u]\n\tgot : %s (%zu)\n\texpected : %s (%zu)\n",
456 filename, lineno, output_buff, output_len, fr_sbuff_current(&line), fr_sbuff_remaining(&line));
457 return false;
458 }
459 continue;
460 }
461
462 /*
463 * The rest of the keywords create output.
464 */
465 output_buff[0] = '\0';
466 out = FR_SBUFF_OUT(output_buff, sizeof(output_buff));
467
468 /*
469 * Look for "xlat"
470 */
471 if (fr_sbuff_adv_past_str_literal(&line, "xlat ") > 0) {
472 ssize_t slen;
473 TALLOC_CTX *xlat_ctx = talloc_init_const("xlat");
474 xlat_exp_head_t *head = NULL;
475 fr_sbuff_parse_rules_t p_rules = { .escapes = &fr_value_unescape_double };
476 tmpl_rules_t t_rules = (tmpl_rules_t) {
477 .attr = {
479 .list_def = request_attr_request,
480 .allow_unresolved = true,
481 },
482 .xlat = {
483 .runtime_el = el,
484 },
485 .at_runtime = true,
486 };
487
488
489 slen = xlat_tokenize(xlat_ctx, &head, &line, &p_rules, &t_rules, 0);
490 if (slen <= 0) {
492 fr_sbuff_in_sprintf(&out, "ERROR offset %d '%s'", (int) -slen, fr_strerror());
493 continue;
494 }
495
496 if (fr_sbuff_remaining(&line) > 0) {
498 too_much_text(&out, slen, &line);
499 continue;
500 }
501
502 len = xlat_eval_compiled(unescaped, sizeof(unescaped), request, head, NULL, NULL);
503 if (len < 0) {
504 char const *err = fr_strerror();
506 (void) fr_sbuff_in_sprintf(&out, "ERROR expanding xlat: %s", *err ? err : "no error provided");
507 continue;
508 }
509
510 /*
511 * Escape the output as if it were a double quoted string.
512 */
513 fr_sbuff_in_escape(&out, unescaped, len, &unprintables);
514
515 TALLOC_FREE(xlat_ctx); /* also frees 'head' */
516 continue;
517 }
518
519 /*
520 * Look for "xlat_expr"
521 */
522 if (fr_sbuff_adv_past_str_literal(&line, "xlat_expr ") > 0) {
523 ssize_t slen;
524 TALLOC_CTX *xlat_ctx = talloc_init_const("xlat");
525 xlat_exp_head_t *head = NULL;
526
528 &line,
529 NULL,
530 &(tmpl_rules_t) {
531 .attr = {
532 .dict_def = dict_protocol,
533 .list_def = request_attr_request,
534 .allow_unresolved = true,
535 },
536 .xlat = {
537 .runtime_el = el,
538 },
539 .at_runtime = true,
540 });
541 if (slen <= 0) {
543 fr_sbuff_in_sprintf(&out, "ERROR offset %d '%s'", (int) -slen, fr_strerror());
544 continue;
545 }
546
547 if (fr_sbuff_remaining(&line) > 0) {
549 too_much_text(&out, slen, &line);
550 continue;
551 }
552
553 if (xlat_resolve(head, NULL) < 0) {
555 (void) fr_sbuff_in_sprintf(&out, "ERROR resolving xlat: %s", fr_strerror());
556 continue;
557 }
558
559 len = xlat_eval_compiled(unescaped, sizeof(unescaped), request, head, NULL, NULL);
560 if (len < 0) {
561 char const *err = fr_strerror();
563 (void) fr_sbuff_in_sprintf(&out, "ERROR expanding xlat: %s", *err ? err : "no error provided");
564 continue;
565 }
566
567 /*
568 * Escape the output as if it were a double quoted string.
569 */
570 fr_sbuff_in_escape(&out, unescaped, len, &unprintables);
571
572 TALLOC_FREE(xlat_ctx); /* also frees 'head' */
573 continue;
574 }
575
576 fprintf(stderr, "Unknown keyword in %s[%d]\n", filename, lineno);
577 return false;
578 }
579
580 return true;
581}
582
583/*
584 * Verify the result of the map.
585 */
586static int map_proc_verify(CONF_SECTION *cs, UNUSED void const *mod_inst, UNUSED void *proc_inst,
587 tmpl_t const *src, UNUSED map_list_t const *maps)
588{
589 if (!src) {
590 cf_log_err(cs, "Missing source");
591
592 return -1;
593 }
594
595 return 0;
596}
597
598static unlang_action_t mod_map_proc(rlm_rcode_t *p_result, UNUSED void const *mod_inst, UNUSED void *proc_inst,
599 UNUSED request_t *request, UNUSED fr_value_box_list_t *src,
600 UNUSED map_list_t const *maps)
601{
603}
604
605static request_t *request_clone(request_t *old, int number, CONF_SECTION *server_cs)
606{
607 request_t *request;
608
609 request = request_alloc_internal(NULL, NULL);
610 if (!request) return NULL;
611
612 if (!request->packet) request->packet = fr_packet_alloc(request, false);
613 if (!request->reply) request->reply = fr_packet_alloc(request, false);
614
615 memcpy(request->packet, old->packet, sizeof(*request->packet));
616 (void) fr_pair_list_copy(request->request_ctx, &request->request_pairs, &old->request_pairs);
617 request->packet->timestamp = fr_time();
618 request->number = number;
619 request->name = talloc_typed_asprintf(request, "%" PRIu64, request->number);
620
621 unlang_call_push(request, server_cs, UNLANG_TOP_FRAME);
622
623 request->master_state = REQUEST_ACTIVE;
624 request->dict = old->dict;
625
626 return request;
627}
628
630{
631 request_t *request = talloc_get_type_abort(uctx, request_t);
633}
634
635/**
636 *
637 * @hidecallgraph
638 */
639int main(int argc, char *argv[])
640{
641 int ret = EXIT_SUCCESS;
642 int c;
643 int count = 1;
644 const char *input_file = NULL;
645 const char *xlat_input_file = NULL;
646 const char *output_file = NULL;
647 const char *filter_file = NULL;
648 FILE *fp = NULL;
649 request_t *request = NULL;
650 fr_pair_t *vp;
651 fr_pair_list_t filter_vps;
652 bool xlat_only = false;
653 fr_event_list_t *el = NULL;
654 fr_event_timer_t const *cancel_timer = NULL;
655 fr_client_t *client = NULL;
656 fr_dict_t *dict = NULL;
657 fr_dict_t const *dict_check;
658 char const *receipt_file = NULL;
659
660 TALLOC_CTX *autofree;
661 TALLOC_CTX *thread_ctx;
662
663 char *p;
665
666 CONF_SECTION *server_cs;
667
668#ifndef NDEBUG
669 size_t memory_used_before = 0;
670 size_t memory_used_after = 0;
671#endif
672 virtual_server_t const *vs;
673
674 fr_pair_list_init(&filter_vps);
675
676 /*
677 * Must be called first, so the handler is called last
678 */
680
682 thread_ctx = talloc_new(autofree);
683
685 if (!config) {
686 fr_perror("unit_test_module");
687 fr_exit_now(EXIT_FAILURE);
688 }
689
690 p = strrchr(argv[0], FR_DIR_SEP);
691 if (!p) {
692 main_config_name_set_default(config, argv[0], false);
693 } else {
695 }
696
698
699 /*
700 * If the server was built with debugging enabled always install
701 * the basic fatal signal handlers.
702 */
703#ifndef NDEBUG
704 if (fr_fault_setup(autofree, getenv("PANIC_ACTION"), argv[0]) < 0) {
705 fr_perror("%s", config->name);
706 fr_exit_now(EXIT_FAILURE);
707 }
708#else
710#endif
711
712 fr_debug_lvl = 0;
714
715 /*
716 * The tests should have only IPs, not host names.
717 */
719
720 /*
721 * We always log to stdout.
722 */
724 default_log.fd = STDOUT_FILENO;
726
727 /* Process the options. */
728 while ((c = getopt(argc, argv, "c:d:D:f:hi:I:mMn:o:p:r:S:xXz")) != -1) {
729 switch (c) {
730 case 'c':
731 count = atoi(optarg);
732 break;
733
734 case 'd':
736 break;
737
738 case 'D':
740 break;
741
742 case 'f':
743 filter_file = optarg;
744 break;
745
746 case 'h':
747 usage(config, EXIT_SUCCESS);
748 break;
749
750 case 'i':
751 input_file = optarg;
752 break;
753
754 case 'I':
755 xlat_input_file = optarg;
756 xlat_only = true;
757 break;
758
759 case 'M':
760 talloc_enable_leak_report();
761 break;
762
763 case 'n':
764 config->name = optarg;
765 break;
766
767 case 'o':
768 output_file = optarg;
769 break;
770
771 case 'p':
772 PROTOCOL_NAME = optarg;
773 break;
774
775 case 'r':
776 receipt_file = optarg;
777 break;
778
779 case 'S': /* Migration support */
780 if (main_config_parse_option(optarg) < 0) {
781 fprintf(stderr, "%s: Unknown configuration option '%s'\n",
782 config->name, optarg);
783 fr_exit_now(EXIT_FAILURE);
784 }
785 break;
786
787 case 'X':
788 fr_debug_lvl += 2;
790 break;
791
792 case 'x':
793 fr_debug_lvl++;
794 if (fr_debug_lvl > 2) default_log.print_level = true;
795 break;
796
797 case 'z':
798 my_debug_lvl++;
799 break;
800
801 default:
802 usage(config, EXIT_FAILURE);
803 break;
804 }
805 }
806
807 if (receipt_file && (fr_unlink(receipt_file) < 0)) {
808 fr_perror("%s", config->name);
810 }
811
812#ifdef WITH_TLS
813 /*
814 * Mismatch between build time OpenSSL and linked SSL, better to die
815 * here than segfault later.
816 */
818
819 /*
820 * Initialising OpenSSL once, here, is safer than having individual modules do it.
821 * Must be called before display_version to ensure relevant engines are loaded.
822 *
823 * fr_openssl_init() must be called before *ANY* OpenSSL functions are used, which is why
824 * it's called so early.
825 */
826 if (fr_openssl_init() < 0) EXIT_WITH_FAILURE;
827#endif
828
830
831 /*
832 * Mismatch between the binary and the libraries it depends on
833 */
835 fr_perror("%s", config->name);
836 ret = EXIT_FAILURE;
837 goto cleanup;
838 }
839
840 /*
841 * Initialize the DL infrastructure, which is used by the
842 * config file parser.
843 */
844 modules_init(config->lib_dir);
845
846 if (!fr_dict_global_ctx_init(NULL, true, config->dict_dir)) {
847 fr_perror("%s", config->name);
849 }
850
852 fr_perror("%s", config->name);
854 }
855
856#ifdef WITH_TLS
857 if (fr_tls_dict_init() < 0) EXIT_WITH_FAILURE;
858#endif
859
860 /*
861 * Load the custom dictionary
862 */
863 if (fr_dict_read(dict, config->raddb_dir, FR_DICTIONARY_FILE) == -1) {
864 PERROR("Failed to initialize the dictionaries");
866 }
867
869 fr_perror("%s", config->name);
871 }
873 fr_perror("%s", config->name);
875 }
876
877 if (request_global_init() < 0) {
878 fr_perror("unit_test_module");
880 }
881
882 if (map_proc_register(NULL, NULL, "test-fail", mod_map_proc, map_proc_verify, 0, 0) < 0) {
884 }
885
886 /*
887 * Initialise the interpreter, registering operations.
888 * This initialises
889 */
890 if (unlang_global_init() < 0) {
891 fr_perror("%s", config->name);
893 }
894
895 /*
896 * Ensure that we load the correct virtual server for the
897 * protocol, if necessary.
898 */
899 if (!getenv("PROTOCOL")) {
900 setenv("PROTOCOL", PROTOCOL_NAME, true);
901 }
902
903 /*
904 * Setup the global structures for module lists
905 */
906 if (modules_rlm_init() < 0) {
907 fr_perror("%s", config->name);
909 }
910 if (virtual_servers_init() < 0) {
911 fr_perror("%s", config->name);
913 }
914
915 if (main_config_init(config) < 0) {
917 }
918
919 /*
920 * Create a dummy client on 127.0.0.1, if one doesn't already exist.
921 */
922 client = client_find(NULL, &(fr_ipaddr_t) { .af = AF_INET, .prefix = 32, .addr.v4.s_addr = htonl(INADDR_LOOPBACK) },
923 IPPROTO_IP);
924 if (!client) {
925 client = client_alloc(NULL, "127.0.0.1", "test");
926 client_add(NULL, client);
927 }
928
929 if (server_init(config->root_cs, config->raddb_dir, dict) < 0) EXIT_WITH_FAILURE;
930
931 vs = virtual_server_find("default");
932 if (!vs) {
933 ERROR("Cannot find virtual server 'default'");
935 }
936
937 server_cs = virtual_server_cs(vs);
938
939 /*
940 * Do some sanity checking.
941 */
942 dict_check = virtual_server_dict_by_name("default");
943 if (!dict_check || !fr_dict_compatible(dict_check, dict_protocol)) {
944 ERROR("Virtual server namespace does not match requested namespace '%s'", PROTOCOL_NAME);
946 }
947
948 /*
949 * Create a dummy event list
950 */
951 el = fr_event_list_alloc(NULL, NULL, NULL);
952 fr_assert(el != NULL);
953
954 /*
955 * Simulate thread specific instantiation
956 */
959 if (xlat_thread_instantiate(thread_ctx, el) < 0) EXIT_WITH_FAILURE;
960 unlang_thread_instantiate(thread_ctx);
961
962 /*
963 * Set the panic action (if required)
964 */
965 {
966 char const *panic_action = NULL;
967
968 panic_action = getenv("PANIC_ACTION");
969 if (!panic_action) panic_action = config->panic_action;
970
971 if (panic_action && (fr_fault_setup(autofree, panic_action, argv[0]) < 0)) {
972 fr_perror("%s", config->name);
974 }
975 }
976
977 setlinebuf(stdout); /* unbuffered output */
978
979#ifndef NDEBUG
980 memory_used_before = talloc_total_size(autofree);
981#endif
982
983 if (!input_file && !xlat_only) input_file = "-";
984
985 if (input_file) {
986 if (strcmp(input_file, "-") == 0) {
987 fp = stdin;
988 } else {
989 fp = fopen(input_file, "r");
990 if (!fp) {
991 fprintf(stderr, "Failed reading %s: %s\n",
992 input_file, fr_syserror(errno));
994 }
995 }
996
997 /*
998 * Grab the VPs from stdin, or from the file.
999 */
1000 request = request_from_file(autofree, fp, client, server_cs);
1001 if (!request) {
1002 fr_perror("Failed reading input from %s", input_file);
1004 }
1005 } else {
1007 }
1008
1009 /*
1010 * For simplicity, read xlat's.
1011 */
1012 if (xlat_only) {
1013 if (fp && (fp != stdin)) fclose(fp);
1014
1015 fp = fopen(xlat_input_file, "r");
1016 if (!fp) {
1017 fprintf(stderr, "Failed reading %s: %s\n",
1018 xlat_input_file, fr_syserror(errno));
1020 }
1021
1022 if (!do_xlats(el, request, xlat_input_file, fp)) ret = EXIT_FAILURE;
1023 if (input_file) fclose(fp);
1024 goto cleanup;
1025 }
1026
1027 /*
1028 * No filter file, OR there's no more input, OR we're
1029 * reading from a file, and it's different from the
1030 * filter file.
1031 */
1032 if (!filter_file || filedone ||
1033 ((input_file != NULL) && (strcmp(filter_file, input_file) != 0))) {
1034 if (output_file) {
1035 if (fp && (fp != stdin)) fclose(fp);
1036 fp = NULL;
1037 }
1038 filedone = false;
1039 }
1040
1041 /*
1042 * There is a filter file. If necessary, open it. If we
1043 * already are reading it via "input_file", then we don't
1044 * need to re-open it.
1045 */
1046 if (filter_file) {
1047 if (!fp) {
1048 fp = fopen(filter_file, "r");
1049 if (!fp) {
1050 fprintf(stderr, "Failed reading %s: %s\n", filter_file, fr_syserror(errno));
1052 }
1053 }
1054
1055 if (fr_pair_list_afrom_file(request->request_ctx, dict_protocol, &filter_vps, fp, &filedone) < 0) {
1056 fr_perror("Failed reading attributes from %s", filter_file);
1058 }
1059
1060 /*
1061 * Filter files can't be empty.
1062 */
1063 if (fr_pair_list_empty(&filter_vps)) {
1064 fr_perror("No attributes in filter file %s", filter_file);
1066 }
1067
1068 /*
1069 * FIXME: loop over input packets.
1070 */
1071 fclose(fp);
1072 }
1073
1074 if (count == 1) {
1075 fr_event_timer_in(request, el, &cancel_timer, config->max_request_time, cancel_request, request);
1077
1078 } else {
1079 int i;
1080 request_t *cached = request;
1081
1082 for (i = 0; i < count; i++) {
1083#ifndef NDEBUG
1084 size_t request_used_before, request_used_after;
1085#endif
1086
1087 request = request_clone(cached, i, server_cs);
1088
1089#ifndef NDEBUG
1090 request_used_before = talloc_total_size(autofree);
1091
1092 /*
1093 * Artificially limit the number of instructions which are run.
1094 */
1095 if (config->ins_max) {
1096 if (config->ins_countup) {
1097 request->ins_max = i + 1;
1098 } else {
1099 request->ins_max = config->ins_max;
1100 }
1101
1102 if (request->ins_max < 10) request->ins_max = 10;
1103
1104 request->ins_count = 0;
1105 }
1106#endif
1107
1108 fr_event_timer_in(request, el, &cancel_timer, config->max_request_time, cancel_request, request);
1110 talloc_free(request);
1111
1112#ifndef NDEBUG
1113 request_used_after = talloc_total_size(autofree);
1114 fr_assert(request_used_after == request_used_before);
1115#endif
1116 }
1117
1118 request = cached;
1119 }
1120
1121 if (!output_file || (strcmp(output_file, "-") == 0)) {
1122 fp = stdout;
1123 } else {
1124 fp = fopen(output_file, "w");
1125 if (!fp) {
1126 fprintf(stderr, "Failed writing %s: %s\n", output_file, fr_syserror(errno));
1127 goto cleanup;
1128 }
1129 }
1130
1131 print_packet(fp, request->reply, &request->reply_pairs);
1132
1133 if (output_file) fclose(fp);
1134
1135 /*
1136 * Update the list with the response type, so that it can
1137 * be matched in filters.
1138 *
1139 * Some state machines already include a response Packet-Type
1140 * so we need to try and update it, else we end up with two!
1141 */
1142 if (!fr_pair_list_empty(&filter_vps)) {
1143 fr_pair_t const *failed[2];
1144
1146 vp->vp_uint32 = request->reply->code;
1147
1148
1149 if (!fr_pair_validate(failed, &filter_vps, &request->reply_pairs)) {
1150 fr_pair_validate_debug(failed);
1151 fr_perror("Output file %s does not match attributes in filter %s",
1152 output_file ? output_file : "-", filter_file);
1153 ret = EXIT_FAILURE;
1154 goto cleanup;
1155 }
1156 }
1157
1158 INFO("Exiting normally");
1159
1160cleanup:
1161 talloc_free(request);
1162
1163 /*
1164 * No leaks.
1165 */
1166#ifndef NDEBUG
1167 memory_used_after = talloc_total_size(autofree);
1168 if (memory_used_after != memory_used_before) {
1169 printf("WARNING: May have leaked memory (%zd - %zd = %zd)\n",
1170 memory_used_after, memory_used_before, memory_used_after - memory_used_before);
1171 }
1172#endif
1173
1174 map_proc_unregister("test-fail");
1175
1176 /*
1177 * Free thread data
1178 */
1179 talloc_free(thread_ctx);
1180
1181 /*
1182 * Ensure all thread local memory is cleaned up
1183 * at the appropriate time. This emulates what's
1184 * done with worker/network threads in the
1185 * scheduler.
1186 */
1188
1189 /*
1190 * Give processes a chance to exit
1191 */
1193
1194 /*
1195 * Free the event list.
1196 */
1197 talloc_free(el);
1198
1199 /*
1200 * Ensure all thread local memory is cleaned up
1201 * at the appropriate time. This emulates what's
1202 * done with worker/network threads in the
1203 * scheduler.
1204 */
1206
1207 server_free();
1208
1209 /*
1210 * Virtual servers need to be freed before modules
1211 * as state entries containing data with module-specific
1212 * destructors may exist.
1213 */
1215
1216 /*
1217 * Free modules, this needs to be done explicitly
1218 * because some libraries used by modules use atexit
1219 * handlers registered after ours, and they may deinit
1220 * themselves before we free the modules and cause
1221 * crashes on exit.
1222 */
1224
1225 /*
1226 * And now nothing should be left anywhere except the
1227 * parsed configuration items.
1228 */
1230
1231#ifdef WITH_TLS
1232 fr_tls_dict_free();
1233#endif
1234
1235 /*
1236 * Free any autoload dictionaries
1237 */
1239
1240 /*
1241 * Free our explicitly loaded internal dictionary
1242 */
1243 if (fr_dict_free(&dict, __FILE__) < 0) {
1244 fr_perror("unit_test_module - dict");
1245 ret = EXIT_FAILURE;
1246 }
1247
1248 /*
1249 * Free any openssl resources and the TLS dictionary
1250 */
1251#ifdef WITH_TLS
1252 fr_openssl_free();
1253#endif
1254
1255 if (receipt_file && (ret == EXIT_SUCCESS) && (fr_touch(NULL, receipt_file, 0644, true, 0755) <= 0)) {
1256 fr_perror("unit_test_module");
1257 ret = EXIT_FAILURE;
1258 }
1259
1260 if (talloc_free(autofree) < 0) {
1261 fr_perror("unit_test_module - autofree");
1262 ret = EXIT_FAILURE;
1263 }
1264
1265 /*
1266 * Ensure our atexit handlers run before any other
1267 * atexit handlers registered by third party libraries.
1268 */
1270
1271 return ret;
1272}
1273
1274
1275/*
1276 * Display the syntax for starting this program.
1277 */
1278static NEVER_RETURNS void usage(main_config_t const *config, int status)
1279{
1280 FILE *output = status ? stderr : stdout;
1281
1282 fprintf(output, "Usage: %s [options]\n", config->name);
1283 fprintf(output, "Options:\n");
1284 fprintf(output, " -c <count> Run packets through the interpreter <count> times\n");
1285 fprintf(output, " -d <raddb_dir> Configuration files are in \"raddb_dir/*\".\n");
1286 fprintf(output, " -D <dict_dir> Dictionary files are in \"dict_dir/*\".\n");
1287 fprintf(output, " -f <file> Filter reply against attributes in 'file'.\n");
1288 fprintf(output, " -h Print this help message.\n");
1289 fprintf(output, " -i <file> File containing request attributes.\n");
1290 fprintf(output, " -m On SIGINT or SIGQUIT exit cleanly instead of immediately.\n");
1291 fprintf(output, " -n <name> Read raddb/name.conf instead of raddb/radiusd.conf.\n");
1292 fprintf(output, " -o <file> Output file for the reply.\n");
1293 fprintf(output, " -p <radius|...> Define which protocol namespace is used to read the file\n");
1294 fprintf(output, " Use radius, dhcpv4, or dhcpv6\n");
1295 fprintf(output, " -X Turn on full debugging.\n");
1296 fprintf(output, " -x Turn on additional debugging. (-xx gives more debugging).\n");
1297 fprintf(output, " -r <receipt_file> Create the <receipt_file> as a 'success' exit.\n");
1298
1299 fr_exit_now(status);
1300}
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
int const char int line
Definition acutest.h:702
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
#define UNUSED
Definition build.h:315
unlang_action_t unlang_call_push(request_t *request, CONF_SECTION *server_cs, bool top_frame)
Push a call frame onto the stack.
Definition call.c:147
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
CONF_PAIR * cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value, fr_token_t op, fr_token_t lhs_quote, fr_token_t rhs_quote)
Allocate a CONF_PAIR.
Definition cf_util.c:1279
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:289
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition cf_util.h:140
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition dcursor.h:288
static char panic_action[512]
The command to execute when panicking.
Definition debug.c:96
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_log_talloc_report(TALLOC_CTX const *ctx)
Generate a talloc memory report for a context and print to stderr/stdout.
Definition debug.c:1147
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
void fr_talloc_fault_setup(void)
Register talloc fault handlers.
Definition debug.c:1223
#define MEM(x)
Definition debug.h:36
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
Definition debug.h:234
void dependency_version_print(void)
Definition dependency.c:376
#define ERROR(fmt,...)
Definition dhcpclient.c:41
static NEVER_RETURNS void usage(void)
Definition dhcpclient.c:114
fr_dict_enum_value_t * fr_dict_enum_by_value(fr_dict_attr_t const *da, fr_value_box_t const *value)
Lookup the structure representing an enum value in a fr_dict_attr_t.
Definition dict_util.c:3353
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:4396
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:852
static fr_slen_t err
Definition dict.h:823
bool fr_dict_compatible(fr_dict_t const *dict1, fr_dict_t const *dict2)
See if two dictionaries have the same end parent.
Definition dict_util.c:2623
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:268
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:4028
int fr_dict_attr_autoload(fr_dict_attr_autoload_t const *to_load)
Process a dict_attr_autoload element to load/verify a dictionary attribute.
Definition dict_util.c:4094
#define fr_dict_autoload(_to_load)
Definition dict.h:849
int fr_dict_read(fr_dict_t *dict, char const *dict_dir, char const *filename)
Read supplementary attribute definitions into an existing dictionary.
char const * name
Enum name.
Definition dict.h:228
Specifies an attribute which must be present for the module to function.
Definition dict.h:267
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:280
Value of an enumerated attribute.
Definition dict.h:227
#define fr_event_timer_in(...)
Definition event.h:255
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
bool fr_hostname_lookups
hostname -> IP lookups?
Definition inet.c:52
bool fr_reverse_lookups
IP -> hostname lookups?
Definition inet.c:51
IPv4/6 prefix.
void unlang_interpret_signal(request_t *request, fr_signal_t action)
Send a signal (usually stop) to a request.
Definition interpret.c:1200
#define UNLANG_TOP_FRAME
Definition interpret.h:35
rlm_rcode_t unlang_interpret_synchronous(fr_event_list_t *el, request_t *request)
Execute an unlang section synchronously.
Minimal data structure to use the new code.
Definition listen.h:58
int server_init(CONF_SECTION *cs, char const *dict_dir, fr_dict_t *dict)
Initialize src/lib/server/.
Definition base.c:47
void server_free(void)
Free src/lib/server/.
Definition base.c:135
Describes a host allowed to send packets to the server.
Definition client.h:80
void vlog_request(fr_log_type_t type, fr_log_lvl_t lvl, request_t *request, char const *file, int line, char const *fmt, va_list ap, void *uctx)
Send a log message to its destination, possibly including fields from the request.
Definition log.c:295
#define PERROR(_fmt,...)
Definition log.h:228
Definition log.h:70
int fr_packet_pairs_from_packet(TALLOC_CTX *ctx, fr_pair_list_t *list, fr_packet_t const *packet)
Allocate a "Net." struct with src/dst host and port.
Definition packet.c:89
void fr_packet_net_from_pairs(fr_packet_t *packet, fr_pair_list_t const *list)
Convert pairs to information in a packet.
Definition packet.c:139
int unlang_global_init(void)
Definition base.c:133
talloc_free(reap)
unsigned int fr_event_list_reap_signal(fr_event_list_t *el, fr_time_delta_t timeout, int signal)
Send a signal to all the processes we have in our reap list, and reap them.
Definition event.c:2004
fr_event_list_t * fr_event_list_alloc(TALLOC_CTX *ctx, fr_event_status_cb_t status, void *status_uctx)
Initialise a new event list.
Definition event.c:2899
Stores all information relating to an event list.
Definition event.c:411
A timer event.
Definition event.c:102
int fr_debug_lvl
Definition log.c:43
fr_log_t default_log
Definition log.c:291
int fr_log_init_fp(fr_log_t *log, FILE *fp)
Initialise a file logging destination to a FILE*.
Definition log.c:1062
void fr_log(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *fmt,...)
Send a server log message to its destination.
Definition log.c:583
@ L_DST_STDOUT
Log to stdout.
Definition log.h:78
@ L_DBG
Only displayed when debugging is enabled.
Definition log.h:59
fr_packet_t * fr_packet_alloc(TALLOC_CTX *ctx, bool new_vector)
Allocate a new fr_packet_t.
Definition packet.c:38
int main_config_parse_option(char const *value)
int main_config_free(main_config_t **config)
main_config_t * main_config_alloc(TALLOC_CTX *ctx)
Allocate a main_config_t struct, setting defaults.
void main_config_raddb_dir_set(main_config_t *config, char const *name)
Set the global radius config directory.
void main_config_name_set_default(main_config_t *config, char const *name, bool overwrite_config)
Set the server name.
int main_config_init(main_config_t *config)
void main_config_dict_dir_set(main_config_t *config, char const *name)
Set the global dictionary directory.
Main server configuration.
Definition main_config.h:51
int map_proc_unregister(char const *name)
Unregister a map processor by name.
Definition map_proc.c:183
int map_proc_register(TALLOC_CTX *ctx, void const *mod_inst, char const *name, map_proc_func_t evaluate, map_proc_instantiate_t instantiate, size_t inst_size, fr_value_box_safe_for_t literals_safe_for)
Register a map processor.
Definition map_proc.c:131
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
long int ssize_t
int modules_rlm_free(void)
Cleanup all global structures.
int modules_rlm_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Allocates thread-specific data for all registered backend modules.
Definition module_rlm.c:976
int modules_rlm_init(void)
Initialise the module list structure.
void fr_pair_list_tainted(fr_pair_list_t *list)
Mark up a list of VPs as tainted.
Definition pair.c:3447
int fr_pair_list_copy(TALLOC_CTX *ctx, fr_pair_list_t *to, fr_pair_list_t const *from)
Duplicate a list of pairs.
Definition pair.c:2319
void fr_pair_validate_debug(fr_pair_t const *failed[2])
Write an error to the library errorbuff detailing the mismatch.
Definition pair.c:2093
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition pair.c:693
int fr_pair_delete_by_da(fr_pair_list_t *list, fr_dict_attr_t const *da)
Delete matching pairs from the specified list.
Definition pair.c:1689
bool fr_pair_validate(fr_pair_t const *failed[2], fr_pair_list_t *filter, fr_pair_list_t *list)
Uses fr_pair_cmp to verify all fr_pair_ts in list match the filter defined by check.
Definition pair.c:2128
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:46
int fr_pair_list_afrom_file(TALLOC_CTX *ctx, fr_dict_t const *dict, fr_pair_list_t *out, FILE *fp, bool *pfiledone)
Read valuepairs from the fp up to End-Of-File.
static const conf_parser_t config[]
Definition base.c:183
#define fr_assert(_expr)
Definition rad_assert.h:38
static TALLOC_CTX * autofree
#define INFO(fmt,...)
Definition radict.c:54
static bool cleanup
Definition radsniff.c:60
#define RETURN_MODULE_FAIL
Definition rcode.h:56
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
fr_dict_attr_t const * request_attr_request
Definition request.c:45
int request_global_init(void)
Definition request.c:722
#define request_alloc_internal(_ctx, _args)
Allocate a new internal request.
Definition request.h:305
#define request_local_alloc_external(_ctx, _args)
Allocate a new external request outside of the request pool.
Definition request.h:316
@ REQUEST_ACTIVE
Request is active (running or runnable)
Definition request.h:61
static char const * name
ssize_t fr_sbuff_in_escape(fr_sbuff_t *sbuff, char const *in, size_t inlen, fr_sbuff_escape_rules_t const *e_rules)
Print an escaped string to an sbuff.
Definition sbuff.c:1620
char * fr_sbuff_adv_to_chr(fr_sbuff_t *sbuff, size_t len, char c)
Wind position to first instance of specified char.
Definition sbuff.c:1956
ssize_t fr_sbuff_in_sprintf(fr_sbuff_t *sbuff, char const *fmt,...)
Print using a fmt string to an sbuff.
Definition sbuff.c:1595
#define fr_sbuff_adv_past_str_literal(_sbuff, _needle)
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_adv_past_whitespace(_sbuff, _len, _tt)
#define fr_sbuff_current(_sbuff_or_marker)
#define fr_sbuff_is_char(_sbuff_or_marker, _c)
#define SBUFF_CHAR_UNPRINTABLES_EXTENDED
#define fr_sbuff_remaining(_sbuff_or_marker)
#define FR_SBUFF_OUT(_start, _len_or_end)
#define SBUFF_CHAR_UNPRINTABLES_LOW
#define pair_update_reply(_attr, _da)
Return or allocate a fr_pair_t in the reply list.
Definition pair.h:129
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition tmpl.h:350
struct tmpl_rules_s tmpl_rules_t
Definition tmpl.h:238
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:347
@ FR_SIGNAL_CANCEL
Request has been cancelled.
Definition signal.h:40
fr_client_t * client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, CONF_SECTION *server_cs, size_t extra)
Allocate a new client from a config section.
Definition client.c:708
fr_client_t * client_find(fr_client_list_t const *clients, fr_ipaddr_t const *ipaddr, int proto)
Definition client.c:378
bool client_add(fr_client_list_t *clients, fr_client_t *client)
Add a client to a fr_client_list_t.
Definition client.c:187
void modules_init(char const *lib_dir)
Perform global initialisation for modules.
Definition module.c:1912
return count
Definition module.c:163
fr_pair_t * vp
#define fr_time()
Allow us to arbitrarily manipulate time.
Definition state_test.c:8
Definition log.h:96
fr_log_dst_t dst
Log destination.
Definition log.h:97
int fd
File descriptor to write messages to.
Definition log.h:112
bool print_level
sometimes we don't want log levels printed
Definition log.h:106
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Definition tmpl.h:287
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
Definition talloc.c:492
static TALLOC_CTX * talloc_init_const(char const *name)
Allocate a top level chunk with a constant name.
Definition talloc.h:112
#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 fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition time.h:590
"server local" time.
Definition time.h:69
int fr_openssl_version_consistent(void)
Definition version.c:246
@ T_BARE_WORD
Definition token.h:120
@ T_OP_EQ
Definition token.h:83
@ T_DOUBLE_QUOTED_STRING
Definition token.h:121
static fr_event_list_t * el
static bool filedone
int main(int argc, char *argv[])
static request_t * request_clone(request_t *old, int number, CONF_SECTION *server_cs)
static fr_dict_attr_t const * attr_packet_type
#define PROTOCOL_NAME
static unlang_action_t mod_map_proc(rlm_rcode_t *p_result, UNUSED void const *mod_inst, UNUSED void *proc_inst, UNUSED request_t *request, UNUSED fr_value_box_list_t *src, UNUSED map_list_t const *maps)
static fr_client_t * client_alloc(TALLOC_CTX *ctx, char const *ip, char const *name)
static fr_dict_t const * dict_freeradius
static fr_dict_attr_t const * attr_net
static void pair_mutable(fr_pair_t *vp)
static fr_dict_t const * dict_protocol
fr_dict_attr_autoload_t unit_test_module_dict_attr[]
char const * radiusd_version
static request_t * request_from_file(TALLOC_CTX *ctx, FILE *fp, fr_client_t *client, CONF_SECTION *server_cs)
static int my_debug_lvl
static void cancel_request(UNUSED fr_event_list_t *el, UNUSED fr_time_t when, void *uctx)
#define EXIT_WITH_FAILURE
static int map_proc_verify(CONF_SECTION *cs, UNUSED void const *mod_inst, UNUSED void *proc_inst, tmpl_t const *src, UNUSED map_list_t const *maps)
static void too_much_text(fr_sbuff_t *out, ssize_t slen, fr_sbuff_t *line)
static void print_packet(FILE *fp, fr_packet_t *packet, fr_pair_list_t *list)
fr_dict_autoload_t unit_test_module_dict[]
static bool do_xlats(fr_event_list_t *el, request_t *request, char const *filename, FILE *fp)
static request_t * request_from_internal(TALLOC_CTX *ctx)
int unlang_thread_instantiate(TALLOC_CTX *ctx)
Create thread-specific data structures for unlang.
Definition compile.c:5138
ssize_t xlat_eval_compiled(char *out, size_t outlen, request_t *request, xlat_exp_head_t const *head, xlat_escape_legacy_t escape, void const *escape_ctx))
Definition xlat_eval.c:1546
static fr_slen_t head
Definition xlat.h:422
int xlat_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Create thread specific instance tree and create thread instances.
Definition xlat_inst.c:444
fr_slen_t xlat_tokenize(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, fr_value_box_safe_for_t literals_safe_for)
Tokenize an xlat expansion.
int xlat_resolve(xlat_exp_head_t *head, xlat_res_rules_t const *xr_rules)
Walk over an xlat tree recursively, resolving any unresolved functions or references.
fr_slen_t xlat_tokenize_expression(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
Definition xlat_expr.c:3258
#define FR_DICTIONARY_FILE
Definition conf.h:7
#define FR_DICTIONARY_INTERNAL_DIR
Definition conf.h:8
unsigned int code
Packet code (type).
Definition packet.h:61
bool fr_pair_list_empty(fr_pair_list_t const *list)
Is a valuepair list empty.
#define fr_pair_list_foreach(_list_head, _iter)
Iterate over the contents of a fr_pair_list_t.
Definition pair.h:261
#define fr_pair_list_log(_log, _lvl, _list)
Definition pair.h:857
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
Definition pair.h:591
#define fr_pair_dcursor_by_ancestor_init(_cursor, _list, _da)
Initialise a cursor that will return only attributes descended from the specified fr_dict_attr_t.
Definition pair.h:646
static void fr_socket_addr_swap(fr_socket_t *dst, fr_socket_t const *src)
Swap src/dst information of a fr_socket_t.
Definition socket.h:121
Holds information necessary for binding or connecting to a socket.
Definition socket.h:63
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:554
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
Definition strerror.c:733
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
Definition strerror.h:84
#define fr_strerror_const(_msg)
Definition strerror.h:223
#define fr_type_is_leaf(_x)
Definition types.h:372
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_VERSION_BUILD(_x)
Create a version string for a utility in the suite of FreeRADIUS utilities.
Definition version.h:58
#define RADIUSD_MAGIC_NUMBER
Definition version.h:81
fr_sbuff_unescape_rules_t fr_value_unescape_double
Definition value.c:266
#define fr_box_uint32(_val)
Definition value.h:312
int format(printf, 5, 0))
static size_t char ** out
Definition value.h:997
fr_dict_t const * virtual_server_dict_by_name(char const *virtual_server)
Return the namespace for the named virtual server.
virtual_server_t const * virtual_server_find(char const *name)
Return virtual server matching the specified name.
CONF_SECTION * virtual_server_cs(virtual_server_t const *vs)
Return the configuration section for a virtual server.
int virtual_servers_init(void)
Performs global initialisation for the virtual server code.
int virtual_servers_free(void)
int virtual_servers_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Perform thread instantiation for all process modules and listeners.
static TALLOC_CTX * xlat_ctx