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