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: 502df2fde09e9e94ec14e8f2278ed24f85452fdf $
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: 502df2fde09e9e94ec14e8f2278ed24f85452fdf $")
27
28#include <freeradius-devel/server/base.h>
29#include <freeradius-devel/server/module_rlm.h>
30#include <freeradius-devel/util/rand.h>
31#include <freeradius-devel/io/listen.h>
32
33#include <freeradius-devel/tls/base.h>
34#include <freeradius-devel/tls/version.h>
35
36#include <freeradius-devel/io/thread.h>
37
38#include <freeradius-devel/unlang/base.h>
39#include <freeradius-devel/unlang/xlat_func.h>
40
41#include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
42
43#ifdef HAVE_GETOPT_H
44# include <getopt.h>
45#endif
46
47#define EXIT_WITH_FAILURE \
48do { \
49 ret = EXIT_FAILURE; \
50 goto cleanup; \
51} while (0)
52
53/*
54 * Global variables.
55 */
56static bool filedone = false;
57static int my_debug_lvl = 0;
58
59char const *radiusd_version = RADIUSD_VERSION_BUILD("unit_test_module");
60
63
64#define PROTOCOL_NAME unit_test_module_dict[1].proto
65
68 { .out = &dict_freeradius, .proto = "freeradius" },
69 { .out = &dict_protocol, .proto = "radius" }, /* hacked in-place with '-p protocol' */
71};
72
75
78 { .out = &attr_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_protocol },
79 { .out = &attr_net, .name = "Net", .type = FR_TYPE_TLV, .dict = &dict_freeradius },
80
82};
83
84/*
85 * Static functions.
86 */
87static void usage(main_config_t const *config, int status);
88
89static fr_client_t *client_alloc(TALLOC_CTX *ctx, char const *ip, char const *name)
90{
91 CONF_SECTION *cs;
92 fr_client_t *client;
93
94 cs = cf_section_alloc(ctx, NULL, "client", name);
95 MEM(cf_pair_alloc(cs, "ipaddr", ip, T_OP_EQ, T_BARE_WORD, T_BARE_WORD));
96 MEM(cf_pair_alloc(cs, "secret", "supersecret", T_OP_EQ, T_BARE_WORD, T_DOUBLE_QUOTED_STRING));
98 MEM(cf_pair_alloc(cs, "shortname", "test", T_OP_EQ, T_BARE_WORD, T_DOUBLE_QUOTED_STRING));
102
103 client = client_afrom_cs(ctx, cs, NULL, 0);
104 if (!client) {
105 PERROR("Failed creating test client");
106 fr_assert(0);
107 }
108 talloc_steal(client, cs);
109 fr_assert(client);
110
111 return client;
112}
113
115{
116 if (fr_type_is_leaf(vp->vp_type)) {
117 vp->vp_immutable = false;
118
119 return;
120 }
121
123
124 fr_pair_list_foreach(&vp->vp_group, child) {
125 pair_mutable(child);
126 }
127}
128
129static request_t *request_from_internal(TALLOC_CTX *ctx)
130{
131 request_t *request;
132
133 /*
134 * Create and initialize the new request.
135 */
136 request = request_local_alloc_internal(ctx, NULL);
137 if (!request->packet) request->packet = fr_packet_alloc(request, false);
138 if (!request->reply) request->reply = fr_packet_alloc(request, false);
139
140 request->packet->socket = (fr_socket_t){
141 .type = SOCK_DGRAM,
142 .inet = {
143 .src_ipaddr = {
144 .af = AF_INET,
145 .prefix = 32,
146 .addr = {
147 .v4 = {
148 .s_addr = htonl(INADDR_LOOPBACK)
149 }
150 }
151 },
152 .src_port = 18120,
153 .dst_ipaddr = {
154 .af = AF_INET,
155 .prefix = 32,
156 .addr = {
157 .v4 = {
158 .s_addr = htonl(INADDR_LOOPBACK)
159 }
160 }
161 },
162 .dst_port = 1812
163 }
164 };
165
166 request->log.dst = talloc_zero(request, log_dst_t);
167 request->log.dst->func = vlog_request;
168 request->log.dst->uctx = &default_log;
169 request->log.dst->lvl = fr_debug_lvl;
170
171 request->master_state = REQUEST_ACTIVE;
172 request->log.lvl = fr_debug_lvl;
173 request->async = talloc_zero(request, fr_async_t);
174
175 if (fr_packet_pairs_from_packet(request->request_ctx, &request->request_pairs, request->packet) < 0) {
176 talloc_free(request);
177 fprintf(stderr, "Failed converting packet IPs to attributes");
178 return NULL;
179 }
180
181 return request;
182}
183
184static request_t *request_from_file(TALLOC_CTX *ctx, FILE *fp, fr_client_t *client, CONF_SECTION *server_cs)
185{
186 fr_pair_t *vp;
187 request_t *request;
188 fr_dcursor_t cursor;
189
190 static int number = 0;
191
192 if (!dict_protocol) {
193 fr_strerror_printf_push("%s dictionary failed to load", PROTOCOL_NAME);
194 return NULL;
195 }
196
197 /*
198 * Create and initialize the new request.
199 */
200 request = request_local_alloc_external(ctx, (&(request_init_args_t){ .namespace = dict_protocol }));
201
202 request->packet = fr_packet_alloc(request, false);
203 if (!request->packet) {
204 oom:
205 fr_strerror_const("No memory");
206 error:
207 talloc_free(request);
208 return NULL;
209 }
210 request->packet->timestamp = fr_time();
211
212 request->reply = fr_packet_alloc(request, false);
213 if (!request->reply) goto oom;
214
215 request->client = client;
216 request->number = number++;
217 request->name = talloc_typed_asprintf(request, "%" PRIu64, request->number);
218 request->master_state = REQUEST_ACTIVE;
219
220 /*
221 * Read packet from fp
222 */
223 if (fr_pair_list_afrom_file(request->request_ctx, dict_protocol, &request->request_pairs, fp, &filedone, true) < 0) {
224 goto error;
225 }
226
227 /*
228 * Pretend that the attributes came in "over the wire".
229 *
230 * @todo - do this only for protocol attributes, and not internal ones?
231 */
232 fr_pair_list_tainted(&request->request_pairs);
233
234 vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_packet_type);
235 if (!vp) {
236 fr_strerror_printf("Input packet does not specify a Packet-Type");
237 goto error;
238 }
239 /*
240 * Set the defaults for IPs, etc.
241 */
242 request->packet->code = vp->vp_uint32;
243
244 /*
245 * Now delete the packet-type to ensure
246 * the virtual attribute gets used in
247 * the tests.
248 */
249 fr_pair_delete_by_da(&request->request_pairs, attr_packet_type);
250
251 request->packet->socket = (fr_socket_t){
252 .type = SOCK_DGRAM,
253 .inet = {
254 .src_ipaddr = {
255 .af = AF_INET,
256 .prefix = 32,
257 .addr = {
258 .v4 = {
259 .s_addr = htonl(INADDR_LOOPBACK)
260 }
261 }
262 },
263 .src_port = 18120,
264 .dst_ipaddr = {
265 .af = AF_INET,
266 .prefix = 32,
267 .addr = {
268 .v4 = {
269 .s_addr = htonl(INADDR_LOOPBACK)
270 }
271 }
272 },
273 .dst_port = 1812
274 }
275 };
276
277 /*
278 * Fill in the packet header from attributes, and then
279 * re-realize the attributes.
280 */
281 vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_packet_type);
282 if (vp) request->packet->code = vp->vp_uint32;
283
284 fr_packet_net_from_pairs(request->packet, &request->request_pairs);
285
286 /*
287 * The input might have updated only some of the Net.*
288 * attributes. So for consistency, we create all of them
289 * from the packet header.
290 */
291 if (fr_packet_pairs_from_packet(request->request_ctx, &request->request_pairs, request->packet) < 0) {
292 fr_strerror_const("Failed converting packet IPs to attributes");
293 goto error;
294 }
295
296 /*
297 * For laziness in the tests, allow the Net.* to be mutable
298 */
299 for (vp = fr_pair_dcursor_by_ancestor_init(&cursor, &request->request_pairs, attr_net);
300 vp != NULL;
301 vp = fr_dcursor_next(&cursor)) {
303 }
304
305 if (fr_debug_lvl) {
306 for (vp = fr_pair_dcursor_init(&cursor, &request->request_pairs);
307 vp;
308 vp = fr_dcursor_next(&cursor)) {
309 /*
310 * Take this opportunity to verify all the fr_pair_ts are still valid.
311 */
312 if (!talloc_get_type(vp, fr_pair_t)) {
313 ERROR("Expected fr_pair_t pointer got \"%s\"", talloc_get_name(vp));
314
316 fr_assert(0);
317 }
318
319 fr_log(&default_log, L_DBG, __FILE__, __LINE__, "%pP", vp);
320 }
321 }
322
323 /*
324 * Build the reply template from the request.
325 */
326 fr_socket_addr_swap(&request->reply->socket, &request->packet->socket);
327
328 request->reply->id = request->packet->id;
329 request->reply->code = 0; /* UNKNOWN code */
330 memcpy(request->reply->vector, request->packet->vector, sizeof(request->reply->vector));
331 request->reply->data = NULL;
332 request->reply->data_len = 0;
333
334 /*
335 * Debugging
336 */
337 request->log.dst = talloc_zero(request, log_dst_t);
338 request->log.dst->func = vlog_request;
339 request->log.dst->uctx = &default_log;
340 request->log.dst->lvl = fr_debug_lvl;
341
342 request->master_state = REQUEST_ACTIVE;
343 request->log.lvl = fr_debug_lvl;
344 request->async = talloc_zero(request, fr_async_t);
345
346
347 /*
348 * New async listeners
349 */
350 unlang_call_push(NULL, request, server_cs, UNLANG_TOP_FRAME);
351
352 return request;
353}
354
355
356static void print_packet(FILE *fp, fr_packet_t *packet, fr_pair_list_t *list)
357{
358 fr_dict_enum_value_t const *dv;
359 fr_log_t log;
360
361 (void) fr_log_init_fp(&log, fp);
362
364 if (dv) {
365 fr_log(&default_log, L_DBG, __FILE__, __LINE__, "Packet-Type = %s", dv->name);
366 } else {
367 fr_log(&default_log, L_DBG, __FILE__, __LINE__, "Packet-Type = %u", packet->code);
368 }
369
370 fr_pair_list_log(&default_log, 2, list);
371}
372
373/*
374 * A common function for reports of too much text when handling xlat
375 * and xlat_expr in do_xlats().
376 * The convolution deals with the edge case of the line being so long
377 * that it plus the surrounding text from the format could won't fit
378 * in the output sbuff, along with the fact that you don't print the
379 * %d or %.*s. OTOH it does include slen, but...
380 * * the format string is 41 characters minus 6 for %d and %.*s
381 * * given that slen reflects text read from line, once slen is
382 * large enough, we know line will fit
383 */
384static inline CC_HINT(always_inline) void too_much_text(fr_sbuff_t *out, ssize_t slen, fr_sbuff_t *line)
385{
386 char const *format = "ERROR offset %d 'Too much text' ::%.*s::";
387
388 (void) fr_sbuff_in_sprintf(out, format, (int) slen,
389 fr_sbuff_remaining(out) - (strlen(format) - 5),
391}
392
393/*
394 * Read a file composed of xlat's and expected results
395 */
396static bool do_xlats(fr_event_list_t *el, request_t *request, char const *filename, FILE *fp)
397{
398 int lineno = 0;
399 ssize_t len;
400 char line_buff[8192];
401 char output_buff[8192];
402 char unescaped[sizeof(output_buff)];
405
406 static fr_sbuff_escape_rules_t unprintables = {
407 .name = "unprintables",
408 .chr = '\\',
409 .esc = {
412 },
413 .do_utf8 = true,
414 .do_oct = true
415 };
416
417 while (fgets(line_buff, sizeof(line_buff), fp) != NULL) {
418 lineno++;
419
420 line = FR_SBUFF_IN(line_buff, sizeof(line_buff));
421 if (!fr_sbuff_adv_to_chr(&line, SIZE_MAX, '\n')) {
422 if (!feof(fp)) {
423 fprintf(stderr, "%s[%d] Line too long\n", filename, lineno);
424 return false;
425 }
426 } else {
427 fr_sbuff_terminate(&line);
428 }
429 line.end = line.p;
430 fr_sbuff_set_to_start(&line);
431
432 /*
433 * Ignore blank lines and comments
434 */
435 fr_sbuff_adv_past_whitespace(&line, SIZE_MAX, NULL);
436 if (*fr_sbuff_current(&line) < ' ') continue;
437 if (fr_sbuff_is_char(&line, '#')) continue;
438
439 /*
440 * Look for "match", as it needs the output_buffer to be left alone.
441 */
442 if (fr_sbuff_adv_past_str_literal(&line, "match ") > 0) {
443 size_t output_len = strlen(output_buff);
444
445 if (!fr_sbuff_is_str(&line, output_buff, output_len) || (output_len != fr_sbuff_remaining(&line))) {
446 fprintf(stderr, "Mismatch at %s[%u]\n\tgot : %s (%zu)\n\texpected : %s (%zu)\n",
447 filename, lineno, output_buff, output_len, fr_sbuff_current(&line), fr_sbuff_remaining(&line));
448 return false;
449 }
450 continue;
451 }
452
453 /*
454 * The rest of the keywords create output.
455 */
456 output_buff[0] = '\0';
457 out = FR_SBUFF_OUT(output_buff, sizeof(output_buff));
458
459 /*
460 * Look for "xlat"
461 */
462 if (fr_sbuff_adv_past_str_literal(&line, "xlat ") > 0) {
463 ssize_t slen;
464 TALLOC_CTX *xlat_ctx = talloc_init_const("xlat");
465 xlat_exp_head_t *head = NULL;
466 fr_sbuff_parse_rules_t p_rules = { .escapes = &fr_value_unescape_double };
467 tmpl_rules_t t_rules = (tmpl_rules_t) {
468 .attr = {
470 .list_def = request_attr_request,
471 .allow_unresolved = true,
472 },
473 .xlat = {
474 .runtime_el = el,
475 },
476 .at_runtime = true,
477 };
478
479
480 slen = xlat_tokenize(xlat_ctx, &head, &line, &p_rules, &t_rules);
481 if (slen <= 0) {
483 fr_sbuff_in_sprintf(&out, "ERROR offset %d '%s'", (int) -slen, fr_strerror());
484 continue;
485 }
486
487 if (fr_sbuff_remaining(&line) > 0) {
489 too_much_text(&out, slen, &line);
490 continue;
491 }
492
493 len = xlat_eval_compiled(unescaped, sizeof(unescaped), request, head, NULL, NULL);
494 if (len < 0) {
495 char const *err = fr_strerror();
497 (void) fr_sbuff_in_sprintf(&out, "ERROR expanding xlat: %s", *err ? err : "no error provided");
498 continue;
499 }
500
501 /*
502 * Escape the output as if it were a double quoted string.
503 */
504 fr_sbuff_in_escape(&out, unescaped, len, &unprintables);
505
506 TALLOC_FREE(xlat_ctx); /* also frees 'head' */
507 continue;
508 }
509
510 /*
511 * Look for "xlat_expr"
512 */
513 if (fr_sbuff_adv_past_str_literal(&line, "xlat_expr ") > 0) {
514 ssize_t slen;
515 TALLOC_CTX *xlat_ctx = talloc_init_const("xlat");
516 xlat_exp_head_t *head = NULL;
517
519 &line,
520 NULL,
521 &(tmpl_rules_t) {
522 .attr = {
523 .dict_def = dict_protocol,
524 .list_def = request_attr_request,
525 .allow_unresolved = true,
526 },
527 .xlat = {
528 .runtime_el = el,
529 },
530 .at_runtime = true,
531 });
532 if (slen <= 0) {
534 fr_sbuff_in_sprintf(&out, "ERROR offset %d '%s'", (int) -slen - 1, fr_strerror());
535 continue;
536 }
537
538 if (fr_sbuff_remaining(&line) > 0) {
540 too_much_text(&out, slen, &line);
541 continue;
542 }
543
544 if (xlat_resolve(head, NULL) < 0) {
546 (void) fr_sbuff_in_sprintf(&out, "ERROR resolving xlat: %s", fr_strerror());
547 continue;
548 }
549
550 len = xlat_eval_compiled(unescaped, sizeof(unescaped), request, head, NULL, NULL);
551 if (len < 0) {
552 char const *err = fr_strerror();
554 (void) fr_sbuff_in_sprintf(&out, "ERROR expanding xlat: %s", *err ? err : "no error provided");
555 continue;
556 }
557
558 /*
559 * Escape the output as if it were a double quoted string.
560 */
561 fr_sbuff_in_escape(&out, unescaped, len, &unprintables);
562
563 TALLOC_FREE(xlat_ctx); /* also frees 'head' */
564 continue;
565 }
566
567 fprintf(stderr, "Unknown keyword in %s[%d]\n", filename, lineno);
568 return false;
569 }
570
571 return true;
572}
573
574/*
575 * Verify the result of the map.
576 */
577static int map_proc_verify(CONF_SECTION *cs, UNUSED void const *mod_inst, UNUSED void *proc_inst,
578 tmpl_t const *src, UNUSED map_list_t const *maps)
579{
580 if (!src) {
581 cf_log_err(cs, "Missing source");
582
583 return -1;
584 }
585
586 return 0;
587}
588
590 UNUSED request_t *request, UNUSED fr_value_box_list_t *src,
591 UNUSED map_list_t const *maps)
592{
594}
595
596static request_t *request_clone(request_t *old, int number, CONF_SECTION *server_cs)
597{
598 request_t *request;
599
600 request = request_local_alloc_internal(NULL, (&(request_init_args_t){ .namespace = old->proto_dict }));
601 if (!request) return NULL;
602
603 if (!request->packet) request->packet = fr_packet_alloc(request, false);
604 if (!request->reply) request->reply = fr_packet_alloc(request, false);
605
606 memcpy(request->packet, old->packet, sizeof(*request->packet));
607 (void) fr_pair_list_copy(request->request_ctx, &request->request_pairs, &old->request_pairs);
608 request->packet->timestamp = fr_time();
609 request->number = number;
610 request->name = talloc_typed_asprintf(request, "%" PRIu64, request->number);
611
612 unlang_call_push(NULL, request, server_cs, UNLANG_TOP_FRAME);
613
614 request->master_state = REQUEST_ACTIVE;
615
616 return request;
617}
618
619static void cancel_request(UNUSED fr_timer_list_t *tl, UNUSED fr_time_t when, void *uctx)
620{
621 request_t *request = talloc_get_type_abort(uctx, request_t);
623 request->rcode = RLM_MODULE_TIMEOUT;
624}
625
627
628/** Sythentic time source for tests
629 *
630 * This allows us to artificially advance time for tests.
631 */
637 { .required = true, .type = FR_TYPE_TIME_DELTA, .single = true },
639};
640
642
644{
645 request_t *request = talloc_get_type_abort(uctx, request_t);
647}
648
650 UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, UNUSED fr_value_box_list_t *in)
651{
652 fr_value_box_t *vb;
653
654 MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_TIME_DELTA, NULL));
655 vb->vb_time_delta = time_offset;
657
658 return XLAT_ACTION_DONE;
659}
660
662 UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *in)
663{
664 fr_value_box_t *delta;
665
666 XLAT_ARGS(in, &delta);
667
668 /*
669 * This ensures we take a pass through the timer list
670 * otherwise the time advances can be ignored.
671 */
673 RPERROR("Failed to add timer");
674 return XLAT_ACTION_FAIL;
675 }
676
678
679 time_offset = fr_time_delta_add(time_offset, delta->vb_time_delta);
680
682
683 unlang_xlat_yield(request, xlat_func_time_advance_resume, NULL, 0, NULL);
684
685 return XLAT_ACTION_YIELD;
686}
687
688/**
689 *
690 * @hidecallgraph
691 */
692int main(int argc, char *argv[])
693{
694 int ret = EXIT_SUCCESS;
695 int c;
696 int count = 1;
697 const char *input_file = NULL;
698 const char *xlat_input_file = NULL;
699 const char *output_file = NULL;
700 const char *filter_file = NULL;
701 FILE *fp = NULL;
702 request_t *request = NULL;
703 fr_pair_t *vp;
704 fr_pair_list_t filter_vps;
705 bool xlat_only = false;
706 fr_event_list_t *el = NULL;
707 fr_client_t *client = NULL;
708 fr_dict_t *dict = NULL;
709 fr_dict_t const *dict_check;
710 char const *receipt_file = NULL;
711
712 xlat_t *time_advance = NULL;
713
714 TALLOC_CTX *autofree;
715 TALLOC_CTX *thread_ctx;
716
717 char *p;
719
720 CONF_SECTION *server_cs;
721
722#ifndef NDEBUG
723 size_t memory_used_before = 0;
724 size_t memory_used_after = 0;
725#endif
726 virtual_server_t const *vs;
727
728 fr_pair_list_init(&filter_vps);
729
730 /*
731 * Must be called first, so the handler is called last
732 */
734
736 thread_ctx = talloc_new(autofree);
737
739 if (!config) {
740 fr_perror("unit_test_module");
741 fr_exit_now(EXIT_FAILURE);
742 }
743
744 p = strrchr(argv[0], FR_DIR_SEP);
745 if (!p) {
746 main_config_name_set_default(config, argv[0], false);
747 } else {
749 }
750
752
753 /*
754 * If the server was built with debugging enabled always install
755 * the basic fatal signal handlers.
756 */
757#ifndef NDEBUG
758 if (fr_fault_setup(autofree, getenv("PANIC_ACTION"), argv[0]) < 0) {
759 fr_perror("%s", config->name);
760 fr_exit_now(EXIT_FAILURE);
761 }
762#else
764#endif
765
766 fr_debug_lvl = 0;
768
769 /*
770 * The tests should have only IPs, not host names.
771 */
773
774 /*
775 * We always log to stdout.
776 */
778 default_log.fd = STDOUT_FILENO;
780
781 /* Process the options. */
782 while ((c = getopt(argc, argv, "c:Cd:D:f:hi:I:mMn:o:p:r:S:xXz")) != -1) {
783 switch (c) {
784 case 'c':
785 count = atoi(optarg);
786 break;
787
788 case 'C':
789 check_config = true;
790 break;
791
792 case 'd':
794 break;
795
796 case 'D':
798 break;
799
800 case 'f':
801 filter_file = optarg;
802 break;
803
804 case 'h':
805 usage(config, EXIT_SUCCESS);
806 break;
807
808 case 'i':
809 input_file = optarg;
810 break;
811
812 case 'I':
813 xlat_input_file = optarg;
814 xlat_only = true;
815 break;
816
817 case 'M':
818 talloc_enable_leak_report();
819 break;
820
821 case 'n':
822 config->name = optarg;
823 break;
824
825 case 'o':
826 output_file = optarg;
827 break;
828
829 case 'p':
830 PROTOCOL_NAME = optarg;
831 break;
832
833 case 'r':
834 receipt_file = optarg;
835 break;
836
837 case 'S': /* Migration support */
838#if 0
839 if (main_config_parse_option(optarg) < 0) {
840 fprintf(stderr, "%s: Unknown configuration option '%s'\n",
841 config->name, optarg);
842 fr_exit_now(EXIT_FAILURE);
843 }
844#endif
845 break;
846
847 case 'X':
848 fr_debug_lvl += 2;
850 break;
851
852 case 'x':
853 fr_debug_lvl++;
854 if (fr_debug_lvl > 2) default_log.print_level = true;
855 break;
856
857 case 'z':
858 my_debug_lvl++;
859 break;
860
861 default:
862 usage(config, EXIT_FAILURE);
863 break;
864 }
865 }
866
867 if (receipt_file && (fr_unlink(receipt_file) < 0)) {
868 fr_perror("%s", config->name);
870 }
871
872#ifdef WITH_TLS
873 /*
874 * Mismatch between build time OpenSSL and linked SSL, better to die
875 * here than segfault later.
876 */
878
879 /*
880 * Initialising OpenSSL once, here, is safer than having individual modules do it.
881 * Must be called before display_version to ensure relevant engines are loaded.
882 *
883 * fr_openssl_init() must be called before *ANY* OpenSSL functions are used, which is why
884 * it's called so early.
885 */
886 if (fr_openssl_init() < 0) EXIT_WITH_FAILURE;
887#endif
888
890
891 /*
892 * Mismatch between the binary and the libraries it depends on
893 */
895 fr_perror("%s", config->name);
896 ret = EXIT_FAILURE;
897 goto cleanup;
898 }
899
900 /*
901 * Initialize the DL infrastructure, which is used by the
902 * config file parser.
903 */
904 modules_init(config->lib_dir);
905
906 if (!fr_dict_global_ctx_init(NULL, true, config->dict_dir)) {
907 fr_perror("%s", config->name);
909 }
910
912 fr_perror("%s", config->name);
914 }
915
916#ifdef WITH_TLS
917 if (fr_tls_dict_init() < 0) EXIT_WITH_FAILURE;
918#endif
919
920 /*
921 * Load the custom dictionary
922 */
923 if (fr_dict_read(dict, config->confdir, FR_DICTIONARY_FILE) == -1) {
924 PERROR("Failed to initialize the dictionaries");
926 }
927
929 fr_perror("%s", config->name);
931 }
933 fr_perror("%s", config->name);
935 }
936
937 if (request_global_init() < 0) {
938 fr_perror("unit_test_module");
940 }
941
942 if (map_proc_register(NULL, NULL, "test-fail", mod_map_proc, map_proc_verify, 0, 0) < 0) {
944 }
945
946 /*
947 * Needed for the triggers. Which are always run-time expansions.
948 */
949 if (main_loop_init() < 0) {
950 PERROR("Failed initialising main event loop");
952 }
953 /*
954 * Initialise the interpreter, registering operations.
955 * This initialises
956 */
957 if (unlang_global_init() < 0) {
958 fr_perror("%s", config->name);
960 }
961
962 time_advance = xlat_func_register(NULL, "time.advance", xlat_func_time_advance, FR_TYPE_VOID);
963 if (!time_advance) EXIT_WITH_FAILURE;
965
966 /*
967 * Ensure that we load the correct virtual server for the
968 * protocol, if necessary.
969 */
970 if (!getenv("PROTOCOL")) {
971 setenv("PROTOCOL", PROTOCOL_NAME, true);
972 }
973
974 /*
975 * Setup the global structures for module lists
976 */
977 if (modules_rlm_init() < 0) {
978 fr_perror("%s", config->name);
980 }
981 if (virtual_servers_init() < 0) {
982 fr_perror("%s", config->name);
984 }
985
986 if (main_config_init(config) < 0) {
988 }
989
990 /*
991 * Create a dummy client on 127.0.0.1, if one doesn't already exist.
992 */
993 client = client_find(NULL, &(fr_ipaddr_t) { .af = AF_INET, .prefix = 32, .addr.v4.s_addr = htonl(INADDR_LOOPBACK) },
994 IPPROTO_IP);
995 if (!client) {
996 client = client_alloc(NULL, "127.0.0.1", "test");
997 client_add(NULL, client);
998 }
999
1000 if (server_init(config->root_cs, config->confdir, dict) < 0) EXIT_WITH_FAILURE;
1001
1002 vs = virtual_server_find("default");
1003 if (!vs) {
1004 ERROR("Cannot find virtual server 'default'");
1006 }
1007
1008 server_cs = virtual_server_cs(vs);
1009
1010 /*
1011 * Do some sanity checking.
1012 */
1013 dict_check = virtual_server_dict_by_name("default");
1014 if (!dict_check || !fr_dict_compatible(dict_check, dict_protocol)) {
1015 ERROR("Virtual server namespace does not match requested namespace '%s'", PROTOCOL_NAME);
1017 }
1018
1019 /*
1020 * Everything seems to have loaded OK, exit gracefully.
1021 */
1022 if (check_config) {
1023 DEBUG("Configuration appears to be OK");
1024 goto cleanup;
1025 }
1026
1027 /*
1028 * Get the main event list.
1029 */
1031 fr_assert(el != NULL);
1033
1034 /*
1035 * Simulate thread specific instantiation
1036 */
1037 if (fr_thread_instantiate(thread_ctx, el) < 0) {
1038 fr_perror("%s", config->name);
1040 }
1041
1042 /*
1043 * Set the panic action (if required)
1044 */
1045 {
1046 char const *panic_action = NULL;
1047
1048 panic_action = getenv("PANIC_ACTION");
1049 if (!panic_action) panic_action = config->panic_action;
1050
1051 if (panic_action && (fr_fault_setup(autofree, panic_action, argv[0]) < 0)) {
1052 fr_perror("%s", config->name);
1054 }
1055 }
1056
1057 setlinebuf(stdout); /* unbuffered output */
1058
1059#ifndef NDEBUG
1060 memory_used_before = talloc_total_size(autofree);
1061#endif
1062
1063 if (!input_file && !xlat_only) input_file = "-";
1064
1065 if (input_file) {
1066 if (strcmp(input_file, "-") == 0) {
1067 fp = stdin;
1068 } else {
1069 fp = fopen(input_file, "r");
1070 if (!fp) {
1071 fprintf(stderr, "Failed reading %s: %s\n",
1072 input_file, fr_syserror(errno));
1074 }
1075 }
1076
1077 /*
1078 * Grab the VPs from stdin, or from the file.
1079 */
1080 request = request_from_file(autofree, fp, client, server_cs);
1081 if (!request) {
1082 fr_perror("Failed reading input from %s", input_file);
1084 }
1085 } else {
1087 }
1088
1089 /*
1090 * For simplicity, read xlat's.
1091 */
1092 if (xlat_only) {
1093 if (fp && (fp != stdin)) fclose(fp);
1094
1095 fp = fopen(xlat_input_file, "r");
1096 if (!fp) {
1097 fprintf(stderr, "Failed reading %s: %s\n",
1098 xlat_input_file, fr_syserror(errno));
1100 }
1101
1102 if (!do_xlats(el, request, xlat_input_file, fp)) ret = EXIT_FAILURE;
1103 fclose(fp);
1104 goto cleanup;
1105 }
1106
1107 /*
1108 * No filter file, OR there's no more input, OR we're
1109 * reading from a file, and it's different from the
1110 * filter file.
1111 */
1112 if (!filter_file || filedone ||
1113 ((input_file != NULL) && (strcmp(filter_file, input_file) != 0))) {
1114 if (output_file) {
1115 if (fp && (fp != stdin)) fclose(fp);
1116 fp = NULL;
1117 }
1118 filedone = false;
1119 }
1120
1121 /*
1122 * There is a filter file. If necessary, open it. If we
1123 * already are reading it via "input_file", then we don't
1124 * need to re-open it.
1125 */
1126 if (filter_file) {
1127 if (!fp) {
1128 fp = fopen(filter_file, "r");
1129 if (!fp) {
1130 fprintf(stderr, "Failed reading %s: %s\n", filter_file, fr_syserror(errno));
1132 }
1133 }
1134
1135 if (fr_pair_list_afrom_file(request->request_ctx, dict_protocol, &filter_vps, fp, &filedone, true) < 0) {
1136 fr_perror("Failed reading attributes from %s", filter_file);
1138 }
1139
1140 /*
1141 * Filter files can't be empty.
1142 */
1143 if (fr_pair_list_empty(&filter_vps)) {
1144 fr_perror("No attributes in filter file %s", filter_file);
1146 }
1147
1148 /*
1149 * FIXME: loop over input packets.
1150 */
1151 fclose(fp);
1152 }
1153
1154 if (count == 1) {
1155 fr_timer_in(request, el->tl, &request->timeout, config->worker.max_request_time, false, cancel_request, request);
1157
1158 } else {
1159 int i;
1160 request_t *cached = request;
1161
1162 for (i = 0; i < count; i++) {
1163#ifndef NDEBUG
1164 size_t request_used_before, request_used_after;
1165#endif
1166
1167 request = request_clone(cached, i, server_cs);
1168
1169#ifndef NDEBUG
1170 request_used_before = talloc_total_size(autofree);
1171
1172 /*
1173 * Artificially limit the number of instructions which are run.
1174 */
1175 if (config->ins_max) {
1176 if (config->ins_countup) {
1177 request->ins_max = i + 1;
1178 } else {
1179 request->ins_max = config->ins_max;
1180 }
1181
1182 if (request->ins_max < 10) request->ins_max = 10;
1183
1184 request->ins_count = 0;
1185 }
1186#endif
1187
1188 fr_timer_in(request, el->tl, &request->timeout, config->worker.max_request_time, false, cancel_request, request);
1190 talloc_free(request);
1191
1192#ifndef NDEBUG
1193 request_used_after = talloc_total_size(autofree);
1194 fr_assert(request_used_after == request_used_before);
1195#endif
1196 }
1197
1198 request = cached;
1199 }
1200
1201 if (!output_file || (strcmp(output_file, "-") == 0)) {
1202 fp = stdout;
1203 } else {
1204 fp = fopen(output_file, "w");
1205 if (!fp) {
1206 fprintf(stderr, "Failed writing %s: %s\n", output_file, fr_syserror(errno));
1207 goto cleanup;
1208 }
1209 }
1210
1211 print_packet(fp, request->reply, &request->reply_pairs);
1212
1213 if (output_file) fclose(fp);
1214
1215 /*
1216 * Update the list with the response type, so that it can
1217 * be matched in filters.
1218 *
1219 * Some state machines already include a response Packet-Type
1220 * so we need to try and update it, else we end up with two!
1221 */
1222 if (!fr_pair_list_empty(&filter_vps)) {
1223 fr_pair_t const *failed[2];
1224
1226 vp->vp_uint32 = request->reply->code;
1227
1228 if (!fr_pair_validate(failed, &filter_vps, &request->reply_pairs)) {
1229 fr_pair_validate_debug(failed);
1230
1231 fr_perror("Output file %s does not match attributes in filter %s",
1232 output_file ? output_file : "-", filter_file);
1233 fr_fprintf_pair_list(stderr, &filter_vps);
1234 ret = EXIT_FAILURE;
1235 goto cleanup;
1236 }
1237 }
1238
1239 INFO("Exiting normally");
1240
1241cleanup:
1242 talloc_free(request);
1243
1244 /*
1245 * No leaks.
1246 */
1247#ifndef NDEBUG
1248 memory_used_after = talloc_total_size(autofree);
1249 if (memory_used_after != memory_used_before) {
1250 printf("WARNING: May have leaked memory (%zd - %zd = %zd)\n",
1251 memory_used_after, memory_used_before, memory_used_after - memory_used_before);
1252 }
1253#endif
1254
1255 map_proc_unregister("test-fail");
1256
1257 /*
1258 * Free thread data
1259 */
1260 talloc_free(thread_ctx);
1261
1262 /*
1263 * Ensure all thread local memory is cleaned up
1264 * at the appropriate time. This emulates what's
1265 * done with worker/network threads in the
1266 * scheduler.
1267 */
1269
1270 /*
1271 * Give processes a chance to exit
1272 */
1274
1276
1277 /*
1278 * Ensure all thread local memory is cleaned up
1279 * at the appropriate time. This emulates what's
1280 * done with worker/network threads in the
1281 * scheduler.
1282 */
1284
1285 server_free();
1286
1287 /*
1288 * Virtual servers need to be freed before modules
1289 * as state entries containing data with module-specific
1290 * destructors may exist.
1291 */
1293
1294 /*
1295 * Free modules, this needs to be done explicitly
1296 * because some libraries used by modules use atexit
1297 * handlers registered after ours, and they may deinit
1298 * themselves before we free the modules and cause
1299 * crashes on exit.
1300 */
1302
1303 /*
1304 * And now nothing should be left anywhere except the
1305 * parsed configuration items.
1306 */
1308
1309#ifdef WITH_TLS
1310 fr_tls_dict_free();
1311#endif
1312
1313 /*
1314 * Free any autoload dictionaries
1315 */
1317
1318 /*
1319 * Free our explicitly loaded internal dictionary
1320 */
1321 if (fr_dict_free(&dict, __FILE__) < 0) {
1322 fr_perror("unit_test_module - dict");
1323 ret = EXIT_FAILURE;
1324 }
1325
1326 /*
1327 * Free any openssl resources and the TLS dictionary
1328 */
1329#ifdef WITH_TLS
1330 fr_openssl_free();
1331#endif
1332
1333 if (receipt_file && (ret == EXIT_SUCCESS) && (fr_touch(NULL, receipt_file, 0644, true, 0755) <= 0)) {
1334 fr_perror("unit_test_module");
1335 ret = EXIT_FAILURE;
1336 }
1337
1338 if (talloc_free(autofree) < 0) {
1339 fr_perror("unit_test_module - autofree");
1340 ret = EXIT_FAILURE;
1341 }
1342
1343 /*
1344 * Ensure our atexit handlers run before any other
1345 * atexit handlers registered by third party libraries.
1346 */
1348
1349 return ret;
1350}
1351
1352
1353/*
1354 * Display the syntax for starting this program.
1355 */
1356static NEVER_RETURNS void usage(main_config_t const *config, int status)
1357{
1358 FILE *output = status ? stderr : stdout;
1359
1360 fprintf(output, "Usage: %s [options]\n", config->name);
1361 fprintf(output, "Options:\n");
1362 fprintf(output, " -c <count> Run packets through the interpreter <count> times\n");
1363 fprintf(output, " -C Check configuration and exit.\n");
1364 fprintf(output, " -d <confdir> Configuration file directory. (defaults to " CONFDIR ").");
1365 fprintf(output, " -D <dict_dir> Dictionary files are in \"dict_dir/*\".\n");
1366 fprintf(output, " -f <file> Filter reply against attributes in 'file'.\n");
1367 fprintf(output, " -h Print this help message.\n");
1368 fprintf(output, " -i <file> File containing request attributes.\n");
1369 fprintf(output, " -m On SIGINT or SIGQUIT exit cleanly instead of immediately.\n");
1370 fprintf(output, " -n <name> Read ${confdir}/name.conf instead of ${confdir}/radiusd.conf.\n");
1371 fprintf(output, " -o <file> Output file for the reply.\n");
1372 fprintf(output, " -p <radius|...> Define which protocol namespace is used to read the file\n");
1373 fprintf(output, " Use radius, dhcpv4, or dhcpv6\n");
1374 fprintf(output, " -X Turn on full debugging.\n");
1375 fprintf(output, " -x Turn on additional debugging. (-xx gives more debugging).\n");
1376 fprintf(output, " -r <receipt_file> Create the <receipt_file> as a 'success' exit.\n");
1377
1378 fr_exit_now(status);
1379}
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:159
int fr_atexit_global_trigger_all(void)
Cause all global free triggers to fire.
Definition atexit.c:285
#define fr_atexit_thread_trigger_all(...)
Definition atexit.h:232
static TALLOC_CTX * autofree
Definition fuzzer.c:44
#define RCSID(id)
Definition build.h:506
#define NEVER_RETURNS
Should be placed before the function return type.
Definition build.h:334
#define unlikely(_x)
Definition build.h:402
#define UNUSED
Definition build.h:336
unlang_action_t unlang_call_push(unlang_result_t *p_result, request_t *request, CONF_SECTION *server_cs, bool top_frame)
Push a call frame onto the stack.
Definition call.c:147
bool check_config
Definition cf_file.c:61
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:1269
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:285
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition cf_util.h:143
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition dcursor.h:288
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition dcursor.h:406
static char panic_action[512]
The command to execute when panicking.
Definition debug.c:66
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_log_talloc_report(TALLOC_CTX const *ctx)
Generate a talloc memory report for a context and print to stderr/stdout.
Definition debug.c:962
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
void fr_talloc_fault_setup(void)
Register talloc fault handlers.
Definition debug.c:1037
#define MEM(x)
Definition debug.h:46
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
Definition debug.h:236
void dependency_version_print(void)
Definition dependency.c:365
#define ERROR(fmt,...)
Definition dhcpclient.c:40
#define DEBUG(fmt,...)
Definition dhcpclient.c:38
static NEVER_RETURNS void usage(void)
Definition dhcpclient.c:113
#define fr_dict_autofree(_to_free)
Definition dict.h:915
static fr_slen_t err
Definition dict.h:882
int fr_dict_internal_afrom_file(fr_dict_t **out, char const *dict_subdir, char const *dependent))
(Re-)Initialize the special internal dictionary
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:2884
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:292
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:305
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:4329
fr_dict_enum_value_t const * 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:3655
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:4395
#define fr_dict_autoload(_to_load)
Definition dict.h:912
#define DICT_AUTOLOAD_TERMINATOR
Definition dict.h:311
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:4713
char const * name
Enum name.
Definition dict.h:254
static fr_slen_t in
Definition dict.h:882
Specifies an attribute which must be present for the module to function.
Definition dict.h:291
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:304
Value of an enumerated attribute.
Definition dict.h:253
talloc_free(hp)
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_mark_runnable(request_t *request)
Mark a request as resumable.
Definition interpret.c:1636
void unlang_interpret_signal(request_t *request, fr_signal_t action)
Send a signal (usually stop) to a request.
Definition interpret.c:1417
fr_event_list_t * unlang_interpret_event_list(request_t *request)
Get the event list for the current interpreter.
Definition interpret.c:2053
#define UNLANG_TOP_FRAME
Definition interpret.h:36
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:63
int server_init(CONF_SECTION *cs, char const *conf_dir, fr_dict_t *dict)
Initialize src/lib/server/.
Definition base.c:42
void server_free(void)
Free src/lib/server/.
Definition base.c:137
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:293
#define PERROR(_fmt,...)
Definition log.h:228
#define RPERROR(fmt,...)
Definition log.h:314
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:91
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:154
int unlang_global_init(void)
Definition base.c:158
#define fr_time()
Definition event.c:60
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:1699
Stores all information relating to an event list.
Definition event.c:377
int fr_unlink(char const *filename)
Remove a regular file from the filesystem.
Definition file.c:366
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:322
int fr_debug_lvl
Definition log.c:40
fr_log_t default_log
Definition log.c:288
int fr_log_init_fp(fr_log_t *log, FILE *fp)
Initialise a file logging destination to a FILE*.
Definition log.c:1056
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:577
@ L_DST_STDOUT
Log to stdout.
Definition log.h:75
@ L_DBG
Only displayed when debugging is enabled.
Definition log.h:56
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_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_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_confdir_set(main_config_t *config, char const *name)
Set the global radius config directory.
void main_config_dict_dir_set(main_config_t *config, char const *name)
Set the global dictionary directory.
int main_config_parse_option(char const *value)
Main server configuration.
Definition main_config.h:51
fr_event_list_t * main_loop_event_list(void)
Return the main loop event list.
Definition main_loop.c:166
int main_loop_init(void)
Initialise the main event loop, setting up signal handlers.
Definition main_loop.c:255
void main_loop_free(void)
Definition main_loop.c:191
int map_proc_unregister(char const *name)
Unregister a map processor by name.
Definition map_proc.c:176
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:124
Temporary structure to hold arguments for map calls.
Definition map_proc.h:52
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_VOID
User data.
long int ssize_t
int modules_rlm_free(void)
Cleanup all global structures.
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:3424
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:2326
void fr_pair_validate_debug(fr_pair_t const *failed[2])
Write an error to the library errorbuff detailing the mismatch.
Definition pair.c:2096
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:707
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:1696
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:2131
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, bool allow_exec)
Read valuepairs from the fp up to End-Of-File.
static const conf_parser_t config[]
Definition base.c:163
#define fr_assert(_expr)
Definition rad_assert.h:37
#define RDEBUG(fmt,...)
#define INFO(fmt,...)
Definition radict.c:63
static bool cleanup
Definition radsniff.c:59
#define RETURN_UNLANG_FAIL
Definition rcode.h:63
@ RLM_MODULE_TIMEOUT
Module (or section) timed out.
Definition rcode.h:56
fr_dict_attr_t const * request_attr_request
Definition request.c:43
int request_global_init(void)
Definition request.c:596
#define request_local_alloc_internal(_ctx, _args)
Allocate a new internal request outside of the request pool.
Definition request.h:343
#define request_local_alloc_external(_ctx, _args)
Allocate a new external request outside of the request pool.
Definition request.h:335
@ REQUEST_ACTIVE
Request is active (running or runnable)
Definition request.h:87
Optional arguments for initialising requests.
Definition request.h:287
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:1630
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:1997
ssize_t fr_sbuff_in_sprintf(fr_sbuff_t *sbuff, char const *fmt,...)
Print using a fmt string to an sbuff.
Definition sbuff.c:1605
#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:339
struct tmpl_rules_s tmpl_rules_t
Definition tmpl.h:233
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:336
@ 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:706
fr_client_t * client_find(fr_client_list_t const *clients, fr_ipaddr_t const *ipaddr, int proto)
Definition client.c:370
bool client_add(fr_client_list_t *clients, fr_client_t *client)
Add a client to a fr_client_list_t.
Definition client.c:182
void modules_init(char const *lib_dir)
Perform global initialisation for modules.
Definition module.c:1939
return count
Definition module.c:155
fr_pair_t * vp
Definition log.h:93
fr_log_dst_t dst
Log destination.
Definition log.h:94
int fd
File descriptor to write messages to.
Definition log.h:109
bool print_level
sometimes we don't want log levels printed
Definition log.h:103
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Definition tmpl.h:273
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:545
static TALLOC_CTX * talloc_init_const(char const *name)
Allocate a top level chunk with a constant name.
Definition talloc.h:120
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
Definition talloc.h:48
int fr_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Instantiate thread-specific data for modules, virtual servers, xlats, unlang, and TLS.
Definition thread.c:165
int fr_time_start(void)
Initialize the local time.
Definition time.c:150
static fr_time_delta_t fr_time_delta_add(fr_time_delta_t a, fr_time_delta_t b)
Definition time.h:255
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition time.h:590
#define fr_time_delta_wrap(_time)
Definition time.h:152
static fr_time_t fr_time_add_delta_time(fr_time_delta_t a, fr_time_t b)
Definition time.h:180
static fr_unix_time_t fr_time_to_unix_time(fr_time_t when)
Convert an fr_time_t (internal time) to our version of unix time (wallclock time)
Definition time.h:688
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
"server local" time.
Definition time.h:69
void fr_timer_list_set_time_func(fr_timer_list_t *tl, fr_event_time_source_t func)
Override event list time source.
Definition timer.c:1199
An event timer list.
Definition timer.c:49
A timer event.
Definition timer.c:83
#define fr_timer_in(...)
Definition timer.h:87
int fr_openssl_version_consistent(void)
Definition version.c:246
@ T_BARE_WORD
Definition token.h:118
@ T_OP_EQ
Definition token.h:81
@ T_DOUBLE_QUOTED_STRING
Definition token.h:119
static char const * receipt_file
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 fr_timer_t * time_advance_timer
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 xlat_action_t xlat_func_time_advance(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *in)
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 xlat_action_t xlat_func_time_advance_resume(TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, UNUSED fr_value_box_list_t *in)
static fr_time_delta_t time_offset
#define EXIT_WITH_FAILURE
static xlat_arg_parser_t const xlat_func_time_advance_args[]
static unlang_action_t mod_map_proc(unlang_result_t *p_result, UNUSED map_ctx_t const *mpctx, UNUSED request_t *request, UNUSED fr_value_box_list_t *src, UNUSED map_list_t const *maps)
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 fr_time_t _synthetic_time_source(void)
Sythentic time source for tests.
static void time_advance_resume(UNUSED fr_timer_list_t *tl, UNUSED fr_time_t now, void *uctx)
static void cancel_request(UNUSED fr_timer_list_t *tl, UNUSED fr_time_t when, void *uctx)
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)
xlat_action_t unlang_xlat_yield(request_t *request, xlat_func_t resume, xlat_func_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
Definition xlat.c:543
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)
Tokenize an xlat expansion.
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:1869
static fr_slen_t head
Definition xlat.h:420
#define XLAT_ARGS(_list,...)
Populate local variables with value boxes from the input list.
Definition xlat.h:383
unsigned int required
Argument must be present, and non-empty.
Definition xlat.h:146
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.
#define XLAT_ARG_PARSER_TERMINATOR
Definition xlat.h:170
xlat_action_t
Definition xlat.h:37
@ XLAT_ACTION_FAIL
An xlat function failed.
Definition xlat.h:44
@ XLAT_ACTION_YIELD
An xlat function pushed a resume frame onto the stack.
Definition xlat.h:42
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition xlat.h:43
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:3165
Definition for a single argument consumed by an xlat function.
Definition xlat.h:145
#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
void fr_fprintf_pair_list(FILE *fp, fr_pair_list_t const *list)
Definition pair_print.c:491
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:279
#define fr_pair_list_log(_log, _lvl, _list)
Definition pair.h:864
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
Definition pair.h:604
#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:657
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:118
Holds information necessary for binding or connecting to a socket.
Definition socket.h:60
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:553
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
Definition strerror.c:732
#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_structural(_x)
Definition types.h:392
#define fr_type_is_leaf(_x)
Definition types.h:393
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 const fr_value_unescape_double
Definition value.c:271
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
Definition value.h:644
#define fr_box_time_delta(_val)
Definition value.h:366
#define fr_box_uint32(_val)
Definition value.h:335
int format(printf, 5, 0))
static size_t char ** out
Definition value.h:1030
#define fr_box_date(_val)
Definition value.h:347
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)
static TALLOC_CTX * xlat_ctx
An xlat calling ctx.
Definition xlat_ctx.h:49
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
Definition xlat_func.c:363
xlat_t * xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function.
Definition xlat_func.c:216