The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
rlm_perl.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 (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: 0854377c6990183178e7dabfc5f70bc2b4fdb2be $
19 * @file rlm_perl.c
20 * @brief Translates requests between the server an a perl interpreter.
21 *
22 * @copyright 2002,2006 The FreeRADIUS server project
23 * @copyright 2002 Boian Jordanov (bjordanov@orbitel.bg)
24 */
25RCSID("$Id: 0854377c6990183178e7dabfc5f70bc2b4fdb2be $")
26
27#define LOG_PREFIX "perl"
28
29#include <freeradius-devel/server/base.h>
30#include <freeradius-devel/server/module_rlm.h>
31#include <freeradius-devel/util/debug.h>
32#include <freeradius-devel/unlang/xlat_func.h>
33
34DIAG_OFF_OPTIONAL(compound-token-split-by-macro) /* Perl does horrible things with macros */
35DIAG_OFF_OPTIONAL(unreachable-code-return)
36DIAG_OFF_OPTIONAL(unreachable-code-break)
37
38#ifdef INADDR_ANY
39# undef INADDR_ANY
40#endif
41#include <EXTERN.h>
42#include <perl.h>
43#include <XSUB.h>
44#include <dlfcn.h>
45#include <semaphore.h>
46
47#if defined(__APPLE__) || defined(__FreeBSD__)
48extern char **environ;
49#endif
50
51#ifndef USE_ITHREADS
52# error perl must be compiled with USE_ITHREADS
53#endif
54
55typedef struct {
56 char const *function_name; //!< Name of the function being called
57 char *name1; //!< Section name1 where this is called
58 char *name2; //!< Section name2 where this is called
59 fr_rb_node_t node; //!< Node in tree of function calls.
61
62typedef struct {
65
66typedef struct {
67 pthread_mutex_t mutex;
69
70/*
71 * Define a structure for our module configuration.
72 *
73 * These variables do not need to be in a structure, but it's
74 * a lot cleaner to do so, and a pointer to the structure can
75 * be used as the instance handle.
76 */
77typedef struct {
78 /* Name of the perl module */
79 char const *module;
80
81 fr_rb_tree_t funcs; //!< Tree of function calls found by call_env parser.
82 bool funcs_init; //!< Has the tree been initialised.
83 char const *func_detach; //!< Function to run when mod_detach is run.
84 char const *perl_flags;
85 PerlInterpreter *perl;
87 HV *rad_perlconf_hv; //!< holds "config" items (perl %RAD_PERLCONF hash).
89
91
92typedef struct {
93 PerlInterpreter *perl; //!< Thread specific perl interpreter.
95
96/*
97 * C structure associated with tied hashes and arrays
98 */
101 fr_dict_attr_t const *da; //!< Dictionary attribute associated with hash / array.
102 fr_pair_t *vp; //!< Real pair associated with the hash / array, if it exists.
103 unsigned int idx; //!< Instance number.
104 fr_perl_pair_t *parent; //!< Parent attribute data.
105 fr_dcursor_t cursor; //!< Cursor used for iterating over the keys of a tied hash.
106};
107
108/*
109 * Dummy Magic Virtual Table used to ensure we retrieve the correct magic data
110 */
111static MGVTBL rlm_perl_vtbl = { 0, 0, 0, 0, 0, 0, 0, 0 };
112
113static void *perl_dlhandle; //!< To allow us to load perl's symbols into the global symbol table.
114
115/*
116 * A mapping of configuration file names to internal variables.
117 */
118static const conf_parser_t module_config[] = {
120
121 { FR_CONF_OFFSET("func_detach", rlm_perl_t, func_detach), .data = NULL, .dflt = "detach", .quote = T_INVALID },
122
123 { FR_CONF_OFFSET("perl_flags", rlm_perl_t, perl_flags) },
124
126};
127
128/** How to compare two Perl function calls
129 *
130 */
131static fr_cmp_ret_t perl_func_def_cmp(void const *one, void const *two)
132{
133 perl_func_def_t const *a = one, *b = two;
134 int ret;
135
136 ret = strcmp(a->name1, b->name1);
137 if (ret != 0) return CMP(ret, 0);
138 if (!a->name2 && !b->name2) return CMP_EQ;
139 if (!a->name2 || !b->name2) return a->name2 ? CMP_GT : CMP_LT;
140 ret = strcmp(a->name2, b->name2);
141 return CMP(ret, 0);
142}
143
144/*
145 * man perlembed
146 */
147EXTERN_C void boot_DynaLoader(pTHX_ CV* cv);
148
150
151# define dl_librefs "DynaLoader::dl_librefs"
152# define dl_modules "DynaLoader::dl_modules"
153static void rlm_perl_clear_handles(pTHX)
154{
155 AV *librefs = get_av(dl_librefs, false);
156 if (librefs) {
157 av_clear(librefs);
158 }
159}
160
161static void **rlm_perl_get_handles(pTHX)
162{
163 I32 i;
164 AV *librefs = get_av(dl_librefs, false);
165 AV *modules = get_av(dl_modules, false);
166 void **handles;
167
168 if (!librefs) return NULL;
169
170 if (!(AvFILL(librefs) >= 0)) {
171 return NULL;
172 }
173
174 MEM(handles = talloc_array(NULL, void *, AvFILL(librefs) + 2));
175 for (i = 0; i <= AvFILL(librefs); i++) {
176 void *handle;
177 SV *handle_sv = *av_fetch(librefs, i, false);
178 if (!handle_sv) {
179 ERROR("Could not fetch $%s[%d]!", dl_librefs, (int)i);
180 continue;
181 }
182 handle = INT2PTR(void *, SvIV(handle_sv));
183
184 if (handle) handles[i] = handle;
185 }
186
187 av_clear(modules);
188 av_clear(librefs);
189
190 handles[i] = (void *)0;
191
192 return handles;
193}
194
195static void rlm_perl_close_handles(void **handles)
196{
197 int i;
198
199 if (!handles) {
200 return;
201 }
202
203 for (i = 0; handles[i]; i++) {
204 DEBUG("Close %p", handles[i]);
205 dlclose(handles[i]);
206 }
207
208 talloc_free(handles);
209}
210
211/*
212 * This is wrapper for fr_log
213 * Now users can call freeradius::log(level,msg) which is the same
214 * as calling fr_log from C code.
215 */
216static XS(XS_freeradius_log)
217{
218 dXSARGS;
219 if (items !=2)
220 croak("Usage: radiusd::log(level, message)");
221 {
222 int level;
223 char *msg;
224
225 level = (int) SvIV(ST(0));
226 msg = (char *) SvPV(ST(1), PL_na);
227
228 /*
229 * Because 'msg' is a 'char *', we don't want '%s', etc.
230 * in it to give us printf-style vulnerabilities.
231 */
232 fr_log(&default_log, level, __FILE__, __LINE__, "rlm_perl: %s", msg);
233 }
234 XSRETURN_NO;
235}
236
237/*
238 * This is a wrapper for xlat_aeval
239 * Now users are able to get data that is accessible only via xlat
240 * e.g. %request.client(...)
241 * Call syntax is freeradius::xlat(string), string will be handled as
242 * a double-quoted string in the configuration files.
243 */
244static XS(XS_freeradius_xlat)
245{
246 dXSARGS;
247 char *in_str;
248 char *expanded;
249 ssize_t slen;
251
252 if (items != 1) croak("Usage: radiusd::xlat(string)");
253
255
256 in_str = (char *) SvPV(ST(0), PL_na);
257
258 slen = xlat_aeval(request, &expanded, request, in_str, NULL, NULL);
259 if (slen < 0) {
260 REDEBUG("Error parsing xlat '%s'", in_str);
261 XSRETURN_UNDEF;
262 }
263
264 XST_mPV(0, expanded);
265 talloc_free(expanded);
266 XSRETURN(1);
267}
268
269/** Helper function for turning hash keys into dictionary attributes
270 *
271 */
272static inline fr_dict_attr_t const *perl_attr_lookup(fr_perl_pair_t *pair_data, char const *attr)
273{
274 fr_dict_attr_t const *da = fr_dict_attr_by_name(NULL, pair_data->da, attr);
275
276 /*
277 * Allow fallback to internal attributes if the parent is a group or dictionary root.
278 */
279 if (!da && (fr_type_is_group(pair_data->da->type) || pair_data->da->flags.is_root)) {
281 }
282
283 if (!da) croak("Unknown or invalid attribute name \"%s\"", attr);
284
285 return da;
286}
287
288/** Convenience macro for fetching C data associated with tied hash / array and validating stack size
289 *
290 */
291#define GET_PAIR_MAGIC(count) MAGIC *mg = mg_findext(ST(0), PERL_MAGIC_ext, &rlm_perl_vtbl); \
292 fr_perl_pair_t *pair_data; \
293 if (unlikely(items < count)) { \
294 croak("Expected %d stack entries, got %d", count, items); \
295 XSRETURN_UNDEF; \
296 } \
297 if (!mg) { \
298 croak("Failed to find Perl magic value"); \
299 XSRETURN_UNDEF; \
300 } \
301 pair_data = (fr_perl_pair_t *)mg->mg_ptr;
302
303/** Functions to implement subroutines required for a tied hash
304 *
305 * All structural components of attributes are represented by tied hashes
306 */
307
308/** Called when fetching hash values
309 *
310 * The stack contains
311 * - the tied SV
312 * - the hash key being requested
313 *
314 * When a numeric key is requested, we treat that as in instruction to find
315 * a specific instance of the key of the parent.
316 *
317 * Whilst this is a bit odd, the alternative would be for every attribute to
318 * be returned as an array so you would end up with crazy syntax like
319 * p{'request'}{'Vendor-Specific'}[0]{'Cisco'}[0]{'AVPair}[0]
320 */
321static XS(XS_pairlist_FETCH)
322{
323 dXSARGS;
324 char *attr;
325 fr_dict_attr_t const *da;
326 fr_pair_t *vp = NULL;
327 STRLEN len, i = 0;
328 int idx = 0;
329
331
332 attr = (char *) SvPV(ST(1), len);
333
334 /*
335 * Check if our key is entirely numeric.
336 */
337 while (i < len) {
338 if (!isdigit(attr[i])) break;
339 i++;
340 }
341 if (i == len) {
342 idx = SvIV(ST(1));
343 da = pair_data->da;
344 if (pair_data->parent->vp) vp = fr_pair_find_by_da_idx(&pair_data->parent->vp->vp_group, da, idx);
345 } else {
346 da = perl_attr_lookup(pair_data, attr);
347 if (!da) XSRETURN_UNDEF;
348 if (pair_data->vp) vp = fr_pair_find_by_da(&pair_data->vp->vp_group, NULL, da);
349 }
350
351 switch(da->type) {
352 /*
353 * Leaf attributes are returned as an array with magic
354 */
355 case FR_TYPE_LEAF:
356 {
357 AV *pair_av;
358 SV *pair_tie;
359 HV *frpair_stash;
360 fr_perl_pair_t child_pair_data;
361
362 frpair_stash = gv_stashpv("freeradiuspairs", GV_ADD);
363 pair_av = newAV();
364 pair_tie = newRV_noinc((SV *)newAV());
365 sv_bless(pair_tie, frpair_stash);
366 sv_magic(MUTABLE_SV(pair_av), MUTABLE_SV((GV *)pair_tie), PERL_MAGIC_tied, NULL, 0);
367 SvREFCNT_dec(pair_tie);
368
369 child_pair_data = (fr_perl_pair_t) {
370 .vp = vp,
371 .da = da,
372 .parent = pair_data
373 };
374 sv_magicext((SV *)pair_tie, 0, PERL_MAGIC_ext, &rlm_perl_vtbl, (char *)&child_pair_data, sizeof(child_pair_data));
375 ST(0) = sv_2mortal(newRV((SV *)pair_av));
376 }
377 break;
378
379 /*
380 * Structural attributes are returned as a hash with magic
381 */
383 {
384 HV *struct_hv;
385 SV *struct_tie;
386 HV *frpair_stash;
387 fr_perl_pair_t child_pair_data;
388
389 frpair_stash = gv_stashpv("freeradiuspairlist", GV_ADD);
390 struct_hv = newHV();
391 struct_tie = newRV_noinc((SV *)newHV());
392 sv_bless(struct_tie, frpair_stash);
393 hv_magic(struct_hv, (GV *)struct_tie, PERL_MAGIC_tied);
394 SvREFCNT_dec(struct_tie);
395
396 child_pair_data = (fr_perl_pair_t) {
397 .vp = vp,
398 .da = da,
399 .parent = pair_data,
400 .idx = idx
401 };
402 sv_magicext((SV *)struct_tie, 0, PERL_MAGIC_ext, &rlm_perl_vtbl, (char *)&child_pair_data, sizeof(child_pair_data));
403 ST(0) = sv_2mortal(newRV((SV *)struct_hv));
404 }
405 break;
406
407 default:
408 fr_assert(0);
409 }
410
411 XSRETURN(1);
412}
413
414/** Called when a hash value is set / updated
415 *
416 * This is not allowed - only leaf node arrays can have values set
417 */
418static XS(XS_pairlist_STORE)
419{
420 dXSARGS;
421 char *attr;
422 fr_dict_attr_t const *da;
423
425
426 attr = (char *) SvPV(ST(1), PL_na);
427 da = perl_attr_lookup(pair_data, attr);
428 if (!da) XSRETURN(0);
429
430 if (fr_type_is_leaf(da->type)) {
431 croak("Cannot set value of array of \"%s\" values. Use array index to set a specific instance.", da->name);
432 } else {
433 croak("Cannot set values of structural object %s", da->name);
434 }
435 XSRETURN(0);
436}
437
438/** Called to test the existence of a key in a tied hash
439 *
440 * The stack contains
441 * - the tied SV
442 * - the key to check for
443 */
444static XS(XS_pairlist_EXISTS)
445{
446 dXSARGS;
447 char *attr;
448 fr_dict_attr_t const *da;
449 STRLEN len, i = 0;
450
452
453 attr = (char *) SvPV(ST(1), len);
454 while (i < len) {
455 if (!isdigit(attr[i])) break;
456 i++;
457 }
458
459 /*
460 * Numeric key - check for an instance of the attribute
461 */
462 if (i == len) {
463 unsigned int idx = SvIV(ST(1));
464 if (pair_data->parent->vp) {
465 if (fr_pair_find_by_da_idx(&pair_data->parent->vp->vp_group, pair_data->da, idx)) XSRETURN_YES;
466 }
467 XSRETURN_NO;
468 }
469
470 if (!pair_data->vp) XSRETURN_NO;
471
472 da = perl_attr_lookup(pair_data, attr);
473 if (!da) XSRETURN_NO;
474
475 if(fr_pair_find_by_da(&pair_data->vp->vp_group, NULL, da)) XSRETURN_YES;
476
477 XSRETURN_NO;
478}
479
480/** Called when functions like keys() want the first key in a tied hash
481 *
482 * The stack contains just the tied SV
483 */
484static XS(XS_pairlist_FIRSTKEY)
485{
486 dXSARGS;
487 fr_pair_t *vp;
488
490 if (!pair_data->vp) XSRETURN_EMPTY;
491
492 vp = fr_pair_dcursor_init(&pair_data->cursor, &pair_data->vp->vp_group);
493 if (!vp) XSRETURN_EMPTY;
494 ST(0) = sv_2mortal(newSVpv(vp->da->name, vp->da->name_len));
495 XSRETURN(1);
496}
497
498/** Called by functions like keys() which iterate over the keys in a tied hash
499 *
500 * The stack contains
501 * - the tied SV
502 * - the previous key
503 */
504static XS(XS_pairlist_NEXTKEY)
505{
506 dXSARGS;
507 fr_pair_t *vp;
508
510 if (!pair_data->vp) XSRETURN_EMPTY;
511
512 vp = fr_dcursor_next(&pair_data->cursor);
513 if (!vp) XSRETURN_EMPTY;
514
515 ST(0) = sv_2mortal(newSVpv(vp->da->name, vp->da->name_len));
516 XSRETURN(1);
517}
518
519/** Called to delete a key from a tied hash
520 *
521 * The stack contains
522 * - the tied SV
523 * - the key being deleted
524 */
525static XS(XS_pairlist_DELETE)
526{
527 dXSARGS;
528 char *attr;
529 fr_dict_attr_t const *da;
530 fr_pair_t *vp;
531
533 attr = SvPV(ST(1), PL_na);
534
535 da = perl_attr_lookup(pair_data, attr);
536 if (!da) XSRETURN(0);
537 if (!pair_data->vp) XSRETURN(0);
538
539 vp = fr_pair_find_by_da(&pair_data->vp->vp_group, NULL, da);
540
541 if (vp) fr_pair_delete(&pair_data->vp->vp_group, vp);
542
543 XSRETURN(0);
544}
545
546/** Functions to implement subroutines required for a tied array
547 *
548 * Leaf attributes are represented by tied arrays to allow multiple instances.
549 */
550
552{
553 switch(vp->vp_type) {
554 case FR_TYPE_STRING:
555 *value = sv_2mortal(newSVpvn(vp->vp_strvalue, vp->vp_length));
556 break;
557
558 case FR_TYPE_OCTETS:
559 *value = sv_2mortal(newSVpvn((char const *)vp->vp_octets, vp->vp_length));
560 break;
561
562#define PERLUINT(_size) case FR_TYPE_UINT ## _size: \
563 *value = sv_2mortal(newSVuv(vp->vp_uint ## _size)); \
564 break;
565 PERLUINT(8)
566 PERLUINT(16)
567 PERLUINT(32)
568 PERLUINT(64)
569
570#define PERLINT(_size) case FR_TYPE_INT ## _size: \
571 *value = sv_2mortal(newSViv(vp->vp_int ## _size)); \
572 break;
573 PERLINT(8)
574 PERLINT(16)
575 PERLINT(32)
576 PERLINT(64)
577
578
579 case FR_TYPE_SIZE:
580 *value = sv_2mortal(newSVuv(vp->vp_size));
581 break;
582
583 case FR_TYPE_BOOL:
584 *value = sv_2mortal(newSVuv(vp->vp_bool));
585 break;
586
587 case FR_TYPE_FLOAT32:
588 *value = sv_2mortal(newSVnv(vp->vp_float32));
589 break;
590
591 case FR_TYPE_FLOAT64:
592 *value = sv_2mortal(newSVnv(vp->vp_float64));
593 break;
594
595 case FR_TYPE_ETHERNET:
602 case FR_TYPE_IFID:
603 case FR_TYPE_DATE:
605 case FR_TYPE_ATTR:
606 {
607 char buff[128];
608 ssize_t slen;
609
611 if (slen < 0) {
612 croak("Cannot convert %s to Perl type, insufficient buffer space",
613 fr_type_to_str(vp->vp_type));
614 return -1;
615 }
616
617 *value = sv_2mortal(newSVpv(buff, slen));
618 }
619 break;
620
621 /* Only leaf nodes should be able to call this */
622 case FR_TYPE_NON_LEAF:
623 croak("Cannot convert %s to Perl type", fr_type_to_str(vp->vp_type));
624 return -1;
625 }
626
627 return 0;
628}
629
630/** Called to retrieve the value of an array entry
631 *
632 * In our case, retrieve the value of a specific instance of a leaf attribute
633 *
634 * The stack contains
635 * - the tied SV
636 * - the index to retrieve
637 *
638 * The magic data will hold the DA of the attribute.
639 */
640static XS(XS_pairs_FETCH)
641{
642 dXSARGS;
643 unsigned int idx = SvUV(ST(1));
644 fr_pair_t *vp = NULL;
646
648
649 parent = pair_data->parent;
650 if (!parent->vp) XSRETURN_UNDEF;
651
652 if (idx == 0) vp = pair_data->vp;
653 if (!vp) vp = fr_pair_find_by_da_idx(&parent->vp->vp_group, pair_data->da, idx);
654 if (!vp) XSRETURN_UNDEF;
655
656 if (perl_value_marshal(vp, &ST(0)) < 0) XSRETURN(0);
657 XSRETURN(1);
658}
659
660/** Build parent structural pairs needed when a leaf node is set
661 *
662 */
664{
665 fr_perl_pair_t *parent = pair_data->parent;
666 if (!parent->vp) {
667 /*
668 * When building parent with idx > 0, it's "parent" is the
669 * first instance of the attribute - so if that's not there
670 * we don't have any.
671 */
672 if (pair_data->idx > 0) {
673 none_exist:
674 croak("Attempt to set instance %u when none exist", pair_data->idx);
675 return -1;
676 }
677 if (fr_perl_pair_parent_build(parent) < 0) return -1;
678 }
679
680 if (pair_data->idx > 0) {
681 unsigned int count;
682
683 if (!parent->parent->vp) goto none_exist;
684 count = fr_pair_count_by_da(&parent->parent->vp->vp_group, pair_data->da);
685 if (count < pair_data->idx) {
686 croak("Attempt to set instance %u when only %u exist", pair_data->idx, count);
687 return -1;
688 }
689 parent = parent->parent;
690 }
691
692 if (fr_pair_append_by_da(parent->vp, &pair_data->vp, &parent->vp->vp_group, pair_data->da) < 0) return -1;
693 return 0;
694}
695
696/** Convert a Perl SV to a pair value.
697 *
698 */
700{
702
703 switch (SvTYPE(value)) {
704 case SVt_IV:
705 fr_value_box_init(&vb, FR_TYPE_INT64, NULL, true);
706 vb.vb_int64 = SvIV(value);
707 break;
708
709 case SVt_NV:
710 fr_value_box_init(&vb, FR_TYPE_FLOAT64, NULL, true);
711 vb.vb_float64 = SvNV(value);
712 break;
713
714 case SVt_PV:
715 case SVt_PVLV:
716 {
717 char *val;
718 STRLEN len;
719 fr_value_box_init(&vb, FR_TYPE_STRING, NULL, true);
720 val = SvPV(value, len);
721 fr_value_box_bstrndup_shallow(&vb, NULL, val, len, true);
722 }
723 break;
724
725 default:
726 croak("Unsupported Perl data type");
727 return -1;
728 }
729
731 if (fr_value_box_cast(vp, &vp->data, vp->vp_type, vp->da, &vb) < 0) {
732 croak("Failed casting Perl value to %s", fr_type_to_str(vp->vp_type));
733 return -1;
734 }
735
736 return 0;
737}
738
739/** Called when an array value is set / updated
740 *
741 * The stack contains
742 * - the tied SV
743 * - the index being updated
744 * - the value being assigned
745 */
746static XS(XS_pairs_STORE)
747{
748 dXSARGS;
749 unsigned int idx = SvUV(ST(1));
750 fr_pair_t *vp;
752
754
755 fr_assert(fr_type_is_leaf(pair_data->da->type));
756
757 parent = pair_data->parent;
758
759 if (!parent->vp) {
760 /*
761 * Trying to set something other than the first instance when
762 * the parent doesn't exist is invalid.
763 */
764 if (idx > 0) {
765 croak("Attempting to set instance %u when none exist", idx);
766 XSRETURN(0);
767 }
768
769 if(fr_perl_pair_parent_build(parent) < 0) XSRETURN(0);
770 }
771
772 vp = fr_pair_find_by_da_idx(&parent->vp->vp_group, pair_data->da, idx);
773 if (!vp) {
774 if (idx > 0) {
775 unsigned int count = fr_pair_count_by_da(&pair_data->parent->vp->vp_group, pair_data->da);
776 if (count < idx) {
777 croak("Attempt to set instance %u when only %u exist", idx, count);
778 XSRETURN(0);
779 }
780 }
781 fr_pair_append_by_da(parent->vp, &vp, &parent->vp->vp_group, pair_data->da);
782 }
783
784 perl_value_unmarshal(vp, ST(2));
785
786 XSRETURN(0);
787}
788
789/** Called when an array entry's existence is tested
790 *
791 */
792static XS(XS_pairs_EXISTS)
793{
794 dXSARGS;
795 unsigned int idx = SvUV(ST(1));
796 fr_pair_t *vp;
798
800
801 parent = pair_data->parent;
802 if (!parent->vp) XSRETURN_NO;
803
804 vp = fr_pair_find_by_da_idx(&parent->vp->vp_group, pair_data->da, idx);
805 if (vp) XSRETURN_YES;
806 XSRETURN_NO;
807}
808
809/** Called when an array entry is deleted
810 *
811 */
812static XS(XS_pairs_DELETE)
813{
814 dXSARGS;
815 unsigned int idx = SvUV(ST(1));
816 fr_pair_t *vp;
818
820
821 parent = pair_data->parent;
822 if (!parent->vp) XSRETURN(0);
823
824 vp = fr_pair_find_by_da_idx(&parent->vp->vp_group, pair_data->da, idx);
825 if (vp) fr_pair_delete(&parent->vp->vp_group, vp);
826 XSRETURN(0);
827}
828
829/** Called when Perl wants the size of a tied array
830 *
831 * The stack contains just the tied SV
832 */
833static XS(XS_pairs_FETCHSIZE)
834{
835 dXSARGS;
837
838 if (!pair_data->parent->vp) XSRETURN_UV(0);
839 XSRETURN_UV(fr_pair_count_by_da(&pair_data->parent->vp->vp_group, pair_data->da));
840}
841
842/** Called when attempting to set the size of an array
843 *
844 * We don't allow expanding the array this way, but will allow deleting pairs
845 *
846 * The stack contains
847 * - the tied SV
848 * - the requested size of the array
849 */
850static XS(XS_pairs_STORESIZE)
851{
852 dXSARGS;
853 unsigned int count, req_size = SvUV(ST(1));
854 fr_pair_t *vp, *prev;
857
858 parent = pair_data->parent;
859 if (!parent->vp) {
860 if (req_size > 0) {
861 croak("Unable to set attribute instance count");
862 }
863 XSRETURN(0);
864 }
865
866 count = fr_pair_count_by_da(&parent->vp->vp_group, pair_data->da);
867 if (req_size > count) {
868 croak("Increasing attribute instance count not supported");
869 XSRETURN(0);
870 }
871
872 /*
873 * As req_size is 1 based and the attribute instance count is
874 * 0 based, searching for instance `req_size` will give the first
875 * pair to delete.
876 */
877 vp = fr_pair_find_by_da_idx(&parent->vp->vp_group, pair_data->da, req_size);
878 while (vp) {
879 prev = fr_pair_list_prev(&parent->vp->vp_group, vp);
880 fr_pair_delete(&parent->vp->vp_group, vp);
881 vp = fr_pair_find_by_da(&parent->vp->vp_group, prev, pair_data->da);
882 }
883 XSRETURN(0);
884}
885
886/** Called when values are pushed on a tied array
887 *
888 * The stack contains
889 * - the tied SV
890 * - one or more values being pushed onto the array
891 */
892static XS(XS_pairs_PUSH)
893{
894 dXSARGS;
895 int i = 1;
896 fr_pair_t *vp;
898
900
901 fr_assert(fr_type_is_leaf(pair_data->da->type));
902
903 parent = pair_data->parent;
904 if (!parent->vp) {
905 if (fr_perl_pair_parent_build(parent) < 0) XSRETURN(0);
906 }
907
908 while (i < items) {
909 fr_pair_append_by_da(parent->vp, &vp, &parent->vp->vp_group, pair_data->da);
910 if (perl_value_unmarshal(vp, ST(i++)) < 0) break;
911 }
912
913 XSRETURN(0);
914}
915
916/** Called when values are popped off a tied array
917 *
918 * The stack contains just the tied SV
919 */
920static XS(XS_pairs_POP)
921{
922 dXSARGS;
923 fr_pair_t *vp;
925
927
928 fr_assert(fr_type_is_leaf(pair_data->da->type));
929
930 parent = pair_data->parent;
931 if (!parent->vp) XSRETURN(0);
932
933 vp = fr_pair_find_last_by_da(&parent->vp->vp_group, pair_data->da);
934 if (!vp) XSRETURN(0);
935
936 if (perl_value_marshal(vp, &ST(0)) < 0) XSRETURN(0);
937
938 fr_pair_remove(&parent->vp->vp_group, vp);
939 XSRETURN(1);
940}
941
942/** Called when values are "shifted" off a tied array
943 *
944 * The stack contains just the tied SV
945 */
946static XS(XS_pairs_SHIFT)
947{
948 dXSARGS;
949 fr_pair_t *vp;
951
953
954 fr_assert(fr_type_is_leaf(pair_data->da->type));
955
956 parent = pair_data->parent;
957 if (!parent->vp) XSRETURN(0);
958
959 vp = fr_pair_find_by_da(&parent->vp->vp_group, NULL, pair_data->da);
960 if (!vp) XSRETURN(0);
961
962 if (perl_value_marshal(vp, &ST(0)) < 0) XSRETURN(0);
963
964 fr_pair_remove(&parent->vp->vp_group, vp);
965 XSRETURN(1);
966}
967
968/** Called when values are "unshifted" onto a tied array
969 *
970 * The stack contains
971 * - the tied SV
972 * - one or more values being shifted onto the array
973 */
974static XS(XS_pairs_UNSHIFT)
975{
976 dXSARGS;
977 int i = 1;
978 fr_pair_t *vp;
980
982
983 fr_assert(fr_type_is_leaf(pair_data->da->type));
984
985 parent = pair_data->parent;
986 if (!parent->vp) {
987 if (fr_perl_pair_parent_build(parent) < 0) XSRETURN(0);
988 }
989
990 while (i < items) {
991 if (unlikely(fr_pair_prepend_by_da(parent->vp, &vp, &parent->vp->vp_group, pair_data->da) < 0)) {
992 croak("Failed adding attribute %s", pair_data->da->name);
993 break;
994 }
995 if (perl_value_unmarshal(vp, ST(i++)) < 0) break;
996 }
997
998 XSRETURN(0);
999}
1000
1001static void xs_init(pTHX)
1002{
1003 char const *file = __FILE__;
1004
1005 /* DynaLoader is a special case */
1006 newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
1007
1008 newXS("freeradius::log",XS_freeradius_log, "rlm_perl");
1009 newXS("freeradius::xlat",XS_freeradius_xlat, "rlm_perl");
1010
1011 /*
1012 * The freeradiuspairlist package implements functions required
1013 * for a tied hash handling structural attributes.
1014 */
1015 newXS("freeradiuspairlist::FETCH", XS_pairlist_FETCH, "rlm_perl");
1016 newXS("freeradiuspairlist::STORE", XS_pairlist_STORE, "rlm_perl");
1017 newXS("freeradiuspairlist::EXISTS", XS_pairlist_EXISTS, "rlm_perl");
1018 newXS("freeradiuspairlist::FIRSTKEY", XS_pairlist_FIRSTKEY, "rlm_perl");
1019 newXS("freeradiuspairlist::NEXTKEY", XS_pairlist_NEXTKEY, "rlm_perl");
1020 newXS("freeradiuspairlist::DELETE", XS_pairlist_DELETE, "rlm_perl");
1021
1022 /*
1023 * The freeradiuspairs package implements functions required
1024 * for a tied array handling leaf attributes.
1025 */
1026 newXS("freeradiuspairs::FETCH", XS_pairs_FETCH, "rlm_perl");
1027 newXS("freeradiuspairs::STORE", XS_pairs_STORE, "rlm_perl");
1028 newXS("freeradiuspairs::EXISTS", XS_pairs_EXISTS, "rlm_perl");
1029 newXS("freeradiuspairs::DELETE", XS_pairs_DELETE, "rlm_perl");
1030 newXS("freeradiuspairs::FETCHSIZE", XS_pairs_FETCHSIZE, "rlm_perl");
1031 newXS("freeradiuspairs::STORESIZE", XS_pairs_STORESIZE, "rlm_perl");
1032 newXS("freeradiuspairs::PUSH", XS_pairs_PUSH, "rlm_perl");
1033 newXS("freeradiuspairs::POP", XS_pairs_POP, "rlm_perl");
1034 newXS("freeradiuspairs::SHIFT", XS_pairs_SHIFT, "rlm_perl");
1035 newXS("freeradiuspairs::UNSHIFT", XS_pairs_UNSHIFT, "rlm_perl");
1036}
1037
1038/** Convert a list of value boxes to a Perl array for passing to subroutines
1039 *
1040 * The Perl array object should be created before calling this
1041 * to populate it.
1042 *
1043 * @param[in,out] av Perl array object to append values to.
1044 * @param[in] head of VB list.
1045 * @return
1046 * - 0 on success
1047 * - -1 on failure
1048 */
1049static int perl_vblist_to_av(AV *av, fr_value_box_list_t *head) {
1050 fr_value_box_t *vb = NULL;
1051 SV *sv;
1052
1053 while ((vb = fr_value_box_list_next(head, vb))) {
1054 switch (vb->type) {
1055 case FR_TYPE_STRING:
1056 sv = newSVpvn(vb->vb_strvalue, vb->vb_length);
1057 break;
1058
1059 case FR_TYPE_OCTETS:
1060 sv = newSVpvn((char const *)vb->vb_octets, vb->vb_length);
1061 break;
1062
1063 case FR_TYPE_GROUP:
1064 {
1065 AV *sub_av;
1066 sub_av = newAV();
1067 perl_vblist_to_av(sub_av, &vb->vb_group);
1068 sv = newRV_inc((SV *)sub_av);
1069 }
1070 break;
1071 default:
1072 {
1073 char buffer[1024];
1074 ssize_t slen;
1075
1076 slen = fr_value_box_print(&FR_SBUFF_OUT(buffer, sizeof(buffer)), vb, NULL);
1077 if (slen < 0) return -1;
1078 sv = newSVpvn(buffer, (size_t)slen);
1079 }
1080 break;
1081 }
1082 if (!sv) return -1;
1083 if (vb->tainted) SvTAINT(sv);
1084 av_push(av, sv);
1085 }
1086 return 0;
1087}
1088
1089/** Parse a Perl SV and create value boxes, appending to a list
1090 *
1091 * For parsing values passed back from a Perl subroutine
1092 *
1093 * When hashes are returned, first the key is added as a value box then the value
1094 *
1095 * @param[in] ctx to allocate boxes in.
1096 * @param[out] list to append value boxes to.
1097 * @param[in] request being handled - only used for debug messages
1098 * @param[in] sv to parse
1099 * @return
1100 * - 0 on success
1101 * - -1 on failure
1102 */
1103static int perl_sv_to_vblist(TALLOC_CTX *ctx, fr_value_box_list_t *list, request_t *request, SV *sv) {
1104 fr_value_box_t *vb = NULL;
1105 char *tmp;
1106 STRLEN len;
1107 AV *av;
1108 HV *hv;
1109 I32 sv_len, i;
1110 int type;
1111
1112 type = SvTYPE(sv);
1113
1114 switch (type) {
1115 case SVt_IV:
1116 /* Integer or Reference */
1117 if (SvROK(sv)) {
1118 RDEBUG3("Reference returned");
1119 if (perl_sv_to_vblist(ctx, list, request, SvRV(sv)) < 0) return -1;
1120 break;
1121 }
1122 RDEBUG3("Integer returned");
1123 MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_INT32, NULL));
1124 vb->vb_int32 = SvIV(sv);
1125 break;
1126
1127 case SVt_NV:
1128 /* Float */
1129 RDEBUG3("Float returned");
1130 MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_FLOAT64, NULL));
1131 vb->vb_float64 = SvNV(sv);
1132 break;
1133
1134 case SVt_PV:
1135 /* String */
1136 RDEBUG3("String returned");
1137 tmp = SvPVutf8(sv, len);
1138 MEM(vb = fr_value_box_alloc_null(ctx));
1139 if (fr_value_box_bstrndup(vb, vb, NULL, tmp, len, SvTAINTED(sv)) < 0) {
1140 talloc_free(vb);
1141 RPEDEBUG("Failed to allocate %zu for output", len);
1142 return -1;
1143 }
1144 break;
1145
1146 case SVt_PVAV:
1147 /* Array */
1148 {
1149 SV **av_sv;
1150 SSize_t last_idx, idx;
1151 RDEBUG3("Array returned");
1152 av = (AV*)sv;
1153 last_idx = av_len(av);
1154 for (idx = 0; idx <= last_idx; idx++) {
1155 av_sv = av_fetch(av, idx, 0);
1156 if (SvOK(*av_sv)) {
1157 if (perl_sv_to_vblist(ctx, list, request, *av_sv) < 0) return -1;
1158 }
1159 }
1160 }
1161 break;
1162
1163 case SVt_PVHV:
1164 /* Hash */
1165 {
1166 SV *hv_sv;
1167 RDEBUG3("Hash returned");
1168 hv = (HV*)sv;
1169 for (i = hv_iterinit(hv); i > 0; i--) {
1170 hv_sv = hv_iternextsv(hv, &tmp, &sv_len);
1171 /*
1172 * Add key first
1173 */
1174 MEM(vb = fr_value_box_alloc_null(ctx));
1175 if (fr_value_box_bstrndup(vb, vb, NULL, tmp, sv_len, SvTAINTED(hv_sv)) < 0) {
1176 talloc_free(vb);
1177 RPEDEBUG("Failed to allocate %d for output", sv_len);
1178 return -1;
1179 }
1180 fr_value_box_list_insert_tail(list, vb);
1181
1182 /*
1183 * Now process value
1184 */
1185 if (perl_sv_to_vblist(ctx, list, request, hv_sv) < 0) return -1;
1186
1187 }
1188 /*
1189 * Box has already been added to list - return
1190 */
1191 return 0;
1192 }
1193
1194 case SVt_NULL:
1195 break;
1196
1197 default:
1198 RPEDEBUG("Perl returned unsupported data type %d", type);
1199 return -1;
1200
1201 }
1202
1203 if (vb) {
1204 vb->tainted = SvTAINTED(sv);
1205 fr_value_box_list_insert_tail(list, vb);
1206 }
1207
1208 return 0;
1209}
1210
1212 { .required = true, .single = true, .type = FR_TYPE_STRING },
1213 { .variadic = XLAT_ARG_VARIADIC_EMPTY_KEEP, .type = FR_TYPE_VOID },
1215};
1216
1217/** Call perl code using an xlat
1218 *
1219 * @ingroup xlat_functions
1220 */
1221static xlat_action_t perl_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
1222 xlat_ctx_t const *xctx,
1223 request_t *request, fr_value_box_list_t *in)
1224{
1226 SSize_t count, i;
1228 STRLEN n_a;
1229 fr_value_box_t *func = fr_value_box_list_pop_head(in);
1230 fr_value_box_t *child;
1231 SV *sv;
1232 AV *av;
1233 fr_value_box_list_t list, sub_list;
1234 fr_value_box_t *vb = NULL;
1235
1236#ifdef __COVERITY__
1237 if (!func) return XLAT_ACTION_FAIL;
1238#endif
1239
1240 fr_value_box_list_init(&list);
1241 fr_value_box_list_init(&sub_list);
1242
1243 {
1244 dTHXa(t->perl);
1245 PERL_SET_CONTEXT(t->perl);
1246 }
1247
1248 {
1249 ssize_t slen;
1250 fr_sbuff_t *sbuff;
1251
1252 dSP;
1253 ENTER;SAVETMPS;
1254
1255 PUSHMARK(SP);
1256
1257 FR_SBUFF_TALLOC_THREAD_LOCAL(&sbuff, 256, 16384);
1258
1260
1261 fr_assert(arg->type == FR_TYPE_GROUP);
1262 if (fr_value_box_list_empty(&arg->vb_group)) continue;
1263
1264 if (fr_value_box_list_num_elements(&arg->vb_group) == 1) {
1265 child = fr_value_box_list_head(&arg->vb_group);
1266
1267 switch (child->type) {
1268 case FR_TYPE_STRING:
1269 if (child->vb_length == 0) continue;
1270
1271 RDEBUG3("Passing single value %pV", child);
1272 sv = newSVpvn(child->vb_strvalue, child->vb_length);
1273 break;
1274
1275 case FR_TYPE_GROUP:
1276 RDEBUG3("Ignoring nested group");
1277 continue;
1278
1279 default:
1280 /*
1281 * @todo - turn over integers as strings.
1282 */
1283 slen = fr_value_box_print(sbuff, child, NULL);
1284 if (slen <= 0) {
1285 RPEDEBUG("Failed printing sbuff");
1286 continue;
1287 }
1288
1289 RDEBUG3("Passing single value %pV", child);
1290 sv = newSVpvn(fr_sbuff_start(sbuff), fr_sbuff_used(sbuff));
1291 fr_sbuff_set_to_start(sbuff);
1292 break;
1293 }
1294
1295 if (child->tainted) SvTAINT(sv);
1296 XPUSHs(sv_2mortal(sv));
1297 continue;
1298 }
1299
1300 /*
1301 * Multiple child values - create array and pass reference
1302 */
1303 av = newAV();
1304 perl_vblist_to_av(av, &arg->vb_group);
1305 RDEBUG3("Passing list as array %pM", &arg->vb_group);
1306 sv = newRV_inc((SV *)av);
1307 XPUSHs(sv_2mortal(sv));
1308 }
1309
1310 PUTBACK;
1311
1312 count = call_pv(func->vb_strvalue, G_ARRAY | G_EVAL);
1313
1314 SPAGAIN;
1315 if (SvTRUE(ERRSV)) {
1316 REDEBUG("Exit %s", SvPV(ERRSV,n_a));
1317 (void)POPs;
1318 goto cleanup;
1319 }
1320
1321 /*
1322 * As results are popped from a stack, they are in reverse
1323 * sequence. Add to a temporary list and then prepend to
1324 * main list.
1325 */
1326 for (i = 0; i < count; i++) {
1327 sv = POPs;
1328 if (perl_sv_to_vblist(ctx, &sub_list, request, sv) < 0) goto cleanup;
1329 fr_value_box_list_move_head(&list, &sub_list);
1330 }
1331 ret = XLAT_ACTION_DONE;
1332
1333 /*
1334 * Move the assembled list of boxes to the output
1335 */
1336 while ((vb = fr_value_box_list_pop_head(&list))) fr_dcursor_append(out, vb);
1337
1338 cleanup:
1339 PUTBACK;
1340 FREETMPS;
1341 LEAVE;
1342
1343 }
1344
1345 return ret;
1346}
1347
1348/*
1349 * Parse a configuration section, and populate a HV.
1350 * This function is recursively called (allows to have nested hashes.)
1351 */
1352static void perl_parse_config(CONF_SECTION *cs, int lvl, HV *rad_hv)
1353{
1354 int indent_section = (lvl + 1) * 4;
1355 int indent_item = (lvl + 2) * 4;
1356
1357 if (!cs || !rad_hv) return;
1358
1359 DEBUG("%*s%s {", indent_section, " ", cf_section_name1(cs));
1360
1361 for (CONF_ITEM *ci = NULL; (ci = cf_item_next(cs, ci)); ) {
1362 /*
1363 * This is a section.
1364 * Create a new HV, store it as a reference in current HV,
1365 * Then recursively call perl_parse_config with this section and the new HV.
1366 */
1367 if (cf_item_is_section(ci)) {
1368 CONF_SECTION *sub_cs = cf_item_to_section(ci);
1369 char const *key = cf_section_name1(sub_cs); /* hash key */
1370 HV *sub_hv;
1371 SV *ref;
1372
1373 if (!key) continue;
1374
1375 if (hv_exists(rad_hv, key, strlen(key))) {
1376 WARN("Ignoring duplicate config section '%s'", key);
1377 continue;
1378 }
1379
1380 sub_hv = newHV();
1381 ref = newRV_inc((SV*) sub_hv);
1382
1383 (void)hv_store(rad_hv, key, strlen(key), ref, 0);
1384
1385 perl_parse_config(sub_cs, lvl + 1, sub_hv);
1386 } else if (cf_item_is_pair(ci)){
1387 CONF_PAIR *cp = cf_item_to_pair(ci);
1388 char const *key = cf_pair_attr(cp); /* hash key */
1389 char const *value = cf_pair_value(cp); /* hash value */
1390
1391 if (!key || !value) continue;
1392
1393 /*
1394 * This is an item.
1395 * Store item attr / value in current HV.
1396 */
1397 if (hv_exists(rad_hv, key, strlen(key))) {
1398 WARN("Ignoring duplicate config item '%s'", key);
1399 continue;
1400 }
1401
1402 (void)hv_store(rad_hv, key, strlen(key), newSVpvn(value, strlen(value)), 0);
1403
1404 DEBUG("%*s%s = %s", indent_item, " ", key, value);
1405 }
1406 }
1407
1408 DEBUG("%*s}", indent_section, " ");
1409}
1410
1411/** Create a Perl tied hash representing a pair list
1412 *
1413 */
1414static void perl_pair_list_tie(HV *parent, HV *frpair_stash, char const *name, fr_pair_t *vp, fr_dict_attr_t const *da)
1415{
1416 HV *list_hv;
1417 SV *list_tie;
1418 fr_perl_pair_t pair_data;
1419
1420 list_hv = newHV();
1421 list_tie = newRV_noinc((SV *)newHV());
1422 sv_bless(list_tie, frpair_stash);
1423 hv_magic(list_hv, (GV *)list_tie, PERL_MAGIC_tied);
1424 SvREFCNT_dec(list_tie);
1425
1426 pair_data = (fr_perl_pair_t) {
1427 .vp = vp,
1428 .da = da
1429 };
1430
1431 sv_magicext((SV *)list_tie, 0, PERL_MAGIC_ext, &rlm_perl_vtbl, (char *)&pair_data, sizeof(pair_data));
1432
1433 (void)hv_store(parent, name, strlen(name), newRV_inc((SV *)list_hv), 0);
1434}
1435
1436/*
1437 * Call the function_name inside the module
1438 * Store all vps in hashes %RAD_CONFIG %RAD_REPLY %RAD_REQUEST
1439 *
1440 */
1442{
1443 rlm_perl_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_perl_t);
1444 perl_call_env_t *func = talloc_get_type_abort(mctx->env_data, perl_call_env_t);
1445 PerlInterpreter *interp = ((rlm_perl_thread_t *)talloc_get_type_abort(mctx->thread, rlm_perl_thread_t))->perl;
1446 int ret=0;
1447 SSize_t count;
1448 STRLEN n_a;
1449
1450 HV *frpair_stash;
1451 HV *fr_packet;
1452
1453 /*
1454 * call_env parsing will have established the function name to call.
1455 */
1457
1458 {
1459 dTHXa(interp);
1460 PERL_SET_CONTEXT(interp);
1461 }
1462
1463 {
1464 dSP;
1465
1466 ENTER;
1467 SAVETMPS;
1468
1469 /* Get the stash for the freeradiuspairlist package */
1470 frpair_stash = gv_stashpv("freeradiuspairlist", GV_ADD);
1471
1472 /* New hash to hold the pair list roots and pass to the Perl subroutine */
1473 fr_packet = newHV();
1474
1475 perl_pair_list_tie(fr_packet, frpair_stash, "request",
1476 fr_pair_list_parent(&request->request_pairs), fr_dict_root(request->proto_dict));
1477 perl_pair_list_tie(fr_packet, frpair_stash, "reply",
1478 fr_pair_list_parent(&request->reply_pairs), fr_dict_root(request->proto_dict));
1479 perl_pair_list_tie(fr_packet, frpair_stash, "control",
1480 fr_pair_list_parent(&request->control_pairs), fr_dict_root(request->proto_dict));
1481 perl_pair_list_tie(fr_packet, frpair_stash, "session-state",
1482 fr_pair_list_parent(&request->session_state_pairs), fr_dict_root(request->proto_dict));
1483
1484 /*
1485 * Store pointer to request structure globally so radiusd::xlat works
1486 */
1488
1489 PUSHMARK(SP);
1490 XPUSHs( sv_2mortal(newRV((SV *)fr_packet)) );
1491 PUTBACK;
1492
1493 count = call_pv(func->func->function_name, G_SCALAR | G_EVAL );
1494
1495 rlm_perl_request = NULL;
1496
1497 SPAGAIN;
1498
1499 if (SvTRUE(ERRSV)) {
1500 REDEBUG("perl_embed:: module = %s , func = %s exit status= %s\n",
1501 inst->module, func->func->function_name, SvPV(ERRSV,n_a));
1502 (void)POPs;
1503 ret = RLM_MODULE_FAIL;
1504 } else if (count == 1) {
1505 ret = POPi;
1506 if (!RLM_MODULE_RCODE_VALID(ret)) {
1507 RERROR("Perl function returned %d, which is not a valid return code", ret);
1508 ret = RLM_MODULE_FAIL;
1509 }
1510 }
1511
1512 PUTBACK;
1513 FREETMPS;
1514 LEAVE;
1515 }
1516
1518}
1519
1520DIAG_OFF_OPTIONAL(shadow)
1521static void rlm_perl_interp_free(PerlInterpreter *perl)
1522{
1523 void **handles;
1524
1525 {
1526 dTHXa(perl);
1527 PERL_SET_CONTEXT(perl);
1528 }
1529
1530 handles = rlm_perl_get_handles(aTHX);
1531 if (handles) rlm_perl_close_handles(handles);
1532
1533 PL_perl_destruct_level = 2;
1534
1535 PL_origenviron = environ;
1536
1537 /*
1538 * FIXME: This shouldn't happen
1539 *
1540 */
1541 while (PL_scopestack_ix > 1) LEAVE;
1542
1543 perl_destruct(perl);
1544 perl_free(perl);
1545}
1546DIAG_ON_OPTIONAL(shadow)
1547
1549{
1550 rlm_perl_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_perl_t);
1551 rlm_perl_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_perl_thread_t);
1552 PerlInterpreter *interp;
1553 UV clone_flags = 0;
1554
1555 PERL_SET_CONTEXT(inst->perl);
1556
1557 /*
1558 * Ensure only one thread is cloning an interpreter at a time
1559 * Whilst the documentation of perl_clone() does not say anything
1560 * about this, seg faults have been seen if multiple threads clone
1561 * the same inst->perl at the same time.
1562 */
1563 pthread_mutex_lock(&inst->mutable->mutex);
1564 interp = perl_clone(inst->perl, clone_flags);
1565 pthread_mutex_unlock(&inst->mutable->mutex);
1566 {
1567 dTHXa(interp); /* Sets the current thread's interpreter */
1568 }
1569# if PERL_REVISION >= 5 && PERL_VERSION <8
1570 call_pv("CLONE", 0);
1571# endif
1572 ptr_table_free(PL_ptr_table);
1573 PL_ptr_table = NULL;
1574
1575 PERL_SET_CONTEXT(aTHX);
1577
1578 t->perl = interp; /* Store perl interp for easy freeing later */
1579
1580 return 0;
1581}
1582
1584{
1585 rlm_perl_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_perl_thread_t);
1586
1588
1589 return 0;
1590}
1591
1592/** Check if a given Perl subroutine exists
1593 *
1594 */
1595static bool perl_func_exists(char const *func)
1596{
1597 char *eval_str;
1598 SV *val;
1599
1600 /*
1601 * Perl's "can" method checks if the object contains a subroutine of the given name.
1602 * We expect referenced subroutines to be in the "main" namespace.
1603 */
1604 eval_str = talloc_asprintf(NULL, "(main->can('%s') ? 1 : 0)", func);
1605 val = eval_pv(eval_str, TRUE);
1606 talloc_free(eval_str);
1607 return SvIV(val) ? true : false;
1608}
1609
1610/*
1611 * Do any per-module initialization that is separate to each
1612 * configured instance of the module. e.g. set up connections
1613 * to external databases, read configuration files, set up
1614 * dictionary entries, etc.
1615 *
1616 * If configuration information is given in the config section
1617 * that must be referenced in later calls, store a handle to it
1618 * in *instance otherwise put a null pointer there.
1619 *
1620 * Setup a hashes which we will use later
1621 * parse a module and give it a chance to live
1622 *
1623 */
1624static int mod_instantiate(module_inst_ctx_t const *mctx)
1625{
1626 rlm_perl_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_perl_t);
1627 perl_func_def_t *func = NULL;
1629 CONF_PAIR *cp;
1630 char *pair_name;
1631
1632 CONF_SECTION *conf = mctx->mi->conf;
1633 AV *end_AV;
1634
1635 char const **embed_c; /* Stupid Perl and lack of const consistency */
1636 char **embed;
1637 int ret = 0, argc = 0;
1638 char arg[] = "0";
1639
1640 CONF_SECTION *cs;
1641
1642 /*
1643 * Setup the argument array we pass to the perl interpreter
1644 */
1645 MEM(embed_c = talloc_zero_array(inst, char const *, 4));
1646 memcpy(&embed, &embed_c, sizeof(embed));
1647 embed_c[0] = NULL;
1648 if (inst->perl_flags) {
1649 embed_c[1] = inst->perl_flags;
1650 embed_c[2] = inst->module;
1651 embed_c[3] = arg;
1652 argc = 4;
1653 } else {
1654 embed_c[1] = inst->module;
1655 embed_c[2] = arg;
1656 argc = 3;
1657 }
1658
1659 /*
1660 * Allocate a new perl interpreter to do the parsing
1661 */
1662 if ((inst->perl = perl_alloc()) == NULL) {
1663 ERROR("No memory for allocating new perl interpreter!");
1664 return -1;
1665 }
1666 perl_construct(inst->perl); /* ...and initialise it */
1667
1668 PL_perl_destruct_level = 2;
1669 {
1670 dTHXa(inst->perl);
1671 }
1672 PERL_SET_CONTEXT(inst->perl);
1673
1674#if PERL_REVISION >= 5 && PERL_VERSION >=8
1675 PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
1676#endif
1677
1678 ret = perl_parse(inst->perl, xs_init, argc, embed, NULL);
1679
1680 end_AV = PL_endav;
1681 PL_endav = (AV *)NULL;
1682
1683 if (ret) {
1684 ERROR("Perl_parse failed: %s not found or has syntax errors", inst->module);
1685 return -1;
1686 }
1687
1688 /* parse perl configuration sub-section */
1689 cs = cf_section_find(conf, "config", NULL);
1690 if (cs) {
1691 inst->rad_perlconf_hv = get_hv("RAD_PERLCONF", 1);
1692 perl_parse_config(cs, 0, inst->rad_perlconf_hv);
1693 }
1694
1695 inst->perl_parsed = true;
1696 perl_run(inst->perl);
1697
1698 /*
1699 * The call_env parser has found all the places the module is called
1700 * Check for config options which set the subroutine name, falling back to
1701 * automatic subroutine names based on section name.
1702 */
1703 if (!inst->funcs_init) fr_rb_inline_init(&inst->funcs, perl_func_def_t, node, perl_func_def_cmp, NULL);
1704
1705 for (func = fr_rb_iter_init_inorder(&inst->funcs, &iter);
1706 func != NULL;
1707 func = fr_rb_iter_next_inorder(&inst->funcs, &iter)) {
1708 /*
1709 * Check for func_<name1>_<name2> or func_<name1> config pairs.
1710 */
1711 if (func->name2) {
1712 pair_name = talloc_asprintf(func, "func_%s_%s", func->name1, func->name2);
1713 cp = cf_pair_find(mctx->mi->conf, pair_name);
1714 talloc_free(pair_name);
1715 if (cp) goto found_func;
1716 }
1717 pair_name = talloc_asprintf(func, "func_%s", func->name1);
1718 cp = cf_pair_find(conf, pair_name);
1719 talloc_free(pair_name);
1720 found_func:
1721 if (cp){
1722 func->function_name = cf_pair_value(cp);
1723 if (!perl_func_exists(func->function_name)) {
1724 cf_log_err(cp, "Perl subroutine %s does not exist", func->function_name);
1725 return -1;
1726 }
1727 /*
1728 * If no pair was found, then use <name1>_<name2> or <name1> as the function to call.
1729 */
1730 } else if (func->name2) {
1731 func->function_name = talloc_asprintf(func, "%s_%s", func->name1, func->name2);
1732 if (!perl_func_exists(func->function_name)) {
1734 goto name1_only;
1735 }
1736 } else {
1737 name1_only:
1738 func->function_name = func->name1;
1739 if (!perl_func_exists(func->function_name)) {
1740 cf_log_err(cp, "Perl subroutine %s does not exist", func->function_name);
1741 return -1;
1742 }
1743 }
1744 }
1745
1746 PL_endav = end_AV;
1747
1748 inst->mutable = talloc(NULL, rlm_perl_mutable_t);
1749 pthread_mutex_init(&inst->mutable->mutex, NULL);
1750
1751 return 0;
1752}
1753
1754/*
1755 * Detach a instance give a chance to a module to make some internal setup ...
1756 */
1757DIAG_OFF(nested-externs)
1758static int mod_detach(module_detach_ctx_t const *mctx)
1759{
1760 rlm_perl_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_perl_t);
1761 int ret = 0;
1762 SSize_t count = 0;
1763
1764
1765 if (inst->perl_parsed) {
1766 dTHXa(inst->perl);
1767 PERL_SET_CONTEXT(inst->perl);
1768 if (inst->rad_perlconf_hv != NULL) hv_undef(inst->rad_perlconf_hv);
1769
1770 if (inst->func_detach) {
1771 dSP; ENTER; SAVETMPS;
1772 PUSHMARK(SP);
1773
1774 count = call_pv(inst->func_detach, G_SCALAR | G_EVAL );
1775 SPAGAIN;
1776
1777 if (count == 1) {
1778 ret = POPi;
1779 if (ret >= 100 || ret < 0) {
1780 ret = RLM_MODULE_FAIL;
1781 }
1782 }
1783 PUTBACK;
1784 FREETMPS;
1785 LEAVE;
1786 }
1787 }
1788
1790 talloc_free(inst->mutable);
1791
1792 return ret;
1793}
1794DIAG_ON(nested-externs)
1795
1796static int mod_bootstrap(module_inst_ctx_t const *mctx)
1797{
1798 xlat_t *xlat;
1799
1800 xlat = module_rlm_xlat_register(mctx->mi->boot, mctx, NULL, perl_xlat, FR_TYPE_VOID);
1802
1803 return 0;
1804}
1805
1806static int mod_load(void)
1807{
1808 char const **embed_c; /* Stupid Perl and lack of const consistency */
1809 char **embed;
1810 char **envp = NULL;
1811 int argc = 0;
1812
1813#define LOAD_INFO(_fmt, ...) fr_log(LOG_DST, L_INFO, __FILE__, __LINE__, "rlm_perl - " _fmt, ## __VA_ARGS__)
1814#define LOAD_WARN(_fmt, ...) fr_log_perror(LOG_DST, L_WARN, __FILE__, __LINE__, \
1815 (&(fr_log_perror_format_t){ \
1816 .first_prefix = "rlm_perl - ", \
1817 .subsq_prefix = "rlm_perl - ", \
1818 }), \
1819 _fmt, ## __VA_ARGS__)
1820
1821 LOAD_INFO("Perl version: %s", PERL_API_VERSION_STRING);
1822 dependency_version_number_add(NULL, "perl", PERL_API_VERSION_STRING);
1823
1824 /*
1825 * Load perl using RTLD_GLOBAL and dlopen.
1826 * This fixes issues where Perl C extensions
1827 * can't find the symbols they need.
1828 */
1829 perl_dlhandle = dl_open_by_sym("perl_construct", RTLD_NOW | RTLD_GLOBAL);
1830 if (!perl_dlhandle) LOAD_WARN("Failed loading libperl symbols into global symbol table");
1831
1832 /*
1833 * Setup the argument array we pass to the perl interpreter
1834 */
1835 MEM(embed_c = talloc_zero_array(NULL, char const *, 1));
1836 memcpy(&embed, &embed_c, sizeof(embed));
1837 embed_c[0] = NULL;
1838 argc = 1;
1839
1840 PERL_SYS_INIT3(&argc, &embed, &envp);
1841
1842 talloc_free(embed_c);
1843
1844 return 0;
1845}
1846
1847static void mod_unload(void)
1848{
1849 if (perl_dlhandle) dlclose(perl_dlhandle);
1850 PERL_SYS_TERM();
1851}
1852
1853/*
1854 * Restrict automatic Perl function names to lowercase characters, numbers and underscore
1855 * meaning that a module call in `recv Access-Request` will look for `recv_access_request`
1856 */
1857static void perl_func_name_safe(char *name) {
1858 char *p;
1859 size_t i;
1860
1861 p = name;
1862 for (i = 0; i < talloc_array_length(name); i++) {
1863 *p = tolower(*p);
1864 if (!strchr("abcdefghijklmnopqrstuvwxyz1234567890", *p)) *p = '_';
1865 p++;
1866 }
1867}
1868
1869static int perl_func_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, UNUSED tmpl_rules_t const *t_rules,
1870 UNUSED CONF_ITEM *ci, call_env_ctx_t const *cec, call_env_parser_t const *rule)
1871{
1872 rlm_perl_t *inst = talloc_get_type_abort(cec->mi->data, rlm_perl_t);
1873 call_env_parsed_t *parsed;
1874 perl_func_def_t *func;
1875 void *found;
1876
1877 if (!inst->funcs_init) {
1879 inst->funcs_init = true;
1880 }
1881
1882 MEM(parsed = call_env_parsed_add(ctx, out,
1884 .name = "func",
1885 .flags = CALL_ENV_FLAG_PARSE_ONLY,
1886 .pair = {
1887 .parsed = {
1888 .offset = rule->pair.offset,
1890 }
1891 }
1892 }));
1893
1894 MEM(func = talloc_zero(inst, perl_func_def_t));
1895 func->name1 = talloc_strdup(func, cec->asked->name1);
1897 if (cec->asked->name2) {
1898 func->name2 = talloc_strdup(func, cec->asked->name2);
1900 }
1901 if (fr_rb_find_or_insert(&found, &inst->funcs, func) < 0) {
1902 talloc_free(func);
1903 return -1;
1904 }
1905
1906 /*
1907 * If the function call is already in the tree, use that entry.
1908 */
1909 if (found) {
1910 talloc_free(func);
1911 call_env_parsed_set_data(parsed, found);
1912 } else {
1913 call_env_parsed_set_data(parsed, func);
1914 }
1915 return 0;
1916}
1917
1925
1926/*
1927 * The module name should be the only globally exported symbol.
1928 * That is, everything else should be 'static'.
1929 *
1930 * If the module needs to temporarily modify it's instantiation
1931 * data, the type should be changed to MODULE_TYPE_THREAD_UNSAFE.
1932 * The server will then take care of ensuring that the module
1933 * is single-threaded.
1934 */
1935extern module_rlm_t rlm_perl;
1937 .common = {
1938 .magic = MODULE_MAGIC_INIT,
1939 .name = "perl",
1940 .inst_size = sizeof(rlm_perl_t),
1941
1943 .onload = mod_load,
1944 .unload = mod_unload,
1945 .bootstrap = mod_bootstrap,
1946 .instantiate = mod_instantiate,
1947 .detach = mod_detach,
1948
1949 .thread_inst_size = sizeof(rlm_perl_thread_t),
1950 .thread_instantiate = mod_thread_instantiate,
1951 .thread_detach = mod_thread_detach,
1952 },
1953 .method_group = {
1954 .bindings = (module_method_binding_t[]){
1955 { .section = SECTION_NAME(CF_IDENT_ANY, CF_IDENT_ANY), .method = mod_perl, .method_env = &perl_method_env },
1957 }
1958 }
1959};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
static int const char char buffer[256]
Definition acutest.h:641
int const char * file
Definition acutest.h:855
log_entry msg
Definition acutest.h:947
#define _Thread_local
Definition atexit.h:213
static uint8_t request[4]
#define RCSID(id)
Definition build.h:603
#define DIAG_OFF_OPTIONAL(_x)
Definition build.h:577
#define DIAG_ON(_x)
Definition build.h:576
#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:130
#define unlikely(_x)
Definition build.h:486
#define UNUSED
Definition build.h:415
#define DIAG_ON_OPTIONAL(_x)
Definition build.h:578
#define DIAG_OFF(_x)
Definition build.h:575
fr_cmp_ret_t
Result of an ordering comparison.
Definition build.h:113
@ CMP_GT
a > b
Definition build.h:117
@ CMP_LT
a < b
Definition build.h:115
@ CMP_EQ
a == b
Definition build.h:116
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:687
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:744
#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_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_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
module_instance_t const * mi
Module instance that the callenv is registered to.
Definition call_env.h:229
@ CALL_ENV_PARSE_TYPE_VOID
Output of the parsing phase is undefined (a custom structure).
Definition call_env.h:62
#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:722
void * data
Pointer to a static variable to write the parsed value to.
Definition cf_parse.h:663
#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:280
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:466
@ CONF_FLAG_FILE_READABLE
File matching value must exist, and must be readable.
Definition cf_parse.h:472
#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:268
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:649
Common header for all CONF_* types.
Definition cf_priv.h:54
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:77
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:106
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
Definition cf_util.c:619
char const * cf_section_name1(CONF_SECTION const *cs)
Return the first identifier of a CONF_SECTION.
Definition cf_util.c:1391
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:1247
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition cf_util.c:671
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
Definition cf_util.c:1640
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
Definition cf_util.c:605
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:651
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1758
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
Definition cf_util.c:1742
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:340
#define cf_item_next(_parent, _curr)
Definition cf_util.h:91
#define CF_IDENT_ANY
Definition cf_util.h:80
static int split(char **input, char **output, bool syntax_string)
Definition command.c:393
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition dcursor.h:288
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition dcursor.h:406
#define MEM(x)
Definition debug.h:38
int dependency_version_number_add(CONF_SECTION *cs, char const *name, char const *version)
Add a library/server version pair to the main configuration.
Definition dependency.c:151
#define ERROR(fmt,...)
Definition dhcpclient.c:40
#define DEBUG(fmt,...)
Definition dhcpclient.c:38
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:3600
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2717
fr_dict_t const * fr_dict_internal(void)
Definition dict_util.c:5065
Test enumeration values.
Definition dict_test.h:92
void * dl_open_by_sym(char const *sym_name, int flags)
Utility function to dlopen the library containing a particular symbol.
Definition dl.c:186
#define RTLD_NOW
Definition dl.c:44
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
static xlat_action_t perl_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Call perl code using an xlat.
Definition rlm_perl.c:1221
talloc_free(hp)
#define RDEBUG3(fmt,...)
Definition log.h:360
#define RERROR(fmt,...)
Definition log.h:315
#define RPEDEBUG(fmt,...)
Definition log.h:393
fr_log_t default_log
Definition log.c:308
#define fr_log(_log, _lvl, _file, _line, _fmt,...)
Definition log.h:172
#define ENTER(_x)
Definition machine.h:93
@ 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_ETHERNET
48 Bit Mac-Address.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_INT64
64 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_INT32
32 Bit signed integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
@ FR_TYPE_VOID
User data.
@ 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_GROUP
A grouping of other attributes.
@ FR_TYPE_FLOAT64
Double precision floating point.
long int ssize_t
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
void * thread
Thread specific instance data.
Definition module_ctx.h:43
void * thread
Thread instance data.
Definition module_ctx.h:67
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
Temporary structure to hold arguments for thread_instantiation calls.
Definition module_ctx.h:63
xlat_t * module_rlm_xlat_register(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
Definition module_rlm.c:234
module_t common
Common fields presented by all modules.
Definition module_rlm.h:39
fr_pair_t * fr_pair_list_parent(fr_pair_list_t const *list)
Return a pointer to the parent pair which contains this list.
Definition pair.c:928
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:684
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:1416
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition pair.c:707
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:754
fr_pair_t * fr_pair_find_last_by_da(fr_pair_list_t const *list, fr_dict_attr_t const *da)
Find the last pair with a matching da.
Definition pair.c:730
void fr_pair_value_clear(fr_pair_t *vp)
Free/zero out value (or children) of a given VP.
Definition pair.c:2485
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:1778
int fr_pair_prepend_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 prepend)
Definition pair.c:1443
static const conf_parser_t config[]
Definition base.c:162
#define fr_assert(_expr)
Definition rad_assert.h:37
#define REDEBUG(fmt,...)
#define WARN(fmt,...)
static bool cleanup
Definition radsniff.c:59
static rs_t * conf
Definition radsniff.c:52
void * fr_rb_iter_init_inorder(fr_rb_tree_t *tree, fr_rb_iter_inorder_t *iter)
Initialise an in-order iterator.
Definition rb.c:850
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:608
void * fr_rb_iter_next_inorder(UNUSED fr_rb_tree_t *tree, fr_rb_iter_inorder_t *iter)
Return the next node.
Definition rb.c:876
#define fr_rb_inline_init(_tree, _type, _field, _data_cmp, _data_free)
Initialises a red black tree.
Definition rb.h:178
Iterator structure for in-order traversal of an rbtree.
Definition rb.h:319
The main red black tree structure.
Definition rb.h:71
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition rcode.h:48
#define RETURN_UNLANG_RCODE(_rcode)
Definition rcode.h:67
#define RLM_MODULE_RCODE_VALID(_rcode)
Whether an integer is an rcode which a module may return.
Definition rcode.h:64
static int perl_sv_to_vblist(TALLOC_CTX *ctx, fr_value_box_list_t *list, request_t *request, SV *sv)
Parse a Perl SV and create value boxes, appending to a list.
Definition rlm_perl.c:1103
static fr_dict_attr_t const * perl_attr_lookup(fr_perl_pair_t *pair_data, char const *attr)
Helper function for turning hash keys into dictionary attributes.
Definition rlm_perl.c:272
fr_rb_node_t node
Node in tree of function calls.
Definition rlm_perl.c:59
static int mod_detach(module_detach_ctx_t const *mctx)
Definition rlm_perl.c:1758
static int mod_load(void)
Definition rlm_perl.c:1806
PerlInterpreter * perl
Thread specific perl interpreter.
Definition rlm_perl.c:93
static bool perl_func_exists(char const *func)
Check if a given Perl subroutine exists.
Definition rlm_perl.c:1595
HV * rad_perlconf_hv
holds "config" items (perl RAD_PERLCONF hash).
Definition rlm_perl.c:87
static XS(XS_freeradius_log)
Definition rlm_perl.c:216
static void perl_func_name_safe(char *name)
Definition rlm_perl.c:1857
static xlat_arg_parser_t const perl_xlat_args[]
Definition rlm_perl.c:1211
char const * func_detach
Function to run when mod_detach is run.
Definition rlm_perl.c:83
char const * function_name
Name of the function being called.
Definition rlm_perl.c:56
#define PERLINT(_size)
#define PERLUINT(_size)
static void ** rlm_perl_get_handles(pTHX)
Definition rlm_perl.c:161
bool perl_parsed
Definition rlm_perl.c:86
fr_perl_pair_t * parent
Parent attribute data.
Definition rlm_perl.c:104
static int perl_value_marshal(fr_pair_t *vp, SV **value)
Functions to implement subroutines required for a tied array.
Definition rlm_perl.c:551
EXTERN_C void boot_DynaLoader(pTHX_ CV *cv)
static void perl_parse_config(CONF_SECTION *cs, int lvl, HV *rad_hv)
Definition rlm_perl.c:1352
char const * perl_flags
Definition rlm_perl.c:84
static int mod_bootstrap(module_inst_ctx_t const *mctx)
Definition rlm_perl.c:1796
char * name1
Section name1 where this is called.
Definition rlm_perl.c:57
#define dl_modules
Definition rlm_perl.c:152
static fr_cmp_ret_t perl_func_def_cmp(void const *one, void const *two)
How to compare two Perl function calls.
Definition rlm_perl.c:131
module_rlm_t rlm_perl
Definition rlm_perl.c:1936
static void rlm_perl_interp_free(PerlInterpreter *perl)
Definition rlm_perl.c:1521
static int perl_value_unmarshal(fr_pair_t *vp, SV *value)
Convert a Perl SV to a pair value.
Definition rlm_perl.c:699
char const *fr_rb_tree_t funcs
Tree of function calls found by call_env parser.
Definition rlm_perl.c:81
static MGVTBL rlm_perl_vtbl
Definition rlm_perl.c:111
static void mod_unload(void)
Definition rlm_perl.c:1847
static void xs_init(pTHX)
Definition rlm_perl.c:1001
fr_dict_attr_t const * da
Dictionary attribute associated with hash / array.
Definition rlm_perl.c:101
struct fr_perl_pair_s fr_perl_pair_t
Definition rlm_perl.c:99
#define LOAD_WARN(_fmt,...)
static void rlm_perl_close_handles(void **handles)
Definition rlm_perl.c:195
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
Definition rlm_perl.c:1548
fr_dcursor_t cursor
Cursor used for iterating over the keys of a tied hash.
Definition rlm_perl.c:105
static void perl_pair_list_tie(HV *parent, HV *frpair_stash, char const *name, fr_pair_t *vp, fr_dict_attr_t const *da)
Create a Perl tied hash representing a pair list.
Definition rlm_perl.c:1414
#define GET_PAIR_MAGIC(count)
Convenience macro for fetching C data associated with tied hash / array and validating stack size.
Definition rlm_perl.c:291
unsigned int idx
Instance number.
Definition rlm_perl.c:103
PerlInterpreter * perl
Definition rlm_perl.c:85
static unlang_action_t mod_perl(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition rlm_perl.c:1441
char * name2
Section name2 where this is called.
Definition rlm_perl.c:58
#define dl_librefs
Definition rlm_perl.c:151
static int perl_vblist_to_av(AV *av, fr_value_box_list_t *head)
Convert a list of value boxes to a Perl array for passing to subroutines.
Definition rlm_perl.c:1049
static void * perl_dlhandle
To allow us to load perl's symbols into the global symbol table.
Definition rlm_perl.c:113
#define LOAD_INFO(_fmt,...)
static const conf_parser_t module_config[]
Definition rlm_perl.c:118
static _Thread_local request_t * rlm_perl_request
Definition rlm_perl.c:149
static const call_env_method_t perl_method_env
Definition rlm_perl.c:1918
static int perl_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, call_env_parser_t const *rule)
Definition rlm_perl.c:1869
bool funcs_init
Has the tree been initialised.
Definition rlm_perl.c:82
pthread_mutex_t mutex
Definition rlm_perl.c:67
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
Definition rlm_perl.c:1583
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition rlm_perl.c:1624
fr_pair_t * vp
Real pair associated with the hash / array, if it exists.
Definition rlm_perl.c:102
perl_func_def_t * func
Definition rlm_perl.c:63
static void rlm_perl_clear_handles(pTHX)
Definition rlm_perl.c:153
static int fr_perl_pair_parent_build(fr_perl_pair_t *pair_data)
Build parent structural pairs needed when a leaf node is set.
Definition rlm_perl.c:663
static char const * name
#define fr_sbuff_start(_sbuff_or_marker)
#define FR_SBUFF_OUT(_start, _len_or_end)
#define fr_sbuff_used(_sbuff_or_marker)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
Definition section.h:39
char const * name2
Second section name. Usually a packet type like 'access-request', 'access-accept',...
Definition section.h:45
char const * name1
First section name. Usually a verb like 'recv', 'send', etc...
Definition section.h:44
API for POSIX semaphores in mmapped memory.
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:355
size_t inst_size
Size of the module's instance data.
Definition module.h:213
void * data
Module's instance data.
Definition module.h:297
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Definition module.h:153
Named methods exported by a module.
Definition module.h:175
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:343
static char buff[sizeof("18446744073709551615")+3]
Definition size_tests.c:37
return count
Definition module.c:155
eap_aka_sim_process_conf_t * inst
fr_aka_sim_id_type_t type
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 talloc_get_type_abort_const
Definition talloc.h:117
static int talloc_const_free(void const *ptr)
Free const'd memory.
Definition talloc.h:289
#define talloc_asprintf
Definition talloc.h:151
#define talloc_strdup(_ctx, _str)
Definition talloc.h:149
@ T_INVALID
Definition token.h:37
@ T_BARE_WORD
Definition token.h:118
xlat_action_t
Definition xlat.h:37
@ XLAT_ACTION_FAIL
An xlat function failed.
Definition xlat.h:44
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition xlat.h:43
@ XLAT_ARG_VARIADIC_EMPTY_KEEP
Empty argument groups are left alone, and either passed through as empty groups or null boxes.
Definition xlat.h:127
static fr_slen_t head
Definition xlat.h:410
unsigned int required
Argument must be present, and non-empty.
Definition xlat.h:136
#define XLAT_ARG_PARSER_TERMINATOR
Definition xlat.h:160
ssize_t xlat_aeval(TALLOC_CTX *ctx, char **out, request_t *request, char const *fmt, xlat_escape_legacy_t escape, void const *escape_ctx))
Definition xlat_eval.c:1916
Definition for a single argument consumed by an xlat function.
Definition xlat.h:135
fr_pair_t * fr_pair_remove(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list without freeing.
Definition pair_inline.c:93
ssize_t fr_pair_print_value_quoted(fr_sbuff_t *out, fr_pair_t const *vp, fr_token_t quote)
Print the value of an attribute to a string.
Definition pair_print.c:59
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
Definition pair.h:605
fr_pair_t * fr_pair_list_prev(fr_pair_list_t const *list, fr_pair_t const *item))
Get the previous item in a valuepair list before a specific entry.
Definition pair_inline.c:82
static fr_slen_t parent
Definition pair.h:864
@ FR_TYPE_ATTR
A contains an attribute reference.
Definition types.h:83
#define fr_type_is_group(_x)
Definition types.h:376
#define FR_TYPE_NON_LEAF
Definition types.h:318
#define FR_TYPE_STRUCTURAL
Definition types.h:316
#define fr_type_is_leaf(_x)
Definition types.h:393
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:454
#define FR_TYPE_LEAF
Definition types.h:317
ssize_t fr_value_box_print(fr_sbuff_t *out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules)
Print one boxed value to a string.
Definition value.c:6293
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
Definition value.c:4071
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
Definition value.c:5014
void fr_value_box_bstrndup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Assign a string to to a fr_value_box_t.
Definition value.c:5101
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
Definition value.h:668
static fr_sbuff_err_t char size_t fr_sbuff_t * in
Definition value.h:1061
static fr_sbuff_err_t char ** out
Definition value.h:1061
static fr_sbuff_err_t char size_t * len
Definition value.h:1061
int nonnull(2, 5))
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
Definition value.h:679
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
Definition value.h:634
#define fr_value_box_list_foreach(_list_head, _iter)
Definition value.h:253
module_ctx_t const * mctx
Synthesised module calling ctx.
Definition xlat_ctx.h:52
An xlat calling ctx.
Definition xlat_ctx.h:49
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
Definition xlat_func.c:374