The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
rlm_mruby.c
Go to the documentation of this file.
1/*
2 * This program is 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 (at
5 * 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/**
18 * $Id: 655b5ce8590b4197f0573f18cc91aa6978faa8d7 $
19 * @file rlm_mruby.c
20 * @brief Translates requests between the server an an mruby interpreter.
21 *
22 * @copyright 2016 Herwin Weststrate (freeradius@herwinw.nl)
23 * @copyright 2016 The FreeRADIUS server project
24 */
25RCSID("$Id: 655b5ce8590b4197f0573f18cc91aa6978faa8d7 $")
26
27#include <freeradius-devel/server/base.h>
28#include <freeradius-devel/server/module_rlm.h>
29#include <freeradius-devel/server/pairmove.h>
30#include <freeradius-devel/util/debug.h>
31
32#include "rlm_mruby.h"
33
34typedef struct {
35 char const *function_name; //!< Name of the function being called
36 char *name1; //!< Section name1 where this is called
37 char *name2; //!< Section name2 where this is called
38 fr_rb_node_t node; //!< Node in tree of function calls.
40
44
45/*
46 * Define a structure for our module configuration.
47 *
48 * These variables do not need to be in a structure, but it's
49 * a lot cleaner to do so, and a pointer to the structure can
50 * be used as the instance handle.
51 */
52typedef struct {
53 char const *filename;
54 char const *module_name;
55
56 fr_rb_tree_t funcs; //!< Tree of function calls found by call_env parser.
57 bool funcs_init; //!< Has the tree been initialised.
58
59 mrb_state *mrb;
60
61 struct RClass *mruby_module;
62 struct RClass *mruby_request;
63 mrb_value mrubyconf_hash;
65
66/*
67 * A mapping of configuration file names to internal variables.
68 */
69static const conf_parser_t module_config[] = {
71 { FR_CONF_OFFSET("module", rlm_mruby_t, module_name), .dflt = "Radiusd" },
73};
74
75/** How to compare two Ruby function calls
76 *
77 */
78static int8_t mruby_func_def_cmp(void const *one, void const *two)
79{
80 mruby_func_def_t const *a = one, *b = two;
81 int ret;
82
83 ret = strcmp(a->name1, b->name1);
84 if (ret != 0) return CMP(ret, 0);
85 if (!a->name2 && !b->name2) return 0;
86 if (!a->name2 || !b->name2) return a->name2 ? 1 : -1;
87 ret = strcmp(a->name2, b->name2);
88 return CMP(ret, 0);
89}
90
91static mrb_value mruby_log(mrb_state *mrb, UNUSED mrb_value self)
92{
93 mrb_int level;
94 char *msg = NULL;
95
96 mrb_get_args(mrb, "iz", &level, &msg);
97 fr_log(&default_log, level, __FILE__, __LINE__, "rlm_ruby: %s", msg);
98
99 return mrb_nil_value();
100}
101
102static void mruby_parse_config(mrb_state *mrb, CONF_SECTION *cs, int lvl, mrb_value hash)
103{
104 int indent_section = (lvl + 1) * 4;
105 int indent_item = (lvl + 2) * 4;
106 CONF_ITEM *ci = NULL;
107
108 if (!cs) return;
109
110 DEBUG("%*s%s {", indent_section, " ", cf_section_name1(cs));
111
112 while ((ci = cf_item_next(cs, ci))) {
113 if (cf_item_is_section(ci)) {
114 CONF_SECTION *sub_cs = cf_item_to_section(ci);
115 char const *key = cf_section_name1(sub_cs);
116 mrb_value sub_hash, mrubyKey;
117
118 if (!key) continue;
119
120 mrubyKey = mrb_str_new_cstr(mrb, key);
121
122 if (!mrb_nil_p(mrb_hash_get(mrb, hash, mrubyKey))) {
123 WARN("rlm_mruby: Ignoring duplicate config section '%s'", key);
124 continue;
125 }
126
127 sub_hash = mrb_hash_new(mrb);
128 mrb_hash_set(mrb, hash, mrubyKey, sub_hash);
129
130 mruby_parse_config(mrb, sub_cs, lvl + 1, sub_hash);
131 } else if (cf_item_is_pair(ci)) {
132 CONF_PAIR *cp = cf_item_to_pair(ci);
133 const char *key = cf_pair_attr(cp);
134 const char *value = cf_pair_value(cp);
135 mrb_value mrubyKey, mrubyValue;
136
137 if (!key || !value) continue;
138
139 mrubyKey = mrb_str_new_cstr(mrb, key);
140 mrubyValue = mrb_str_new_cstr(mrb, value);
141
142 if (!mrb_nil_p(mrb_hash_get(mrb, hash, mrubyKey))) {
143 WARN("rlm_mruby: Ignoring duplicate config item '%s'", key);
144 continue;
145 }
146
147 mrb_hash_set(mrb, hash, mrubyKey, mrubyValue);
148
149 DEBUG("%*s%s = %s", indent_item, " ", key, value);
150 }
151 }
152
153 DEBUG("%*s}", indent_section, " ");
154}
155
156/*
157 * Do any per-module initialization that is separate to each
158 * configured instance of the module. e.g. set up connections
159 * to external databases, read configuration files, set up
160 * dictionary entries, etc.
161 */
162static int mod_instantiate(module_inst_ctx_t const *mctx)
163{
164 rlm_mruby_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_mruby_t);
165 mrb_state *mrb;
166 CONF_SECTION *cs;
167 FILE *f;
168 mrb_value status;
169
170 mrb = inst->mrb = mrb_open();
171 if (!mrb) {
172 ERROR("mruby initialization failed");
173 return -1;
174 }
175
176 /* Define the freeradius module */
177 DEBUG("Creating module %s", inst->module_name);
178 inst->mruby_module = mrb_define_module(mrb, inst->module_name);
179 if (!inst->mruby_module) {
180 ERROR("Creating module %s failed", inst->module_name);
181 return -1;
182 }
183
184 /* Define the log method */
185 mrb_define_class_method(mrb, inst->mruby_module, "log", mruby_log, MRB_ARGS_REQ(2));
186
187#define A(x) mrb_define_const(mrb, inst->mruby_module, #x, mrb_fixnum_value(x));
188 /* Define the logging constants */
189 A(L_DBG);
190 A(L_WARN);
191 A(L_INFO);
192 A(L_ERR);
193 A(L_WARN);
194 A(L_DBG_WARN);
195 A(L_DBG_ERR);
198
199 /* Define the return value constants */
210#undef A
211
212 /* Convert a FreeRADIUS config structure into a mruby hash */
213 inst->mrubyconf_hash = mrb_hash_new(mrb);
214 cs = cf_section_find(mctx->mi->conf, "config", NULL);
215 if (cs) mruby_parse_config(mrb, cs, 0, inst->mrubyconf_hash);
216
217 /* Define the Request class */
218 inst->mruby_request = mruby_request_class(mrb, inst->mruby_module);
219
220 DEBUG("Loading file %s...", inst->filename);
221 f = fopen(inst->filename, "r");
222 if (!f) {
223 ERROR("Opening file failed");
224 return -1;
225 }
226
227 status = mrb_load_file(mrb, f);
228 fclose(f);
229 if (mrb_undef_p(status)) {
230 ERROR("Parsing file failed");
231 return -1;
232 }
233
234 status = mrb_funcall(mrb, mrb_obj_value(inst->mruby_module), "instantiate", 0);
235 if (mrb_undef_p(status)) {
236 ERROR("Running instantiate failed");
237 return -1;
238 }
239
240 return 0;
241}
242
243static int mruby_vps_to_array(request_t *request, mrb_value *out, mrb_state *mrb, fr_pair_list_t *vps)
244{
245 mrb_value res;
246 fr_pair_t *vp;
247
248 res = mrb_ary_new(mrb);
249 for (vp = fr_pair_list_head(vps); vp; vp = fr_pair_list_next(vps, vp)) {
250 mrb_value tmp, key, val, to_cast;
251
252 tmp = mrb_ary_new_capa(mrb, 2);
253 key = mrb_str_new(mrb, vp->da->name, strlen(vp->da->name));
254
255 /*
256 * The only way to create floats, doubles, bools etc,
257 * is to feed mruby the string representation and have
258 * it convert to its internal types.
259 */
260 switch (vp->vp_type) {
261 case FR_TYPE_STRING:
262 case FR_TYPE_OCTETS:
263 to_cast = mrb_str_new(mrb, vp->vp_ptr, vp->vp_length);
264 break;
265
266 case FR_TYPE_BOOL:
267#ifndef NDEBUG
268 to_cast = mrb_nil_value(); /* Not needed but clang flags it */
269#endif
270 break;
271
272 default:
273 {
274 char *in;
275 size_t len;
276
277 len = fr_value_box_aprint(request, &in, &vp->data, NULL);
278 to_cast = mrb_str_new(mrb, in, len);
280 }
281 break;
282 }
283
284 switch (vp->vp_type) {
285 case FR_TYPE_STRING:
286 case FR_TYPE_OCTETS:
291 case FR_TYPE_IFID:
292 case FR_TYPE_ETHERNET:
295 val = to_cast; /* No conversions required */
296 break;
297
298 case FR_TYPE_BOOL:
299 val = vp->vp_bool ? mrb_obj_value(mrb->true_class) : mrb_obj_value(mrb->false_class);
300 break;
301
302 case FR_TYPE_UINT8:
303 case FR_TYPE_UINT16:
304 case FR_TYPE_UINT32:
305 case FR_TYPE_UINT64:
306 case FR_TYPE_INT8:
307 case FR_TYPE_INT16:
308 case FR_TYPE_INT32:
309 case FR_TYPE_INT64:
310 case FR_TYPE_DATE:
312 case FR_TYPE_SIZE:
313 val = mrb_convert_type(mrb, to_cast, MRB_TT_FIXNUM, "Fixnum", "to_int");
314 break;
315
316 case FR_TYPE_FLOAT32:
317 case FR_TYPE_FLOAT64:
318 val = mrb_convert_type(mrb, to_cast, MRB_TT_FLOAT, "Float", "to_f");
319 break;
320
321 case FR_TYPE_NON_LEAF:
322 fr_assert(0);
323 return -1;
324 }
325
326 mrb_ary_push(mrb, tmp, key);
327 mrb_ary_push(mrb, tmp, val);
328 mrb_ary_push(mrb, res, tmp);
329
330 *out = res;
331 }
332
333 return 0;
334}
335
336static void add_vp_tuple(TALLOC_CTX *ctx, request_t *request, fr_pair_list_t *vps, mrb_state *mrb, mrb_value value, char const *function_name)
337{
338 int i;
339 fr_pair_list_t tmp_list;
340
341 fr_pair_list_init(&tmp_list);
342
343 for (i = 0; i < RARRAY_LEN(value); i++) {
344 mrb_value tuple = mrb_ary_entry(value, i);
345 mrb_value key, val;
346 char const *ckey, *cval;
347 fr_pair_t *vp;
348 tmpl_t *dst;
349 fr_token_t op = T_OP_EQ;
350
351 /* This tuple should be an array of length 2 */
352 if (mrb_type(tuple) != MRB_TT_ARRAY) {
353 REDEBUG("add_vp_tuple, %s: non-array passed at index %i", function_name, i);
354 continue;
355 }
356
357 if (RARRAY_LEN(tuple) != 2 && RARRAY_LEN(tuple) != 3) {
358 REDEBUG("add_vp_tuple, %s: array with incorrect length passed at index "
359 "%i, expected 2 or 3, got %"PRId64, function_name, i, RARRAY_LEN(tuple));
360 continue;
361 }
362
363 key = mrb_ary_entry(tuple, 0);
364 val = mrb_ary_entry(tuple, -1);
365 if (mrb_type(key) != MRB_TT_STRING) {
366 REDEBUG("add_vp_tuple, %s: tuple element %i must have a string as first element", function_name, i);
367 continue;
368 }
369
370 ckey = mrb_str_to_cstr(mrb, key);
371 cval = mrb_str_to_cstr(mrb, mrb_obj_as_string(mrb, val));
372 if (ckey == NULL || cval == NULL) {
373 REDEBUG("%s: string conv failed", function_name);
374 continue;
375 }
376
377
378 if (RARRAY_LEN(tuple) == 3) {
379 if (mrb_type(mrb_ary_entry(tuple, 1)) != MRB_TT_STRING) {
380 REDEBUG("Invalid type for operator, expected string, falling back to =");
381 } else {
382 char const *cop = mrb_str_to_cstr(mrb, mrb_ary_entry(tuple, 1));
383 if (!(op = fr_table_value_by_str(fr_tokens_table, cop, 0))) {
384 REDEBUG("Invalid operator: %s, falling back to =", cop);
385 op = T_OP_EQ;
386 }
387 }
388 }
389 DEBUG("%s: %s %s %s", function_name, ckey, fr_table_str_by_value(fr_tokens_table, op, "="), cval);
390
391 if (tmpl_afrom_attr_str(request, NULL, &dst, ckey,
392 &(tmpl_rules_t){
393 .attr = {
394 .dict_def = request->proto_dict,
395 .list_def = request_attr_reply,
396 }
397 }) <= 0) {
398 ERROR("Failed to find attribute %s", ckey);
399 continue;
400 }
401
402 if (tmpl_request_ptr(&request, tmpl_request(dst)) < 0) {
403 ERROR("Attribute name %s refers to outer request but not in a tunnel, skipping...", ckey);
404 talloc_free(dst);
405 continue;
406 }
407
409 talloc_free(dst);
410
411 if (fr_pair_value_from_str(vp, cval, strlen(cval), NULL, false) < 0) {
412 REDEBUG("%s: %s = %s failed", function_name, ckey, cval);
413 } else {
414 DEBUG("%s: %s = %s OK", function_name, ckey, cval);
415 }
416
417 fr_pair_append(&tmp_list, vp);
418 }
419 radius_pairmove(request, vps, &tmp_list);
420}
421
422static inline int mruby_set_vps(request_t *request, mrb_state *mrb, mrb_value mruby_request,
423 char const *list_name, fr_pair_list_t *vps)
424{
425 mrb_value res;
426
427 memset(&res, 0, sizeof(res)); /* clang scan */
428
429 if (mruby_vps_to_array(request, &res, mrb, vps) < 0) return -1;
430
431 mrb_iv_set(mrb, mruby_request, mrb_intern_cstr(mrb, list_name), res);
432
433 return 0;
434}
435
436static unlang_action_t CC_HINT(nonnull) mod_mruby(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
437{
438 rlm_mruby_t const *inst = talloc_get_type_abort(mctx->mi->data, rlm_mruby_t);
439 mruby_call_env_t *func = talloc_get_type_abort(mctx->env_data, mruby_call_env_t);
440 mrb_state *mrb = inst->mrb;
441 mrb_value mruby_request, mruby_result;
442
443 mruby_request = mrb_obj_new(mrb, inst->mruby_request, 0, NULL);
444 mrb_iv_set(mrb, mruby_request, mrb_intern_cstr(mrb, "@frconfig"), inst->mrubyconf_hash);
445 mruby_set_vps(request, mrb, mruby_request, "@request", &request->request_pairs);
446 mruby_set_vps(request, mrb, mruby_request, "@reply", &request->reply_pairs);
447 mruby_set_vps(request, mrb, mruby_request, "@control", &request->control_pairs);
448 mruby_set_vps(request, mrb, mruby_request, "@session_state", &request->session_state_pairs);
449
451DIAG_OFF(class-varargs)
452 mruby_result = mrb_funcall(mrb, mrb_obj_value(inst->mruby_module), func->func->function_name, 1, mruby_request);
453DIAG_ON(class-varargs)
455
456 /* Two options for the return value:
457 * - a fixnum: convert to rlm_rcode_t, and return that
458 * - an array: this should have exactly three items in it. The first one
459 * should be a fixnum, this will once again be converted to
460 * rlm_rcode_t and eventually returned. The other two items
461 * should be arrays. The items of the first array should be
462 * merged into reply, the second array into control.
463 */
464 switch (mrb_type(mruby_result)) {
465 /* If it is a Fixnum: return that value */
466 case MRB_TT_FIXNUM:
467 RETURN_MODULE_RCODE((rlm_rcode_t)mrb_int(mrb, mruby_result));
468
469 case MRB_TT_ARRAY:
470 /* Must have exactly three items */
471 if (RARRAY_LEN(mruby_result) != 3) {
472 ERROR("Expected array to have exactly three values, got %" PRId64 " instead", RARRAY_LEN(mruby_result));
474 }
475
476 /* First item must be a Fixnum, this will be the return type */
477 if (mrb_type(mrb_ary_entry(mruby_result, 0)) != MRB_TT_FIXNUM) {
478 ERROR("Expected first array element to be a Fixnum, got %s instead", RSTRING_PTR(mrb_obj_as_string(mrb, mrb_ary_entry(mruby_result, 0))));
480 }
481
482 /* Second and third items must be Arrays, these will be the updates for reply and control */
483 if (mrb_type(mrb_ary_entry(mruby_result, 1)) != MRB_TT_ARRAY) {
484 ERROR("Expected second array element to be an Array, got %s instead", RSTRING_PTR(mrb_obj_as_string(mrb, mrb_ary_entry(mruby_result, 1))));
486 } else if (mrb_type(mrb_ary_entry(mruby_result, 2)) != MRB_TT_ARRAY) {
487 ERROR("Expected third array element to be an Array, got %s instead", RSTRING_PTR(mrb_obj_as_string(mrb, mrb_ary_entry(mruby_result, 2))));
489 }
490
491 add_vp_tuple(request->reply_ctx, request, &request->reply_pairs, mrb, mrb_ary_entry(mruby_result, 1), func->func->function_name);
492 add_vp_tuple(request->control_ctx, request, &request->control_pairs, mrb, mrb_ary_entry(mruby_result, 2), func->func->function_name);
493 RETURN_MODULE_RCODE((rlm_rcode_t)mrb_int(mrb, mrb_ary_entry(mruby_result, 0)));
494
495 default:
496 /* Invalid return type */
497 ERROR("Expected return to be a Fixnum or an Array, got %s instead", RSTRING_PTR(mrb_obj_as_string(mrb, mruby_result)));
499 }
500}
501
502/*
503 * Only free memory we allocated. The strings allocated via
504 * cf_section_parse() do not need to be freed.
505 */
506static int mod_detach(module_detach_ctx_t const *mctx)
507{
508 rlm_mruby_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_mruby_t);
509
510 mrb_close(inst->mrb);
511
512 return 0;
513}
514
515/*
516 * Restrict automatic Ruby function names to lowercase characters, numbers and underscore
517 * meaning that a module call in `recv Access-Request` will look for `recv_access_request`
518 */
519static void mruby_func_name_safe(char *name) {
520 char *p;
521 size_t i;
522
523 p = name;
524 for (i = 0; i < talloc_array_length(name); i++) {
525 *p = tolower(*p);
526 if (!strchr("abcdefghijklmnopqrstuvwxyz1234567890", *p)) *p = '_';
527 p++;
528 }
529}
530
531static int mruby_func_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, UNUSED tmpl_rules_t const *t_rules,
532 UNUSED CONF_ITEM *ci, call_env_ctx_t const *cec, UNUSED call_env_parser_t const *rule)
533{
534 rlm_mruby_t *inst = talloc_get_type_abort(cec->mi->data, rlm_mruby_t);
535 call_env_parsed_t *parsed;
536 mruby_func_def_t *func;
537 void *found;
538
539 if (!inst->funcs_init) {
541 inst->funcs_init = true;
542 }
543
544 MEM(parsed = call_env_parsed_add(ctx, out,
546 .name = "func",
548 .pair = {
549 .parsed = {
550 .offset = rule->pair.offset,
552 }
553 }
554 }));
555
556 MEM(func = talloc_zero(inst, mruby_func_def_t));
557 func->name1 = talloc_strdup(func, cec->asked->name1);
559 if (cec->asked->name2) {
560 func->name2 = talloc_strdup(func, cec->asked->name2);
562 }
563 if (fr_rb_find_or_insert(&found, &inst->funcs, func) < 0) {
564 talloc_free(func);
565 return -1;
566 }
567
568 /*
569 * If the function call is already in the tree, use that entry.
570 */
571 if (found) {
572 talloc_free(func);
573 call_env_parsed_set_data(parsed, found);
574 } else {
575 call_env_parsed_set_data(parsed, func);
576 }
577 return 0;
578}
579
587
588/*
589 * The module name should be the only globally exported symbol.
590 * That is, everything else should be 'static'.
591 *
592 * If the module needs to temporarily modify it's instantiation
593 * data, the type should be changed to MODULE_TYPE_THREAD_UNSAFE.
594 * The server will then take care of ensuring that the module
595 * is single-threaded.
596 */
599 .common = {
600 .magic = MODULE_MAGIC_INIT,
601 .name = "mruby",
602 .flags = MODULE_TYPE_THREAD_UNSAFE, /* Not sure */
603 .inst_size = sizeof(rlm_mruby_t),
606 .detach = mod_detach,
607 },
608 .method_group = {
609 .bindings = (module_method_binding_t[]){
610 { .section = SECTION_NAME(CF_IDENT_ANY, CF_IDENT_ANY), .method = mod_mruby, .method_env = &mruby_method_env },
612 }
613 }
614};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
log_entry msg
Definition acutest.h:794
#define RCSID(id)
Definition build.h:485
#define DIAG_UNKNOWN_PRAGMAS
Definition build.h:458
#define DIAG_ON(_x)
Definition build.h:460
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition build.h:112
#define UNUSED
Definition build.h:317
#define DIAG_OFF(_x)
Definition build.h:459
call_env_parsed_t * call_env_parsed_add(TALLOC_CTX *ctx, call_env_parsed_head_t *head, call_env_parser_t const *rule)
Allocate a new call_env_parsed_t structure and add it to the list of parsed call envs.
Definition call_env.c:644
void call_env_parsed_set_data(call_env_parsed_t *parsed, void const *data)
Assign data to a call_env_parsed_t.
Definition call_env.c:701
#define CALL_ENV_TERMINATOR
Definition call_env.h:236
#define FR_CALL_ENV_METHOD_OUT(_inst)
Helper macro for populating the size/type fields of a call_env_method_t from the output structure typ...
Definition call_env.h:240
call_env_parser_t const * env
Parsing rules for call method env.
Definition call_env.h:247
section_name_t const * asked
The actual name1/name2 that resolved to a module_method_binding_t.
Definition call_env.h:232
@ CALL_ENV_FLAG_PARSE_ONLY
The result of parsing will not be evaluated at runtime.
Definition call_env.h:85
@ CALL_ENV_FLAG_PARSE_MISSING
If this subsection is missing, still parse it.
Definition call_env.h:88
@ CALL_ENV_PARSE_TYPE_VOID
Output of the parsing phase is undefined (a custom structure).
Definition call_env.h:62
module_instance_t const * mi
Module instance that the callenv is registered to.
Definition call_env.h:229
#define FR_CALL_ENV_SUBSECTION_FUNC(_name, _name2, _flags, _func)
Specify a call_env_parser_t which parses a subsection using a callback function.
Definition call_env.h:412
Per method call config.
Definition call_env.h:180
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:658
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:284
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:272
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:434
@ CONF_FLAG_FILE_INPUT
File matching value must exist, and must be readable.
Definition cf_parse.h:440
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:595
Common header for all CONF_* types.
Definition cf_priv.h:49
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:70
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
Definition cf_util.c:631
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1170
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition cf_util.c:1027
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition cf_util.c:683
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
Definition cf_util.c:617
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:663
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1593
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
Definition cf_util.c:1577
#define cf_item_next(_parent, _curr)
Definition cf_util.h:92
#define CF_IDENT_ANY
Definition cf_util.h:78
#define MEM(x)
Definition debug.h:36
#define ERROR(fmt,...)
Definition dhcpclient.c:41
#define DEBUG(fmt,...)
Definition dhcpclient.c:39
static fr_slen_t in
Definition dict.h:833
Test enumeration values.
Definition dict_test.h:92
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
talloc_free(reap)
fr_log_t default_log
Definition log.c:288
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_DBG_WARN_REQ
Less severe warning only displayed when debugging is enabled.
Definition log.h:63
@ L_WARN
Warning.
Definition log.h:57
@ L_ERR
Error message.
Definition log.h:56
@ L_DBG_ERR
Error only displayed when debugging is enabled.
Definition log.h:62
@ L_DBG_ERR_REQ
Less severe error only displayed when debugging is enabled.
Definition log.h:64
@ L_DBG_WARN
Warning only displayed when debugging is enabled.
Definition log.h:61
@ L_INFO
Informational message.
Definition log.h:55
@ L_DBG
Only displayed when debugging is enabled.
Definition log.h:59
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_FLOAT32
Single precision floating point.
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_INT8
8 Bit signed integer.
@ FR_TYPE_ETHERNET
48 Bit Mac-Address.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_INT64
64 Bit signed integer.
@ FR_TYPE_INT16
16 Bit signed integer.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_COMBO_IP_PREFIX
IPv4 or IPv6 address prefix depending on length.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_INT32
32 Bit signed integer.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
@ FR_TYPE_IFID
Interface ID.
@ FR_TYPE_OCTETS
Raw octets.
@ FR_TYPE_FLOAT64
Double precision floating point.
void * env_data
Per call environment data.
Definition module_ctx.h:44
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:42
module_instance_t * mi
Module instance to detach.
Definition module_ctx.h:57
module_instance_t * mi
Instance of the module being instantiated.
Definition module_ctx.h:51
Temporary structure to hold arguments for module calls.
Definition module_ctx.h:41
Temporary structure to hold arguments for detach calls.
Definition module_ctx.h:56
Temporary structure to hold arguments for instantiation calls.
Definition module_ctx.h:50
module_t common
Common fields presented by all modules.
Definition module_rlm.h:39
struct RClass * mruby_request_class(mrb_state *mrb, struct RClass *parent)
Definition mruby.c:73
int fr_pair_value_from_str(fr_pair_t *vp, char const *value, size_t inlen, fr_sbuff_unescape_rules_t const *uerules, UNUSED bool tainted)
Convert string value to native attribute value.
Definition pair.c:2591
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
Definition pair.c:1347
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
Definition pair.c:285
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:46
void radius_pairmove(request_t *request, fr_pair_list_t *to, fr_pair_list_t *from)
Definition pairmove.c:44
static const conf_parser_t config[]
Definition base.c:183
#define fr_assert(_expr)
Definition rad_assert.h:38
#define REDEBUG(fmt,...)
Definition radclient.h:52
#define WARN(fmt,...)
Definition radclient.h:47
int fr_rb_find_or_insert(void **found, fr_rb_tree_t *tree, void const *data)
Attempt to find current data in the tree, if it does not exist insert it.
Definition rb.c:598
#define fr_rb_inline_init(_tree, _type, _field, _data_cmp, _data_free)
Initialises a red black tree.
Definition rb.h:180
The main red black tree structure.
Definition rb.h:73
#define RETURN_MODULE_RCODE(_rcode)
Definition rcode.h:64
#define RETURN_MODULE_FAIL
Definition rcode.h:56
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
@ RLM_MODULE_INVALID
The module considers the request invalid.
Definition rcode.h:45
@ RLM_MODULE_OK
The module is OK, continue.
Definition rcode.h:43
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition rcode.h:42
@ RLM_MODULE_DISALLOW
Reject the request (user is locked out).
Definition rcode.h:46
@ RLM_MODULE_REJECT
Immediately reject the request.
Definition rcode.h:41
@ RLM_MODULE_NOTFOUND
User not found.
Definition rcode.h:47
@ RLM_MODULE_UPDATED
OK (pairs modified).
Definition rcode.h:49
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition rcode.h:48
@ RLM_MODULE_NUMCODES
How many valid return codes there are.
Definition rcode.h:50
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
Definition rcode.h:44
fr_dict_attr_t const * request_attr_reply
Definition request.c:44
static int mod_detach(module_detach_ctx_t const *mctx)
Definition rlm_mruby.c:506
mrb_value mrubyconf_hash
Definition rlm_mruby.c:63
mruby_func_def_t * func
Definition rlm_mruby.c:42
char const * filename
Definition rlm_mruby.c:53
mrb_state * mrb
Definition rlm_mruby.c:59
char * name1
Section name1 where this is called.
Definition rlm_mruby.c:36
static int mruby_vps_to_array(request_t *request, mrb_value *out, mrb_state *mrb, fr_pair_list_t *vps)
Definition rlm_mruby.c:243
#define A(x)
static unlang_action_t mod_mruby(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition rlm_mruby.c:436
char const * module_name
Definition rlm_mruby.c:54
struct RClass * mruby_request
Definition rlm_mruby.c:62
static void mruby_func_name_safe(char *name)
Definition rlm_mruby.c:519
static int8_t mruby_func_def_cmp(void const *one, void const *two)
How to compare two Ruby function calls.
Definition rlm_mruby.c:78
struct RClass * mruby_module
Definition rlm_mruby.c:61
fr_rb_tree_t funcs
Tree of function calls found by call_env parser.
Definition rlm_mruby.c:56
char const * function_name
Name of the function being called.
Definition rlm_mruby.c:35
bool funcs_init
Has the tree been initialised.
Definition rlm_mruby.c:57
char * name2
Section name2 where this is called.
Definition rlm_mruby.c:37
static const call_env_method_t mruby_method_env
Definition rlm_mruby.c:580
static mrb_value mruby_log(mrb_state *mrb, UNUSED mrb_value self)
Definition rlm_mruby.c:91
fr_rb_node_t node
Node in tree of function calls.
Definition rlm_mruby.c:38
static void add_vp_tuple(TALLOC_CTX *ctx, request_t *request, fr_pair_list_t *vps, mrb_state *mrb, mrb_value value, char const *function_name)
Definition rlm_mruby.c:336
static int mruby_func_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, UNUSED tmpl_rules_t const *t_rules, UNUSED CONF_ITEM *ci, call_env_ctx_t const *cec, UNUSED call_env_parser_t const *rule)
Definition rlm_mruby.c:531
static void mruby_parse_config(mrb_state *mrb, CONF_SECTION *cs, int lvl, mrb_value hash)
Definition rlm_mruby.c:102
module_rlm_t rlm_mruby
Definition rlm_mruby.c:598
static const conf_parser_t module_config[]
Definition rlm_mruby.c:69
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition rlm_mruby.c:162
static int mruby_set_vps(request_t *request, mrb_state *mrb, mrb_value mruby_request, char const *list_name, fr_pair_list_t *vps)
Definition rlm_mruby.c:422
Translates requests between the server an an mruby interpreter.
static unsigned int hash(char const *username, unsigned int tablesize)
Definition rlm_passwd.c:132
static char const * name
static int instantiate(module_inst_ctx_t const *mctx)
Definition rlm_rest.c:1313
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
Definition section.h:40
char const * name2
Second section name. Usually a packet type like 'access-request', 'access-accept',...
Definition section.h:46
char const * name1
First section name. Usually a verb like 'recv', 'send', etc...
Definition section.h:45
@ MODULE_TYPE_THREAD_UNSAFE
Module is not threadsafe.
Definition module.h:48
module_flags_t flags
Flags that control how a module starts up and how a module is called.
Definition module.h:228
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:330
void * data
Module's instance data.
Definition module.h:272
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Definition module.h:151
Named methods exported by a module.
Definition module.h:173
ssize_t tmpl_afrom_attr_str(TALLOC_CTX *ctx, tmpl_attr_error_t *err, tmpl_t **out, char const *name, tmpl_rules_t const *rules))
Parse a string into a TMPL_TYPE_ATTR_* type tmpl_t.
int tmpl_request_ptr(request_t **request, FR_DLIST_HEAD(tmpl_request_list) const *rql)
Resolve a tmpl_request_ref_t to a request_t.
Definition tmpl_eval.c:163
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
Definition tmpl.h:801
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:332
eap_aka_sim_process_conf_t * inst
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition pair.h:69
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
Definition table.h:653
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:772
fr_table_num_ordered_t const fr_tokens_table[]
Definition token.c:32
enum fr_token fr_token_t
@ T_OP_EQ
Definition token.h:83
fr_pair_t * fr_pair_list_next(fr_pair_list_t const *list, fr_pair_t const *item))
Get the next item in a valuepair list after a specific entry.
Definition pair_inline.c:69
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
Definition pair_inline.c:42
#define FR_TYPE_NON_LEAF
Definition types.h:298
static fr_slen_t fr_value_box_aprint(TALLOC_CTX *ctx, char **out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules) 1(fr_value_box_print
int nonnull(2, 5))
static size_t char ** out
Definition value.h:1012