The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
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: 80c39121fda98495a0d6d48878439252a6566598 $
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 */
25
26#include "rlm_mruby.h"
27
30 rlm_mruby_t const *inst; //!< Module instance. Needed for access to classes
31 request_t *request; //!< Current request
32 fr_dict_attr_t const *da; //!< Dictionary attribute for this pair.
33 fr_pair_t *vp; //!< Real pair if it exists.
34 unsigned int idx; //!< Instance index.
35 mruby_pair_t *parent; //!< Parent pair.
36};
37
38static mrb_value mruby_request_frconfig(mrb_state *mrb, mrb_value self)
39{
40 return mrb_iv_get(mrb, self, mrb_intern_cstr(mrb, "@frconfig"));
41}
42
43static mrb_value mruby_request_request(mrb_state *mrb, mrb_value self)
44{
45 return mrb_iv_get(mrb, self, mrb_intern_cstr(mrb, "@request"));
46}
47
48static mrb_value mruby_request_reply(mrb_state *mrb, mrb_value self)
49{
50 return mrb_iv_get(mrb, self, mrb_intern_cstr(mrb, "@reply"));
51}
52
53static mrb_value mruby_request_control(mrb_state *mrb, mrb_value self)
54{
55 return mrb_iv_get(mrb, self, mrb_intern_cstr(mrb, "@control"));
56}
57
58static mrb_value mruby_request_session_state(mrb_state *mrb, mrb_value self)
59{
60 return mrb_iv_get(mrb, self, mrb_intern_cstr(mrb, "@session_state"));
61}
62
63struct RClass *mruby_request_class(mrb_state *mrb, struct RClass *parent)
64{
65 struct RClass *request;
66
67 request = mrb_define_class_under(mrb, parent, "Request", mrb->object_class);
68
69 mrb_define_method(mrb, request, "frconfig", mruby_request_frconfig, MRB_ARGS_NONE());
70 mrb_define_method(mrb, request, "request", mruby_request_request, MRB_ARGS_NONE());
71 mrb_define_method(mrb, request, "reply", mruby_request_reply, MRB_ARGS_NONE());
72 mrb_define_method(mrb, request, "control", mruby_request_control, MRB_ARGS_NONE());
73 mrb_define_method(mrb, request, "session_state", mruby_request_session_state, MRB_ARGS_NONE());
74
75 return request;
76}
77
78/*
79 * Structures used to identify C data types in mruby pointers
80 */
81static const struct mrb_data_type mruby_inst_type = {
82 .struct_name = "Inst",
83 .dfree = NULL
84};
85
86static const struct mrb_data_type mruby_request_type = {
87 .struct_name = "Request",
88 .dfree = NULL
89};
90
91static const struct mrb_data_type mruby_dict_attr_type = {
92 .struct_name = "DictAttr",
93 .dfree = NULL
94};
95
96static const struct mrb_data_type mruby_value_pair_type = {
97 .struct_name = "ValuePair",
98 .dfree = NULL
99};
100
101static const struct mrb_data_type mruby_ruby_pair_type = {
102 .struct_name = "RubyPair",
103 .dfree = NULL
104};
105
106/*
107 * Helper functions to return C data type pointers as mruby values
108 */
109mrb_value mruby_inst_object(mrb_state *mrb, struct RClass *klass, rlm_mruby_t const *inst)
110{
111 return mrb_obj_value(Data_Wrap_Struct(mrb, klass, &mruby_inst_type, UNCONST(void *, inst)));
112}
113
114mrb_value mruby_request_object(mrb_state *mrb, struct RClass *klass, request_t *request)
115{
116 return mrb_obj_value(Data_Wrap_Struct(mrb, klass, &mruby_request_type, (void *)request));
117}
118
119mrb_value mruby_dict_attr_object(mrb_state *mrb, struct RClass *klass, fr_dict_attr_t const *da)
120{
121 return mrb_obj_value(Data_Wrap_Struct(mrb, klass, &mruby_dict_attr_type, UNCONST(void *,da)));
122}
123
124mrb_value mruby_value_pair_object(mrb_state *mrb, struct RClass *klass, fr_pair_t *vp)
125{
126 return mrb_obj_value(Data_Wrap_Struct(mrb, klass, &mruby_value_pair_type, (void *)vp));
127}
128
129static mrb_value mruby_ruby_pair_object(mrb_state *mrb, struct RClass *klass, mruby_pair_t *pair)
130{
131 return mrb_obj_value(Data_Wrap_Struct(mrb, klass, &mruby_ruby_pair_type, (void *)pair));
132}
133
134/** Associate C structure with Ruby object representing a pair
135 *
136 * Will be called with 5 or 6 arguments
137 * - a pointer to the module instance
138 * - a pointer to the request
139 * - a pointer to the dictionary attribute for the pair
140 * - the instance number of the pair
141 * - a pointer to the real pair (if it exists)
142 * - (optional) the parent pair C structure
143 */
144static mrb_value mruby_pair_init(mrb_state *mrb, mrb_value self)
145{
146 mruby_pair_t *pair, *parent = NULL;
147 rlm_mruby_t const *inst;
148 request_t *request;
149 fr_dict_attr_t const *da;
150 mrb_int idx;
151 fr_pair_t *vp;
152
153 mrb_get_args(mrb, "dddid|d",
155 &request, &mruby_request_type,
157 &idx,
160
161 /*
162 * Apparently `initialize` can be called more than once in some
163 * scenarios, so it is best practice to clear up any old data first
164 */
165 pair = (mruby_pair_t *)DATA_PTR(self);
166 if (pair) talloc_free(pair);
167
168 /*
169 * The C data is talloced off frame ctx so we free correctly.
170 */
171 pair = talloc(unlang_interpret_frame_talloc_ctx(request), mruby_pair_t);
172 mrb_data_init(self, pair, &mruby_value_pair_type);
173
174 *pair = (mruby_pair_t) {
175 .inst = inst,
176 .request = request,
177 .da = da,
178 .idx = idx,
179 .vp = vp,
180 .parent = parent
181 };
182
183 return self;
184}
185
186/** Fetch the list of children of a list
187 *
188 */
189static mrb_value mruby_pair_list_keys(mrb_state *mrb, mrb_value self)
190{
191 mruby_pair_t *pair;
192 mrb_value keys, key;
193 fr_pair_t *vp = NULL;
194
195 pair = (mruby_pair_t *)DATA_PTR(self);
196 if (!pair) mrb_raise(mrb, E_RUNTIME_ERROR, "Failed to retrieve C data");
197
198 keys = mrb_ary_new(mrb);
199 for (vp = fr_pair_list_head(&pair->vp->vp_group); vp; vp = fr_pair_list_next(&pair->vp->vp_group, vp)) {
200 key = mrb_str_new(mrb, vp->da->name, strlen(vp->da->name));
201 mrb_ary_push(mrb, keys, key);
202 }
203 return keys;
204}
205
206/** Convert a pair value to a suitable mruby value type
207 *
208 */
209static mrb_value mruby_pair_value_to_ruby(mrb_state *mrb, request_t *request, fr_pair_t *vp)
210{
211 switch(vp->vp_type){
212 case FR_TYPE_STRING:
213 case FR_TYPE_OCTETS:
214 return mrb_str_new(mrb, vp->vp_ptr, vp->vp_length);
215
216 case FR_TYPE_BOOL:
217 return vp->vp_bool ? mrb_obj_value(mrb->true_class) : mrb_obj_value(mrb->false_class);
218
219 case FR_TYPE_UINT8:
220 return mrb_int_value(mrb, vp->vp_uint8);
221 case FR_TYPE_UINT16:
222 return mrb_int_value(mrb, vp->vp_uint16);
223 case FR_TYPE_UINT32:
224 return mrb_int_value(mrb, vp->vp_uint32);
225 case FR_TYPE_UINT64:
226 return mrb_int_value(mrb, vp->vp_uint64);
227 case FR_TYPE_INT8:
228 return mrb_int_value(mrb, vp->vp_int8);
229 case FR_TYPE_INT16:
230 return mrb_int_value(mrb, vp->vp_int16);
231 case FR_TYPE_INT32:
232 return mrb_int_value(mrb, vp->vp_int32);
233 case FR_TYPE_INT64:
234 return mrb_int_value(mrb, vp->vp_int64);
235 case FR_TYPE_SIZE:
236 return mrb_int_value(mrb, vp->vp_size);
237
238 case FR_TYPE_FLOAT32:
239 return mrb_float_value(mrb, vp->vp_float32);
240 case FR_TYPE_FLOAT64:
241 return mrb_float_value(mrb, vp->vp_float64);
242
243 case FR_TYPE_ETHERNET:
250 case FR_TYPE_IFID:
252 case FR_TYPE_DATE:
253 {
254 char *in;
255 size_t len;
256 mrb_value value;
257
258 len = fr_value_box_aprint(request, &in, &vp->data, NULL);
259 value = mrb_str_new(mrb, in, len);
261 return value;
262 }
263
264 default:
265 fr_assert(0);
266 break;
267 }
268 return mrb_nil_value();
269}
270
271/** Get a pair value from mruby
272 *
273 * The mruby method can take an optional argument to specify the instance number
274 */
275static mrb_value mruby_value_pair_get(mrb_state *mrb, mrb_value self)
276{
277 mruby_pair_t *pair;
278 request_t *request;
279 mrb_int idx = 0;
280 fr_pair_t *vp = NULL;
281
282 pair = (mruby_pair_t *)DATA_PTR(self);
283 if (!pair) mrb_raise(mrb, E_RUNTIME_ERROR, "Failed to retrieve C data");
284 request = pair->request;
285
286 if (mrb_get_argc(mrb) > 0) {
287 if (mrb_get_args(mrb, "|i", &idx) < 1) mrb_raise(mrb, E_ARGUMENT_ERROR, "Invalid argument");
288 }
289
290 if (idx == pair->idx) vp = pair->vp;
291 if (!vp && pair->parent && pair->parent->vp) vp = fr_pair_find_by_da_idx(&pair->parent->vp->vp_group, pair->da, idx);
292
293 if (!vp) return mrb_nil_value();
294
295 return mruby_pair_value_to_ruby(mrb, request, vp);
296}
297
298/** Build parent structural pairs needed when a leaf node is set
299 *
300 */
301static void mruby_pair_parent_build(mrb_state *mrb, mruby_pair_t *pair)
302{
303 mruby_pair_t *parent = pair->parent;
304 if (!parent->vp) mruby_pair_parent_build(mrb, parent);
305
306 if (pair->idx > 0) {
307 unsigned int count = fr_pair_count_by_da(&parent->vp->vp_group, pair->da);
308 if (count < pair->idx) mrb_raisef(mrb, E_ARGUMENT_ERROR,
309 "Attempt to set instance %d when only %d exist", pair->idx, count);
310 }
311
312 if (fr_pair_append_by_da(parent->vp, &pair->vp, &parent->vp->vp_group, pair->da) < 0) {
313 mrb_raisef(mrb, E_RUNTIME_ERROR, "Failed adding %s", pair->da->name);
314 }
315}
316
317/** Convert a ruby value to a fr_pair_t value
318 *
319 */
320static void mruby_roby_to_pair_value(mrb_state *mrb, mrb_value *value, fr_pair_t *vp)
321{
322 switch (vp->vp_type) {
323 case FR_TYPE_STRING:
324 *value = mrb_obj_as_string(mrb, *value);
326 fr_pair_value_bstrndup(vp, RSTRING_PTR(*value), RSTRING_LEN(*value), true);
327 break;
328
329 case FR_TYPE_OCTETS:
330 *value = mrb_obj_as_string(mrb, *value);
332 fr_pair_value_memdup(vp, (uint8_t *)RSTRING_PTR(*value), RSTRING_LEN(*value), true);
333 break;
334
335#define RUBYSETINT(_size) case FR_TYPE_INT ## _size: \
336 if (mrb_type(*value) != MRB_TT_INTEGER) mrb_raise(mrb, E_ARGUMENT_ERROR, "Integer value required"); \
337 vp->vp_int ## _size = mrb_integer(*value); \
338 break;
339 RUBYSETINT(8)
340 RUBYSETINT(16)
341 RUBYSETINT(32)
342 RUBYSETINT(64)
343
344#define RUBYSETUINT(_size) case FR_TYPE_UINT ## _size: \
345 if (mrb_type(*value) != MRB_TT_INTEGER) mrb_raise(mrb, E_ARGUMENT_ERROR, "Integer value required"); \
346 vp->vp_uint ## _size = mrb_integer(*value); \
347 break;
348 RUBYSETUINT(8)
349 RUBYSETUINT(16)
350 RUBYSETUINT(32)
351 RUBYSETUINT(64)
352
353#define RUBYSETFLOAT(_size) case FR_TYPE_FLOAT ## _size: \
354 switch (mrb_type(*value)) { \
355 case MRB_TT_FLOAT: \
356 vp->vp_float ## _size = mrb_float(*value); \
357 break; \
358 case MRB_TT_INTEGER: \
359 vp->vp_float ## _size = mrb_integer(*value); \
360 break; \
361 default: \
362 mrb_raise(mrb, E_ARGUMENT_ERROR, "Float or integer value required"); \
363 } \
364 break;
365 RUBYSETFLOAT(32)
366 RUBYSETFLOAT(64)
367
368 case FR_TYPE_ETHERNET:
375 case FR_TYPE_IFID:
377 case FR_TYPE_DATE:
378 *value = mrb_obj_as_string(mrb, *value);
379 if (fr_pair_value_from_str(vp, RSTRING_PTR(*value), RSTRING_LEN(*value), NULL, false) < 0) {
380 mrb_raise(mrb, E_RUNTIME_ERROR, "Failed populating pair");
381 }
382 break;
383
384 default:
385 fr_assert(0);
386 break;
387 }
388}
389
390/** Set a value pair from mruby
391 *
392 * The ruby method expects one or two arguments
393 * - the value to assign to the pair
394 * - (optional) instance number
395 */
396static mrb_value mruby_value_pair_set(mrb_state *mrb, mrb_value self)
397{
398 mruby_pair_t *pair;
399 mrb_value value;
400 mrb_int idx = 0;
401 fr_pair_t *vp = NULL;
402 request_t *request;
403
404 pair = (mruby_pair_t *)DATA_PTR(self);
405 if (!pair) mrb_raise(mrb, E_RUNTIME_ERROR, "Failed to retrieve C data");
406
407 request = pair->request;
408 /*
409 * We use "o" (object) for the first argument type so we can
410 * accept strings and numbers, according to the pair type.
411 */
412 mrb_get_args(mrb, "o|i", &value, &idx);
413
414 if (!pair->parent->vp) mruby_pair_parent_build(mrb, pair->parent);
415
416 if (idx == pair->idx) vp = pair->vp;
417 if (!vp) vp = fr_pair_find_by_da_idx(&pair->parent->vp->vp_group, pair->da, idx);
418 if (!vp) {
419 if (idx > 0) {
420 unsigned int count = fr_pair_count_by_da(&pair->parent->vp->vp_group, pair->da);
421 if (count < idx) mrb_raisef(mrb, E_ARGUMENT_ERROR,
422 "Attempt to set instance %d when only %d exist", idx, count);
423 }
424
425 if (fr_pair_append_by_da(pair->parent->vp, &vp, &pair->parent->vp->vp_group, pair->da) < 0) {
426 mrb_raisef(mrb, E_RUNTIME_ERROR, "Failed adding %s", pair->da->name);
427 }
428 }
429
431
432 RDEBUG2("%pP", vp);
433 return mrb_nil_value();
434}
435
436/** Append an instance of a value pair from mruby
437 *
438 * The ruby method expects one argument - the value to assign to the pair
439 */
440static mrb_value mruby_value_pair_append(mrb_state *mrb, mrb_value self)
441{
442 mruby_pair_t *pair;
443 mrb_value value;
444 fr_pair_t *vp = NULL;
445 request_t *request;
446
447 pair = (mruby_pair_t *)DATA_PTR(self);
448 if (!pair) mrb_raise(mrb, E_RUNTIME_ERROR, "Failed to retrieve C data");
449
450 request = pair->request;
451
452 mrb_get_args(mrb, "o", &value);
453
454 if (!pair->parent->vp) mruby_pair_parent_build(mrb, pair->parent);
455
456 if (fr_pair_append_by_da(pair->parent->vp, &vp, &pair->parent->vp->vp_group, pair->da) < 0) {
457 mrb_raisef(mrb, E_RUNTIME_ERROR, "Failed adding %s", pair->da->name);
458 }
459
461
462 RDEBUG2("%pP", vp);
463 return mrb_nil_value();
464}
465
466/** Delete a value pair from mruby
467 *
468 * The ruby method expects an optional argument - the instance number
469 */
470static mrb_value mruby_value_pair_del(mrb_state *mrb, mrb_value self)
471{
472 mruby_pair_t *pair;
473 mrb_int idx = 0;
474 fr_pair_t *vp = NULL;
475
476 pair = (mruby_pair_t *)DATA_PTR(self);
477 if (!pair) mrb_raise(mrb, E_RUNTIME_ERROR, "Failed to retrieve C data");
478
479 mrb_get_args(mrb, "|i", &idx);
480
481 if (!pair->parent->vp) return mrb_nil_value();
482
483 if (idx == pair->idx) vp = pair->vp;
484 if (!vp) vp = fr_pair_find_by_da_idx(&pair->parent->vp->vp_group, pair->da, idx);
485 if (!vp) return mrb_nil_value();
486
487 fr_pair_delete(&pair->parent->vp->vp_group, vp);
488 if (idx == pair->idx) pair->vp = NULL;
489 return mrb_nil_value();
490}
491
492/** Implement mruby method_missing functionality to find child pairs
493 *
494 */
495static mrb_value mruby_pair_list_missing(mrb_state *mrb, mrb_value self)
496{
497 mruby_pair_t *pair;
498 request_t *request;
499 mrb_sym attr;
500 mrb_value *args = NULL, mruby_pair, pair_args[6], argv;
501 mrb_int argc = 0, len;
502 int i;
503 size_t idx = 0, child_idx = 0;
504 char *attr_name, *child_attr_name = NULL;
505 fr_dict_attr_t const *da, *child_da;
506 fr_pair_t *vp = NULL;
507
508 pair = (mruby_pair_t *)DATA_PTR(self);
509 if (!pair) mrb_raise(mrb, E_RUNTIME_ERROR, "Failed to retrieve C data");
510 request = pair->request;
511
512 if (fr_type_is_leaf(pair->da->type)) mrb_raisef(mrb, E_RUNTIME_ERROR, "%s is a leaf attribute so has no children",
513 pair->da->name);
514 mrb_get_args(mrb, "n|*!", &attr, &args, &argc);
515
516 if (argc > 3) mrb_raise(mrb, E_ARGUMENT_ERROR, "Maximum three arguments allowed");
517
518 /*
519 * Parse any provided arguments. We allow
520 * * int - instance of attribute
521 * * str - child attribute name
522 * * int, str - instance of parent and child attribute name
523 * * str, int - child attribute and its instance
524 * * int, str, int - instance of parent, child attribute name and instance
525 *
526 * This is to allow for attribute names which begin with a number (e.g. 3GPP2 VSA) which is not
527 * allowed in mruby method names.
528 *
529 * p.request.vendor_specific("3gpp2") gets the pair request.Vendor-Specific.3GPP2
530 */
531 for (i = 0; i < argc; i++) {
532 argv = args[i];
533 switch (mrb_type(argv)) {
534 case MRB_TT_INTEGER:
535 if (i == 0) {
536 idx = mrb_integer(argv);
537 } else {
538 if (!child_attr_name) mrb_raise(mrb, E_ARGUMENT_ERROR, "Child attribute instance must follow attribute name");
539 child_idx = mrb_integer(argv);
540 }
541 break;
542
543 case MRB_TT_STRING:
544 if (child_attr_name) mrb_raise(mrb, E_ARGUMENT_ERROR, "Only one child attribute name allowed");
545 child_attr_name = mrb_str_to_cstr(mrb, argv);
546 break;
547
548 default:
549 mrb_raise(mrb, E_ARGUMENT_ERROR, "Arguments can only be integer (attribute instance), or string (attribute name)");
550 }
551 }
552
553 attr_name = talloc_strdup(request, mrb_sym_name_len(mrb, attr, &len));
554 for (i = 0; i < len; i++) {
555 if (attr_name[i] == '_') attr_name[i] = '-';
556 }
557
558 da = fr_dict_attr_by_name(NULL, pair->da, attr_name);
559
560 /*
561 * Allow fallback to internal attributes if the parent is a group or dictionary root.
562 */
563 if (!da && (fr_type_is_group(pair->da->type) || pair->da->flags.is_root)) {
564 da = fr_dict_attr_by_name(NULL, fr_dict_root(fr_dict_internal()), attr_name);
565 }
566
567 if (!da) mrb_raisef(mrb, E_ARGUMENT_ERROR, "Unknown or invalid attriubte name \"%s\"", attr_name);
568
569 if (pair->vp) vp = fr_pair_find_by_da_idx(&pair->vp->vp_group, da, idx);
570
571 pair_args[0] = mruby_inst_object(mrb, pair->inst->mruby_ptr, pair->inst);
572 pair_args[1] = mruby_request_object(mrb, pair->inst->mruby_ptr, request);
573 pair_args[2] = mruby_dict_attr_object(mrb, pair->inst->mruby_ptr, da);
574 pair_args[3] = mrb_int_value(mrb, idx);
575 pair_args[4] = mruby_value_pair_object(mrb, pair->inst->mruby_ptr, vp);
576 pair_args[5] = mruby_ruby_pair_object(mrb, pair->inst->mruby_ptr, pair);
577
578 mruby_pair = mrb_obj_new(mrb, fr_type_is_leaf(da->type) ? pair->inst->mruby_pair : pair->inst->mruby_pair_list,
579 6, pair_args);
580
581 /*
582 * No child attr name in the arguments, so return the pair
583 */
584 if (!child_attr_name) return mruby_pair;
585
586 for (i = 0; i < (int)strlen(child_attr_name); i++) {
587 if (child_attr_name[i] == '_') child_attr_name[i] = '-';
588 }
589
590 child_da = fr_dict_attr_by_name(NULL, da, child_attr_name);
591
592 if (!child_da && fr_type_is_group(da->type)) {
593 child_da = fr_dict_attr_by_name(NULL, fr_dict_root(fr_dict_internal()), attr_name);
594 }
595
596 if (!child_da) mrb_raisef(mrb, E_ARGUMENT_ERROR, "Unknown or invalid attriubte name \"%s\"", attr_name);
597
598 if (vp) vp = fr_pair_find_by_da_idx(&vp->vp_group, child_da, child_idx);
599
600 pair = (mruby_pair_t *)DATA_PTR(mruby_pair);
601 pair_args[2] = mruby_dict_attr_object(mrb, pair->inst->mruby_ptr, child_da);
602 pair_args[3] = mrb_boxing_int_value(mrb, child_idx);
603 pair_args[4] = mruby_value_pair_object(mrb, pair->inst->mruby_ptr, vp);
604 pair_args[5] = mruby_ruby_pair_object(mrb, pair->inst->mruby_ptr, pair);
605
606 mruby_pair = mrb_obj_new(mrb, fr_type_is_leaf(da->type) ? pair->inst->mruby_pair : pair->inst->mruby_pair_list, 6, pair_args);
607
608 return mruby_pair;
609}
610
611struct RClass *mruby_pair_list_class(mrb_state *mrb, struct RClass *parent)
612{
613 struct RClass *pair_list;
614
615 pair_list = mrb_define_class_under(mrb, parent, "PairList", mrb->object_class);
616 MRB_SET_INSTANCE_TT(pair_list, MRB_TT_DATA);
617
618 mrb_define_method(mrb, pair_list, "initialize", mruby_pair_init, MRB_ARGS_ARG(5,1));
619 mrb_define_method(mrb, pair_list, "keys", mruby_pair_list_keys, MRB_ARGS_REQ(0));
620 mrb_define_method(mrb, pair_list, "method_missing", mruby_pair_list_missing, MRB_ARGS_OPT(1));
621
622 return pair_list;
623}
624
625struct RClass *mruby_pair_class(mrb_state *mrb, struct RClass *parent)
626{
627 struct RClass *pair;
628
629 pair = mrb_define_class_under(mrb, parent, "Pair", mrb->object_class);
630 MRB_SET_INSTANCE_TT(pair, MRB_TT_DATA);
631
632 mrb_define_method(mrb, pair, "initialize", mruby_pair_init, MRB_ARGS_ARG(5,1));
633 mrb_define_method(mrb, pair, "get", mruby_value_pair_get, MRB_ARGS_OPT(1));
634 mrb_define_method(mrb, pair, "set", mruby_value_pair_set, MRB_ARGS_ARG(1,1));
635 mrb_define_method(mrb, pair, "del", mruby_value_pair_del, MRB_ARGS_OPT(1));
636 mrb_define_method(mrb, pair, "append", mruby_value_pair_append, MRB_ARGS_REQ(1));
637
638 return pair;
639}
va_list args
Definition acutest.h:770
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:167
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *attr))
Locate a fr_dict_attr_t by its name.
Definition dict_util.c:3266
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2403
fr_dict_t const * fr_dict_internal(void)
Definition dict_util.c:4654
static fr_slen_t in
Definition dict.h:841
Test enumeration values.
Definition dict_test.h:92
TALLOC_CTX * unlang_interpret_frame_talloc_ctx(request_t *request)
Get a talloc_ctx which is valid only for this frame.
Definition interpret.c:1665
talloc_free(reap)
@ 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.
unsigned char uint8_t
struct RClass * mruby_request_class(mrb_state *mrb, struct RClass *parent)
Definition mruby.c:63
static mrb_value mruby_value_pair_append(mrb_state *mrb, mrb_value self)
Append an instance of a value pair from mruby.
Definition mruby.c:440
mrb_value mruby_request_object(mrb_state *mrb, struct RClass *klass, request_t *request)
Definition mruby.c:114
static const struct mrb_data_type mruby_value_pair_type
Definition mruby.c:96
static mrb_value mruby_value_pair_del(mrb_state *mrb, mrb_value self)
Delete a value pair from mruby.
Definition mruby.c:470
mruby_pair_t * parent
Parent pair.
Definition mruby.c:35
#define RUBYSETINT(_size)
static mrb_value mruby_pair_init(mrb_state *mrb, mrb_value self)
Associate C structure with Ruby object representing a pair.
Definition mruby.c:144
mrb_value mruby_value_pair_object(mrb_state *mrb, struct RClass *klass, fr_pair_t *vp)
Definition mruby.c:124
static const struct mrb_data_type mruby_ruby_pair_type
Definition mruby.c:101
static mrb_value mruby_request_reply(mrb_state *mrb, mrb_value self)
Definition mruby.c:48
rlm_mruby_t const * inst
Module instance. Needed for access to classes.
Definition mruby.c:30
static mrb_value mruby_value_pair_get(mrb_state *mrb, mrb_value self)
Get a pair value from mruby.
Definition mruby.c:275
unsigned int idx
Instance index.
Definition mruby.c:34
static mrb_value mruby_pair_list_keys(mrb_state *mrb, mrb_value self)
Fetch the list of children of a list.
Definition mruby.c:189
static const struct mrb_data_type mruby_dict_attr_type
Definition mruby.c:91
#define RUBYSETUINT(_size)
struct mruby_pair_s mruby_pair_t
Definition mruby.c:28
static const struct mrb_data_type mruby_inst_type
Definition mruby.c:81
static mrb_value mruby_pair_value_to_ruby(mrb_state *mrb, request_t *request, fr_pair_t *vp)
Convert a pair value to a suitable mruby value type.
Definition mruby.c:209
mrb_value mruby_dict_attr_object(mrb_state *mrb, struct RClass *klass, fr_dict_attr_t const *da)
Definition mruby.c:119
static mrb_value mruby_request_control(mrb_state *mrb, mrb_value self)
Definition mruby.c:53
struct RClass * mruby_pair_list_class(mrb_state *mrb, struct RClass *parent)
Definition mruby.c:611
request_t * request
Current request.
Definition mruby.c:31
static mrb_value mruby_value_pair_set(mrb_state *mrb, mrb_value self)
Set a value pair from mruby.
Definition mruby.c:396
static void mruby_pair_parent_build(mrb_state *mrb, mruby_pair_t *pair)
Build parent structural pairs needed when a leaf node is set.
Definition mruby.c:301
struct RClass * mruby_pair_class(mrb_state *mrb, struct RClass *parent)
Definition mruby.c:625
static mrb_value mruby_pair_list_missing(mrb_state *mrb, mrb_value self)
Implement mruby method_missing functionality to find child pairs.
Definition mruby.c:495
mrb_value mruby_inst_object(mrb_state *mrb, struct RClass *klass, rlm_mruby_t const *inst)
Definition mruby.c:109
static mrb_value mruby_request_session_state(mrb_state *mrb, mrb_value self)
Definition mruby.c:58
fr_pair_t * vp
Real pair if it exists.
Definition mruby.c:33
static const struct mrb_data_type mruby_request_type
Definition mruby.c:86
static mrb_value mruby_request_frconfig(mrb_state *mrb, mrb_value self)
Definition mruby.c:38
fr_dict_attr_t const * da
Dictionary attribute for this pair.
Definition mruby.c:32
static mrb_value mruby_request_request(mrb_state *mrb, mrb_value self)
Definition mruby.c:43
static void mruby_roby_to_pair_value(mrb_state *mrb, mrb_value *value, fr_pair_t *vp)
Convert a ruby value to a fr_pair_t value.
Definition mruby.c:320
static mrb_value mruby_ruby_pair_object(mrb_state *mrb, struct RClass *klass, mruby_pair_t *pair)
Definition mruby.c:129
#define RUBYSETFLOAT(_size)
unsigned int fr_pair_count_by_da(fr_pair_list_t const *list, fr_dict_attr_t const *da)
Return the number of instances of a given da in the specified list.
Definition pair.c:674
int fr_pair_append_by_da(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list, fr_dict_attr_t const *da)
Alloc a new fr_pair_t (and append)
Definition pair.c:1463
int fr_pair_value_memdup(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Copy data into an "octets" data type.
Definition pair.c:2936
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:2590
fr_pair_t * fr_pair_find_by_da_idx(fr_pair_list_t const *list, fr_dict_attr_t const *da, unsigned int idx)
Find a pair with a matching da at a given index.
Definition pair.c:745
int fr_pair_value_bstrndup(fr_pair_t *vp, char const *src, size_t len, bool tainted)
Copy data into a "string" type value pair.
Definition pair.c:2786
void fr_pair_value_clear(fr_pair_t *vp)
Free/zero out value (or children) of a given VP.
Definition pair.c:2534
int fr_pair_delete(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list and free.
Definition pair.c:1823
#define fr_assert(_expr)
Definition rad_assert.h:38
#define RDEBUG2(fmt,...)
Definition radclient.h:54
Translates requests between the server an an mruby interpreter.
struct RClass * mruby_pair_list
Definition rlm_mruby.h:53
struct RClass * mruby_pair
Definition rlm_mruby.h:54
struct RClass * mruby_ptr
Definition rlm_mruby.h:52
return count
Definition module.c:155
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
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
static fr_slen_t parent
Definition pair.h:839
#define fr_type_is_group(_x)
Definition types.h:372
#define fr_type_is_leaf(_x)
Definition types.h:389
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