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: 871a070a6550821953b94e94b8063b648fb457cd $
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: 871a070a6550821953b94e94b8063b648fb457cd $")
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_local_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 if (!dict_protocol) {
194 fr_strerror_printf_push("%s dictionary failed to load", PROTOCOL_NAME);
195 return NULL;
196 }
197
198 /*
199 * Create and initialize the new request.
200 */
201 request = request_local_alloc_external(ctx, (&(request_init_args_t){ .namespace = dict_protocol }));
202
203 request->packet = fr_packet_alloc(request, false);
204 if (!request->packet) {
205 oom:
206 fr_strerror_const("No memory");
207 error:
208 talloc_free(request);
209 return NULL;
210 }
211 request->packet->timestamp = fr_time();
212
213 request->reply = fr_packet_alloc(request, false);
214 if (!request->reply) goto oom;
215
216 request->client = client;
217 request->number = number++;
218 request->name = talloc_typed_asprintf(request, "%" PRIu64, request->number);
219 request->master_state = REQUEST_ACTIVE;
220
221 /*
222 * Read packet from fp
223 */
224 if (fr_pair_list_afrom_file(request->request_ctx, dict_protocol, &request->request_pairs, fp, &filedone) < 0) {
225 goto error;
226 }
227
228 /*
229 * Pretend that the attributes came in "over the wire".
230 *
231 * @todo - do this only for protocol attributes, and not internal ones?
232 */
233 fr_pair_list_tainted(&request->request_pairs);
234
235 vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_packet_type);
236 if (!vp) {
237 fr_strerror_printf("Input packet does not specify a Packet-Type");
238 goto error;
239 }
240 /*
241 * Set the defaults for IPs, etc.
242 */
243 request->packet->code = vp->vp_uint32;
244
245 /*
246 * Now delete the packet-type to ensure
247 * the virtual attribute gets used in
248 * the tests.
249 */
250 fr_pair_delete_by_da(&request->request_pairs, attr_packet_type);
251
252 request->packet->socket = (fr_socket_t){
253 .type = SOCK_DGRAM,
254 .inet = {
255 .src_ipaddr = {
256 .af = AF_INET,
257 .prefix = 32,
258 .addr = {
259 .v4 = {
260 .s_addr = htonl(INADDR_LOOPBACK)
261 }
262 }
263 },
264 .src_port = 18120,
265 .dst_ipaddr = {
266 .af = AF_INET,
267 .prefix = 32,
268 .addr = {
269 .v4 = {
270 .s_addr = htonl(INADDR_LOOPBACK)
271 }
272 }
273 },
274 .dst_port = 1812
275 }
276 };
277
278 /*
279 * Fill in the packet header from attributes, and then
280 * re-realize the attributes.
281 */
282 vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_packet_type);
283 if (vp) request->packet->code = vp->vp_uint32;
284
285 fr_packet_net_from_pairs(request->packet, &request->request_pairs);
286
287 /*
288 * The input might have updated only some of the Net.*
289 * attributes. So for consistency, we create all of them
290 * from the packet header.
291 */
292 if (fr_packet_pairs_from_packet(request->request_ctx, &request->request_pairs, request->packet) < 0) {
293 fr_strerror_const("Failed converting packet IPs to attributes");
294 goto error;
295 }
296
297 /*
298 * For laziness in the tests, allow the Net.* to be mutable
299 */
300 for (vp = fr_pair_dcursor_by_ancestor_init(&cursor, &request->request_pairs, attr_net);
301 vp != NULL;
302 vp = fr_dcursor_next(&cursor)) {
304 }
305
306 if (fr_debug_lvl) {
307 for (vp = fr_pair_dcursor_init(&cursor, &request->request_pairs);
308 vp;
309 vp = fr_dcursor_next(&cursor)) {
310 /*
311 * Take this opportunity to verify all the fr_pair_ts are still valid.
312 */
313 if (!talloc_get_type(vp, fr_pair_t)) {
314 ERROR("Expected fr_pair_t pointer got \"%s\"", talloc_get_name(vp));
315
317 fr_assert(0);
318 }
319
320 fr_log(&default_log, L_DBG, __FILE__, __LINE__, "%pP", vp);
321 }
322 }
323
324 /*
325 * Build the reply template from the request.
326 */
327 fr_socket_addr_swap(&request->reply->socket, &request->packet->socket);
328
329 request->reply->id = request->packet->id;
330 request->reply->code = 0; /* UNKNOWN code */
331 memcpy(request->reply->vector, request->packet->vector, sizeof(request->reply->vector));
332 request->reply->data = NULL;
333 request->reply->data_len = 0;
334
335 /*
336 * Debugging
337 */
338 request->log.dst = talloc_zero(request, log_dst_t);
339 request->log.dst->func = vlog_request;
340 request->log.dst->uctx = &default_log;
341 request->log.dst->lvl = fr_debug_lvl;
342
343 request->master_state = REQUEST_ACTIVE;
344 request->log.lvl = fr_debug_lvl;
345 request->async = talloc_zero(request, fr_async_t);
346
347
348 /*
349 * New async listeners
350 */
351 request->async = talloc_zero(request, fr_async_t);
352 unlang_call_push(request, server_cs, UNLANG_TOP_FRAME);
353
354 return request;
355}
356
357
358static void print_packet(FILE *fp, fr_packet_t *packet, fr_pair_list_t *list)
359{
361 fr_log_t log;
362
363 (void) fr_log_init_fp(&log, fp);
364
366 if (dv) {
367 fr_log(&default_log, L_DBG, __FILE__, __LINE__, "Packet-Type = %s", dv->name);
368 } else {
369 fr_log(&default_log, L_DBG, __FILE__, __LINE__, "Packet-Type = %u", packet->code);
370 }
371
372 fr_pair_list_log(&default_log, 2, list);
373}
374
375/*
376 * A common function for reports of too much text when handling xlat
377 * and xlat_expr in do_xlats().
378 * The convolution deals with the edge case of the line being so long
379 * that it plus the surrounding text from the format could won't fit
380 * in the output sbuff, along with the fact that you don't print the
381 * %d or %.*s. OTOH it does include slen, but...
382 * * the format string is 41 characters minus 6 for %d and %.*s
383 * * given that slen reflects text read from line, once slen is
384 * large enough, we know line will fit
385 */
386static inline CC_HINT(always_inline) void too_much_text(fr_sbuff_t *out, ssize_t slen, fr_sbuff_t *line)
387{
388 char const *format = "ERROR offset %d 'Too much text' ::%.*s::";
389
390 (void) fr_sbuff_in_sprintf(out, format, (int) slen,
391 fr_sbuff_remaining(out) - (strlen(format) - 5),
393}
394
395/*
396 * Read a file composed of xlat's and expected results
397 */
398static bool do_xlats(fr_event_list_t *el, request_t *request, char const *filename, FILE *fp)
399{
400 int lineno = 0;
401 ssize_t len;
402 char line_buff[8192];
403 char output_buff[8192];
404 char unescaped[sizeof(output_buff)];
407
408 static fr_sbuff_escape_rules_t unprintables = {
409 .name = "unprintables",
410 .chr = '\\',
411 .esc = {
414 },
415 .do_utf8 = true,
416 .do_oct = true
417 };
418
419 while (fgets(line_buff, sizeof(line_buff), fp) != NULL) {
420 lineno++;
421
422 line = FR_SBUFF_IN(line_buff, sizeof(line_buff));
423 if (!fr_sbuff_adv_to_chr(&line, SIZE_MAX, '\n')) {
424 if (!feof(fp)) {
425 fprintf(stderr, "%s[%d] Line too long\n", filename, lineno);
426 return false;
427 }
428 } else {
429 fr_sbuff_terminate(&line);
430 }
431 line.end = line.p;
432 fr_sbuff_set_to_start(&line);
433
434 /*
435 * Ignore blank lines and comments
436 */
437 fr_sbuff_adv_past_whitespace(&line, SIZE_MAX, NULL);
438 if (*fr_sbuff_current(&line) < ' ') continue;
439 if (fr_sbuff_is_char(&line, '#')) continue;
440
441 /*
442 * Look for "match", as it needs the output_buffer to be left alone.
443 */
444 if (fr_sbuff_adv_past_str_literal(&line, "match ") > 0) {
445 size_t output_len = strlen(output_buff);
446
447 if (!fr_sbuff_is_str(&line, output_buff, output_len) || (output_len != fr_sbuff_remaining(&line))) {
448 fprintf(stderr, "Mismatch at %s[%u]\n\tgot : %s (%zu)\n\texpected : %s (%zu)\n",
449 filename, lineno, output_buff, output_len, fr_sbuff_current(&line), fr_sbuff_remaining(&line));
450 return false;
451 }
452 continue;
453 }
454
455 /*
456 * The rest of the keywords create output.
457 */
458 output_buff[0] = '\0';
459 out = FR_SBUFF_OUT(output_buff, sizeof(output_buff));
460
461 /*
462 * Look for "xlat"
463 */
464 if (fr_sbuff_adv_past_str_literal(&line, "xlat ") > 0) {
465 ssize_t slen;
466 TALLOC_CTX *xlat_ctx = talloc_init_const("xlat");
467 xlat_exp_head_t *head = NULL;
468 fr_sbuff_parse_rules_t p_rules = { .escapes = &fr_value_unescape_double };
469 tmpl_rules_t t_rules = (tmpl_rules_t) {
470 .attr = {
472 .list_def = request_attr_request,
473 .allow_unresolved = true,
474 },
475 .xlat = {
476 .runtime_el = el,
477 },
478 .at_runtime = true,
479 };
480
481
482 slen = xlat_tokenize(xlat_ctx, &head, &line, &p_rules, &t_rules);
483 if (slen <= 0) {
485 fr_sbuff_in_sprintf(&out, "ERROR offset %d '%s'", (int) -slen, fr_strerror());
486 continue;
487 }
488
489 if (fr_sbuff_remaining(&line) > 0) {
491 too_much_text(&out, slen, &line);
492 continue;
493 }
494
495 len = xlat_eval_compiled(unescaped, sizeof(unescaped), request, head, NULL, NULL);
496 if (len < 0) {
497 char const *err = fr_strerror();
499 (void) fr_sbuff_in_sprintf(&out, "ERROR expanding xlat: %s", *err ? err : "no error provided");
500 continue;
501 }
502
503 /*
504 * Escape the output as if it were a double quoted string.
505 */
506 fr_sbuff_in_escape(&out, unescaped, len, &unprintables);
507
508 TALLOC_FREE(xlat_ctx); /* also frees 'head' */
509 continue;
510 }
511
512 /*
513 * Look for "xlat_expr"
514 */
515 if (fr_sbuff_adv_past_str_literal(&line, "xlat_expr ") > 0) {
516 ssize_t slen;
517 TALLOC_CTX *xlat_ctx = talloc_init_const("xlat");
518 xlat_exp_head_t *head = NULL;
519
521 &line,
522 NULL,
523 &(tmpl_rules_t) {
524 .attr = {
525 .dict_def = dict_protocol,
526 .list_def = request_attr_request,
527 .allow_unresolved = true,
528 },
529 .xlat = {
530 .runtime_el = el,
531 },
532 .at_runtime = true,
533 });
534 if (slen <= 0) {
536 fr_sbuff_in_sprintf(&out, "ERROR offset %d '%s'", (int) -slen - 1, fr_strerror());
537 continue;
538 }
539
540 if (fr_sbuff_remaining(&line) > 0) {
542 too_much_text(&out, slen, &line);
543 continue;
544 }
545
546 if (xlat_resolve(head, NULL) < 0) {
548 (void) fr_sbuff_in_sprintf(&out, "ERROR resolving xlat: %s", fr_strerror());
549 continue;
550 }
551
552 len = xlat_eval_compiled(unescaped, sizeof(unescaped), request, head, NULL, NULL);
553 if (len < 0) {
554 char const *err = fr_strerror();
556 (void) fr_sbuff_in_sprintf(&out, "ERROR expanding xlat: %s", *err ? err : "no error provided");
557 continue;
558 }
559
560 /*
561 * Escape the output as if it were a double quoted string.
562 */
563 fr_sbuff_in_escape(&out, unescaped, len, &unprintables);
564
565 TALLOC_FREE(xlat_ctx); /* also frees 'head' */
566 continue;
567 }
568
569 fprintf(stderr, "Unknown keyword in %s[%d]\n", filename, lineno);
570 return false;
571 }
572
573 return true;
574}
575
576/*
577 * Verify the result of the map.
578 */
579static int map_proc_verify(CONF_SECTION *cs, UNUSED void const *mod_inst, UNUSED void *proc_inst,
580 tmpl_t const *src, UNUSED map_list_t const *maps)
581{
582 if (!src) {
583 cf_log_err(cs, "Missing source");
584
585 return -1;
586 }
587
588 return 0;
589}
590
591static unlang_action_t mod_map_proc(rlm_rcode_t *p_result, UNUSED void const *mod_inst, UNUSED void *proc_inst,
592 UNUSED request_t *request, UNUSED fr_value_box_list_t *src,
593 UNUSED map_list_t const *maps)
594{
596}
597
598static request_t *request_clone(request_t *old, int number, CONF_SECTION *server_cs)
599{
600 request_t *request;
601
602 request = request_local_alloc_internal(NULL, (&(request_init_args_t){ .namespace = old->proto_dict }));
603 if (!request) return NULL;
604
605 if (!request->packet) request->packet = fr_packet_alloc(request, false);
606 if (!request->reply) request->reply = fr_packet_alloc(request, false);
607
608 memcpy(request->packet, old->packet, sizeof(*request->packet));
609 (void) fr_pair_list_copy(request->request_ctx, &request->request_pairs, &old->request_pairs);
610 request->packet->timestamp = fr_time();
611 request->number = number;
612 request->name = talloc_typed_asprintf(request, "%" PRIu64, request->number);
613
614 unlang_call_push(request, server_cs, UNLANG_TOP_FRAME);
615
616 request->master_state = REQUEST_ACTIVE;
617
618 return request;
619}
620
621static void cancel_request(UNUSED fr_timer_list_t *tl, UNUSED fr_time_t when, void *uctx)
622{
623 request_t *request = talloc_get_type_abort(uctx, request_t);
625}
626
627/**
628 *
629 * @hidecallgraph
630 */
631int main(int argc, char *argv[])
632{
633 int ret = EXIT_SUCCESS;
634 int c;
635 int count = 1;
636 const char *input_file = NULL;
637 const char *xlat_input_file = NULL;
638 const char *output_file = NULL;
639 const char *filter_file = NULL;
640 FILE *fp = NULL;
641 request_t *request = NULL;
642 fr_pair_t *vp;
643 fr_pair_list_t filter_vps;
644 bool xlat_only = false;
645 fr_event_list_t *el = NULL;
646 fr_timer_t *cancel_timer = NULL;
647 fr_client_t *client = NULL;
648 fr_dict_t *dict = NULL;
649 fr_dict_t const *dict_check;
650 char const *receipt_file = NULL;
651
652 TALLOC_CTX *autofree;
653 TALLOC_CTX *thread_ctx;
654
655 char *p;
657
658 CONF_SECTION *server_cs;
659
660#ifndef NDEBUG
661 size_t memory_used_before = 0;
662 size_t memory_used_after = 0;
663#endif
664 virtual_server_t const *vs;
665
666 fr_pair_list_init(&filter_vps);
667
668 /*
669 * Must be called first, so the handler is called last
670 */
672
674 thread_ctx = talloc_new(autofree);
675
677 if (!config) {
678 fr_perror("unit_test_module");
679 fr_exit_now(EXIT_FAILURE);
680 }
681
682 p = strrchr(argv[0], FR_DIR_SEP);
683 if (!p) {
684 main_config_name_set_default(config, argv[0], false);
685 } else {
687 }
688
690
691 /*
692 * If the server was built with debugging enabled always install
693 * the basic fatal signal handlers.
694 */
695#ifndef NDEBUG
696 if (fr_fault_setup(autofree, getenv("PANIC_ACTION"), argv[0]) < 0) {
697 fr_perror("%s", config->name);
698 fr_exit_now(EXIT_FAILURE);
699 }
700#else
702#endif
703
704 fr_debug_lvl = 0;
706
707 /*
708 * The tests should have only IPs, not host names.
709 */
711
712 /*
713 * We always log to stdout.
714 */
716 default_log.fd = STDOUT_FILENO;
718
719 /* Process the options. */
720 while ((c = getopt(argc, argv, "c:d:D:f:hi:I:mMn:o:p:r:S:xXz")) != -1) {
721 switch (c) {
722 case 'c':
723 count = atoi(optarg);
724 break;
725
726 case 'd':
728 break;
729
730 case 'D':
732 break;
733
734 case 'f':
735 filter_file = optarg;
736 break;
737
738 case 'h':
739 usage(config, EXIT_SUCCESS);
740 break;
741
742 case 'i':
743 input_file = optarg;
744 break;
745
746 case 'I':
747 xlat_input_file = optarg;
748 xlat_only = true;
749 break;
750
751 case 'M':
752 talloc_enable_leak_report();
753 break;
754
755 case 'n':
756 config->name = optarg;
757 break;
758
759 case 'o':
760 output_file = optarg;
761 break;
762
763 case 'p':
764 PROTOCOL_NAME = optarg;
765 break;
766
767 case 'r':
768 receipt_file = optarg;
769 break;
770
771 case 'S': /* Migration support */
772 if (main_config_parse_option(optarg) < 0) {
773 fprintf(stderr, "%s: Unknown configuration option '%s'\n",
774 config->name, optarg);
775 fr_exit_now(EXIT_FAILURE);
776 }
777 break;
778
779 case 'X':
780 fr_debug_lvl += 2;
782 break;
783
784 case 'x':
785 fr_debug_lvl++;
786 if (fr_debug_lvl > 2) default_log.print_level = true;
787 break;
788
789 case 'z':
790 my_debug_lvl++;
791 break;
792
793 default:
794 usage(config, EXIT_FAILURE);
795 break;
796 }
797 }
798
799 if (receipt_file && (fr_unlink(receipt_file) < 0)) {
800 fr_perror("%s", config->name);
802 }
803
804#ifdef WITH_TLS
805 /*
806 * Mismatch between build time OpenSSL and linked SSL, better to die
807 * here than segfault later.
808 */
810
811 /*
812 * Initialising OpenSSL once, here, is safer than having individual modules do it.
813 * Must be called before display_version to ensure relevant engines are loaded.
814 *
815 * fr_openssl_init() must be called before *ANY* OpenSSL functions are used, which is why
816 * it's called so early.
817 */
818 if (fr_openssl_init() < 0) EXIT_WITH_FAILURE;
819#endif
820
822
823 /*
824 * Mismatch between the binary and the libraries it depends on
825 */
827 fr_perror("%s", config->name);
828 ret = EXIT_FAILURE;
829 goto cleanup;
830 }
831
832 /*
833 * Initialize the DL infrastructure, which is used by the
834 * config file parser.
835 */
836 modules_init(config->lib_dir);
837
838 if (!fr_dict_global_ctx_init(NULL, true, config->dict_dir)) {
839 fr_perror("%s", config->name);
841 }
842
844 fr_perror("%s", config->name);
846 }
847
848#ifdef WITH_TLS
849 if (fr_tls_dict_init() < 0) EXIT_WITH_FAILURE;
850#endif
851
852 /*
853 * Load the custom dictionary
854 */
855 if (fr_dict_read(dict, config->raddb_dir, FR_DICTIONARY_FILE) == -1) {
856 PERROR("Failed to initialize the dictionaries");
858 }
859
861 fr_perror("%s", config->name);
863 }
865 fr_perror("%s", config->name);
867 }
868
869 if (request_global_init() < 0) {
870 fr_perror("unit_test_module");
872 }
873
874 if (map_proc_register(NULL, NULL, "test-fail", mod_map_proc, map_proc_verify, 0, 0) < 0) {
876 }
877
878 /*
879 * Initialise the interpreter, registering operations.
880 * This initialises
881 */
882 if (unlang_global_init() < 0) {
883 fr_perror("%s", config->name);
885 }
886
887 /*
888 * Ensure that we load the correct virtual server for the
889 * protocol, if necessary.
890 */
891 if (!getenv("PROTOCOL")) {
892 setenv("PROTOCOL", PROTOCOL_NAME, true);
893 }
894
895 /*
896 * Setup the global structures for module lists
897 */
898 if (modules_rlm_init() < 0) {
899 fr_perror("%s", config->name);
901 }
902 if (virtual_servers_init() < 0) {
903 fr_perror("%s", config->name);
905 }
906
907 if (main_config_init(config) < 0) {
909 }
910
911 /*
912 * Create a dummy client on 127.0.0.1, if one doesn't already exist.
913 */
914 client = client_find(NULL, &(fr_ipaddr_t) { .af = AF_INET, .prefix = 32, .addr.v4.s_addr = htonl(INADDR_LOOPBACK) },
915 IPPROTO_IP);
916 if (!client) {
917 client = client_alloc(NULL, "127.0.0.1", "test");
918 client_add(NULL, client);
919 }
920
921 if (server_init(config->root_cs, config->raddb_dir, dict) < 0) EXIT_WITH_FAILURE;
922
923 vs = virtual_server_find("default");
924 if (!vs) {
925 ERROR("Cannot find virtual server 'default'");
927 }
928
929 server_cs = virtual_server_cs(vs);
930
931 /*
932 * Do some sanity checking.
933 */
934 dict_check = virtual_server_dict_by_name("default");
935 if (!dict_check || !fr_dict_compatible(dict_check, dict_protocol)) {
936 ERROR("Virtual server namespace does not match requested namespace '%s'", PROTOCOL_NAME);
938 }
939
940 /*
941 * Create a dummy event list
942 */
943 el = fr_event_list_alloc(NULL, NULL, NULL);
944 fr_assert(el != NULL);
945
946 /*
947 * Simulate thread specific instantiation
948 */
951 if (xlat_thread_instantiate(thread_ctx, el) < 0) EXIT_WITH_FAILURE;
952 unlang_thread_instantiate(thread_ctx);
953
954 /*
955 * Set the panic action (if required)
956 */
957 {
958 char const *panic_action = NULL;
959
960 panic_action = getenv("PANIC_ACTION");
961 if (!panic_action) panic_action = config->panic_action;
962
963 if (panic_action && (fr_fault_setup(autofree, panic_action, argv[0]) < 0)) {
964 fr_perror("%s", config->name);
966 }
967 }
968
969 setlinebuf(stdout); /* unbuffered output */
970
971#ifndef NDEBUG
972 memory_used_before = talloc_total_size(autofree);
973#endif
974
975 if (!input_file && !xlat_only) input_file = "-";
976
977 if (input_file) {
978 if (strcmp(input_file, "-") == 0) {
979 fp = stdin;
980 } else {
981 fp = fopen(input_file, "r");
982 if (!fp) {
983 fprintf(stderr, "Failed reading %s: %s\n",
984 input_file, fr_syserror(errno));
986 }
987 }
988
989 /*
990 * Grab the VPs from stdin, or from the file.
991 */
992 request = request_from_file(autofree, fp, client, server_cs);
993 if (!request) {
994 fr_perror("Failed reading input from %s", input_file);
996 }
997 } else {
999 }
1000
1001 /*
1002 * For simplicity, read xlat's.
1003 */
1004 if (xlat_only) {
1005 if (fp && (fp != stdin)) fclose(fp);
1006
1007 fp = fopen(xlat_input_file, "r");
1008 if (!fp) {
1009 fprintf(stderr, "Failed reading %s: %s\n",
1010 xlat_input_file, fr_syserror(errno));
1012 }
1013
1014 if (!do_xlats(el, request, xlat_input_file, fp)) ret = EXIT_FAILURE;
1015 if (input_file) fclose(fp);
1016 goto cleanup;
1017 }
1018
1019 /*
1020 * No filter file, OR there's no more input, OR we're
1021 * reading from a file, and it's different from the
1022 * filter file.
1023 */
1024 if (!filter_file || filedone ||
1025 ((input_file != NULL) && (strcmp(filter_file, input_file) != 0))) {
1026 if (output_file) {
1027 if (fp && (fp != stdin)) fclose(fp);
1028 fp = NULL;
1029 }
1030 filedone = false;
1031 }
1032
1033 /*
1034 * There is a filter file. If necessary, open it. If we
1035 * already are reading it via "input_file", then we don't
1036 * need to re-open it.
1037 */
1038 if (filter_file) {
1039 if (!fp) {
1040 fp = fopen(filter_file, "r");
1041 if (!fp) {
1042 fprintf(stderr, "Failed reading %s: %s\n", filter_file, fr_syserror(errno));
1044 }
1045 }
1046
1047 if (fr_pair_list_afrom_file(request->request_ctx, dict_protocol, &filter_vps, fp, &filedone) < 0) {
1048 fr_perror("Failed reading attributes from %s", filter_file);
1050 }
1051
1052 /*
1053 * Filter files can't be empty.
1054 */
1055 if (fr_pair_list_empty(&filter_vps)) {
1056 fr_perror("No attributes in filter file %s", filter_file);
1058 }
1059
1060 /*
1061 * FIXME: loop over input packets.
1062 */
1063 fclose(fp);
1064 }
1065
1066 if (count == 1) {
1067 fr_timer_in(request, el->tl, &cancel_timer, config->worker.max_request_time, false, cancel_request, request);
1069
1070 } else {
1071 int i;
1072 request_t *cached = request;
1073
1074 for (i = 0; i < count; i++) {
1075#ifndef NDEBUG
1076 size_t request_used_before, request_used_after;
1077#endif
1078
1079 request = request_clone(cached, i, server_cs);
1080
1081#ifndef NDEBUG
1082 request_used_before = talloc_total_size(autofree);
1083
1084 /*
1085 * Artificially limit the number of instructions which are run.
1086 */
1087 if (config->ins_max) {
1088 if (config->ins_countup) {
1089 request->ins_max = i + 1;
1090 } else {
1091 request->ins_max = config->ins_max;
1092 }
1093
1094 if (request->ins_max < 10) request->ins_max = 10;
1095
1096 request->ins_count = 0;
1097 }
1098#endif
1099
1100 fr_timer_in(request, el->tl, &cancel_timer, config->worker.max_request_time, false, cancel_request, request);
1102 talloc_free(request);
1103
1104#ifndef NDEBUG
1105 request_used_after = talloc_total_size(autofree);
1106 fr_assert(request_used_after == request_used_before);
1107#endif
1108 }
1109
1110 request = cached;
1111 }
1112
1113 if (!output_file || (strcmp(output_file, "-") == 0)) {
1114 fp = stdout;
1115 } else {
1116 fp = fopen(output_file, "w");
1117 if (!fp) {
1118 fprintf(stderr, "Failed writing %s: %s\n", output_file, fr_syserror(errno));
1119 goto cleanup;
1120 }
1121 }
1122
1123 print_packet(fp, request->reply, &request->reply_pairs);
1124
1125 if (output_file) fclose(fp);
1126
1127 /*
1128 * Update the list with the response type, so that it can
1129 * be matched in filters.
1130 *
1131 * Some state machines already include a response Packet-Type
1132 * so we need to try and update it, else we end up with two!
1133 */
1134 if (!fr_pair_list_empty(&filter_vps)) {
1135 fr_pair_t const *failed[2];
1136
1138 vp->vp_uint32 = request->reply->code;
1139
1140
1141 if (!fr_pair_validate(failed, &filter_vps, &request->reply_pairs)) {
1142 fr_pair_validate_debug(failed);
1143 fr_perror("Output file %s does not match attributes in filter %s",
1144 output_file ? output_file : "-", filter_file);
1145 ret = EXIT_FAILURE;
1146 goto cleanup;
1147 }
1148 }
1149
1150 INFO("Exiting normally");
1151
1152cleanup:
1153 talloc_free(request);
1154
1155 /*
1156 * No leaks.
1157 */
1158#ifndef NDEBUG
1159 memory_used_after = talloc_total_size(autofree);
1160 if (memory_used_after != memory_used_before) {
1161 printf("WARNING: May have leaked memory (%zd - %zd = %zd)\n",
1162 memory_used_after, memory_used_before, memory_used_after - memory_used_before);
1163 }
1164#endif
1165
1166 map_proc_unregister("test-fail");
1167
1168 /*
1169 * Free thread data
1170 */
1171 talloc_free(thread_ctx);
1172
1173 /*
1174 * Ensure all thread local memory is cleaned up
1175 * at the appropriate time. This emulates what's
1176 * done with worker/network threads in the
1177 * scheduler.
1178 */
1180
1181 /*
1182 * Give processes a chance to exit
1183 */
1185
1186 /*
1187 * Free the event list.
1188 */
1189 talloc_free(el);
1190
1191 /*
1192 * Ensure all thread local memory is cleaned up
1193 * at the appropriate time. This emulates what's
1194 * done with worker/network threads in the
1195 * scheduler.
1196 */
1198
1199 server_free();
1200
1201 /*
1202 * Virtual servers need to be freed before modules
1203 * as state entries containing data with module-specific
1204 * destructors may exist.
1205 */
1207
1208 /*
1209 * Free modules, this needs to be done explicitly
1210 * because some libraries used by modules use atexit
1211 * handlers registered after ours, and they may deinit
1212 * themselves before we free the modules and cause
1213 * crashes on exit.
1214 */
1216
1217 /*
1218 * And now nothing should be left anywhere except the
1219 * parsed configuration items.
1220 */
1222
1223#ifdef WITH_TLS
1224 fr_tls_dict_free();
1225#endif
1226
1227 /*
1228 * Free any autoload dictionaries
1229 */
1231
1232 /*
1233 * Free our explicitly loaded internal dictionary
1234 */
1235 if (fr_dict_free(&dict, __FILE__) < 0) {
1236 fr_perror("unit_test_module - dict");
1237 ret = EXIT_FAILURE;
1238 }
1239
1240 /*
1241 * Free any openssl resources and the TLS dictionary
1242 */
1243#ifdef WITH_TLS
1244 fr_openssl_free();
1245#endif
1246
1247 if (receipt_file && (ret == EXIT_SUCCESS) && (fr_touch(NULL, receipt_file, 0644, true, 0755) <= 0)) {
1248 fr_perror("unit_test_module");
1249 ret = EXIT_FAILURE;
1250 }
1251
1252 if (talloc_free(autofree) < 0) {
1253 fr_perror("unit_test_module - autofree");
1254 ret = EXIT_FAILURE;
1255 }
1256
1257 /*
1258 * Ensure our atexit handlers run before any other
1259 * atexit handlers registered by third party libraries.
1260 */
1262
1263 return ret;
1264}
1265
1266
1267/*
1268 * Display the syntax for starting this program.
1269 */
1270static NEVER_RETURNS void usage(main_config_t const *config, int status)
1271{
1272 FILE *output = status ? stderr : stdout;
1273
1274 fprintf(output, "Usage: %s [options]\n", config->name);
1275 fprintf(output, "Options:\n");
1276 fprintf(output, " -c <count> Run packets through the interpreter <count> times\n");
1277 fprintf(output, " -d <raddb_dir> Configuration files are in \"raddb_dir/*\".\n");
1278 fprintf(output, " -D <dict_dir> Dictionary files are in \"dict_dir/*\".\n");
1279 fprintf(output, " -f <file> Filter reply against attributes in 'file'.\n");
1280 fprintf(output, " -h Print this help message.\n");
1281 fprintf(output, " -i <file> File containing request attributes.\n");
1282 fprintf(output, " -m On SIGINT or SIGQUIT exit cleanly instead of immediately.\n");
1283 fprintf(output, " -n <name> Read raddb/name.conf instead of raddb/radiusd.conf.\n");
1284 fprintf(output, " -o <file> Output file for the reply.\n");
1285 fprintf(output, " -p <radius|...> Define which protocol namespace is used to read the file\n");
1286 fprintf(output, " Use radius, dhcpv4, or dhcpv6\n");
1287 fprintf(output, " -X Turn on full debugging.\n");
1288 fprintf(output, " -x Turn on additional debugging. (-xx gives more debugging).\n");
1289 fprintf(output, " -r <receipt_file> Create the <receipt_file> as a 'success' exit.\n");
1290
1291 fr_exit_now(status);
1292}
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:485
#define NEVER_RETURNS
Should be placed before the function return type.
Definition build.h:315
#define UNUSED
Definition build.h:317
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:1278
#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:375
#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:3351
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:4394
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:862
static fr_slen_t err
Definition dict.h:833
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:2621
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:272
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:285
int fr_dict_free(fr_dict_t **dict, char const *dependent)
Decrement the reference count on a previously loaded dictionary.
Definition dict_util.c:4026
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:4092
#define fr_dict_autoload(_to_load)
Definition dict.h:859
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:232
Specifies an attribute which must be present for the module to function.
Definition dict.h:271
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:284
Value of an enumerated attribute.
Definition dict.h:231
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:1212
#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:59
int server_init(CONF_SECTION *cs, char const *dict_dir, fr_dict_t *dict)
Initialize src/lib/server/.
Definition base.c:42
void server_free(void)
Free src/lib/server/.
Definition base.c:130
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
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:1699
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:2523
Stores all information relating to an event list.
Definition event.c:377
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:1059
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:580
@ 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:177
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:125
@ 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:962
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:3356
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:2321
void fr_pair_validate_debug(fr_pair_t const *failed[2])
Write an error to the library errorbuff detailing the mismatch.
Definition pair.c:2095
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:695
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:1691
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:2130
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:43
int request_global_init(void)
Definition request.c:589
#define request_local_alloc_internal(_ctx, _args)
Allocate a new internal request outside of the request pool.
Definition request.h:339
#define request_local_alloc_external(_ctx, _args)
Allocate a new external request outside of the request pool.
Definition request.h:331
@ REQUEST_ACTIVE
Request is active (running or runnable)
Definition request.h:87
Optional arguments for initialising requests.
Definition request.h:283
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:1622
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:1958
ssize_t fr_sbuff_in_sprintf(fr_sbuff_t *sbuff, char const *fmt,...)
Print using a fmt string to an sbuff.
Definition sbuff.c:1597
#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:335
struct tmpl_rules_s tmpl_rules_t
Definition tmpl.h:233
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:332
@ 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:701
fr_client_t * client_find(fr_client_list_t const *clients, fr_ipaddr_t const *ipaddr, int proto)
Definition client.c:373
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:1904
return count
Definition module.c:155
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: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:488
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
An event timer list.
Definition timer.c:49
A timer event.
Definition timer.c:75
#define fr_timer_in(...)
Definition timer.h:86
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
#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 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)
int unlang_thread_instantiate(TALLOC_CTX *ctx)
Create thread-specific data structures for unlang.
Definition compile.c:5164
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:1708
static fr_slen_t head
Definition xlat.h:416
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:442
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:3030
#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:851
#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: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_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:265
#define fr_box_uint32(_val)
Definition value.h:323
int format(printf, 5, 0))
static size_t char ** out
Definition value.h:1012
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