From: Nick Porter Date: Thu, 3 Jun 2021 17:13:21 +0000 (+0100) Subject: v4: Convert %(perl: ) to new xlat API (#4092) X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d38d2a2f12d522bcf44e7bc1ca4fcf783f76542c;p=thirdparty%2Ffreeradius-server.git v4: Convert %(perl: ) to new xlat API (#4092) * Define perl_vblist_to_av() to convert a value box list to a perl array * Define perl_sv_to_vblist() for parsing perl values to value boxes * Convert %(perl: ) to new xlat API * Add simple test for %(perl: ) * Add tests for %(perl: ) passing arrays and returning arrays / hashes * Correct perl calls to FR logging in example * Improve perl xlat comments * Add perl tests which access and manipulate attributes * Improve documentation for rlm_perl --- diff --git a/doc/antora/modules/raddb/pages/mods-available/perl.adoc b/doc/antora/modules/raddb/pages/mods-available/perl.adoc index a91020d15ba..d6b2cb9ff60 100644 --- a/doc/antora/modules/raddb/pages/mods-available/perl.adoc +++ b/doc/antora/modules/raddb/pages/mods-available/perl.adoc @@ -15,7 +15,6 @@ included in your module. If the module is called for a section which does not have a function defined, it will return `noop`. - ## Configuration Settings The following hashes are given to the module and @@ -97,7 +96,7 @@ For instance: [source,perl] ---- $RAD_PERLCONF{'name'} -$RAD_PERLCONF{'sub-config'}->{'name'}` +$RAD_PERLCONF{'sub-config'}->{'name'} ---- @@ -114,7 +113,6 @@ perl { # func_pre_proxy = pre_proxy # func_post_proxy = post_proxy # func_post_auth = post_auth -# func_xlat = xlat # func_detach = detach # func_start_accounting = accounting_start # func_stop_accounting = accounting_stop @@ -126,3 +124,29 @@ perl { # } } ``` + +## xlat for calling arbitrary Perl subroutines + +An xlat based on the instance name can be called to run arbitrary subroutines +declared in the perl file configured in the instance. The xlat takes the +subroutine name as its first argument and then any subsequent arguments are +passed as string scalars to the subroutine. If any of the arguments are +lists with multiple values e.g. `%{User-Name[*]}` where there are multiple +instances of `User-Name` then those arguments will be passed as references +to arrays containing all the values from the list. + +The return value of the subroutine is passed back as the expanded value of +the xlat. Since the subroutine is called in array context, all returned values +are received, though currently they are concatenated to form a single value. +This is due to change in the future. + +NOTE: The Perl xlat does not have access to the attribute lists, nor will +setting the hashes update the attribute lists. + +.Example + +``` +update control { + &Tmp-String-0 := "%(perl:myfunc arg1 arg2)" +} +``` diff --git a/raddb/mods-available/perl b/raddb/mods-available/perl index f54207cae36..9efba7500b1 100644 --- a/raddb/mods-available/perl +++ b/raddb/mods-available/perl @@ -88,7 +88,6 @@ perl { # func_pre_proxy = pre_proxy # func_post_proxy = post_proxy # func_post_auth = post_auth -# func_xlat = xlat # func_detach = detach # @@ -114,7 +113,7 @@ perl { # [source,perl] # ---- # $RAD_PERLCONF{'name'} - # $RAD_PERLCONF{'sub-config'}->{'name'}` + # $RAD_PERLCONF{'sub-config'}->{'name'} # ---- # # config { diff --git a/raddb/mods-config/perl/example.pl b/raddb/mods-config/perl/example.pl index d712e5e1c51..7b9b3a79dd3 100644 --- a/raddb/mods-config/perl/example.pl +++ b/raddb/mods-config/perl/example.pl @@ -180,14 +180,27 @@ sub post_auth { } # Function to handle xlat +# Receives arguments presented to the xlat as discrete +# arguments to the function. +# If any of the arguments are lists with multiple values e.g. +# %{User-Name[*]} where there are multiple instances of User-Name +# then these will be passed as references to arrays. +# +# Any return value is presented as the result of the xlat +# +# The function is called in array context so all returned values +# are received, though currently are concatenated before being +# presented as the expansion of the xlat. This is due to change +# in the future. +# +# Note: Hashes for the attribute lists are not available in +# xlat evaluation and neither will setting them result +# in attributes being created. sub xlat { - # For debugging purposes only -# log_request_attributes(); - # Loads some external perl and evaluate it my ($filename,$a,$b,$c,$d) = @_; - radiusd::radlog(L_DBG, "From xlat $filename"); - radiusd::radlog(L_DBG,"From xlat $a $b $c $d"); + radiusd::log(L_DBG, "From xlat $filename"); + radiusd::log(L_DBG,"From xlat $a $b $c $d"); open(my $FH, '<', $filename) or die "open '$filename' $!"; local($/) = undef; my $sub = <$FH>; @@ -215,7 +228,7 @@ sub log_request_attributes { # This shouldn't be done in production environments! # This is only meant for debugging! for (keys %RAD_REQUEST) { - radiusd::radlog(L_DBG, "RAD_REQUEST: $_ = $RAD_REQUEST{$_}"); + radiusd::log(L_DBG, "RAD_REQUEST: $_ = $RAD_REQUEST{$_}"); } } diff --git a/src/modules/rlm_perl/rlm_perl.c b/src/modules/rlm_perl/rlm_perl.c index 74dbe9f4c6b..e80d806a0c1 100644 --- a/src/modules/rlm_perl/rlm_perl.c +++ b/src/modules/rlm_perl/rlm_perl.c @@ -63,7 +63,6 @@ typedef struct { char const *func_stop_accounting; char const *func_preacct; char const *func_detach; - char const *func_xlat; char const *func_post_auth; char const *xlat_name; char const *perl_flags; @@ -79,6 +78,10 @@ typedef struct { } rlm_perl_t; +typedef struct { + rlm_perl_t *inst; //!< Module instance +} rlm_perl_xlat_t; + static void *perl_dlhandle; //!< To allow us to load perl's symbols into the global symbol table. /* @@ -96,7 +99,6 @@ static const CONF_PARSER module_config[] = { RLM_PERL_CONF(accounting), RLM_PERL_CONF(preacct), RLM_PERL_CONF(detach), - RLM_PERL_CONF(xlat), { FR_CONF_OFFSET("perl_flags", FR_TYPE_STRING, rlm_perl_t, perl_flags) }, @@ -351,23 +353,213 @@ static void xs_init(pTHX) newXS("radiusd::xlat",XS_radiusd_xlat, "rlm_perl"); } +/** Convert a list of value boxes to a Perl array for passing to subroutines + * + * The Perl array object should be created before calling this + * to populate it. + * + * @param[in,out] av Perl array object to append values to. + * @param[in] head of VB list. + * @return + * - 0 on success + * - -1 on failure + */ +static int perl_vblist_to_av(AV *av, fr_value_box_list_t *head) { + fr_value_box_t *vb = NULL; + SV *sv; + + while ((vb = fr_dlist_next(head, vb))) { + switch (vb->type) { + case FR_TYPE_STRING: + sv = newSVpvn(vb->vb_strvalue, vb->length); + break; + + case FR_TYPE_OCTETS: + sv = newSVpvn((char const *)vb->vb_octets, vb->vb_length); + break; + + case FR_TYPE_GROUP: + { + AV *sub_av; + sub_av = newAV(); + perl_vblist_to_av(sub_av, &vb->vb_group); + sv = newRV_inc((SV *)sub_av); + } + break; + default: + { + char buffer[1024]; + ssize_t slen; + + slen = fr_value_box_print_quoted(&FR_SBUFF_OUT(buffer, sizeof(buffer)), vb, T_BARE_WORD); + if (slen < 0) return -1; + sv = newSVpvn(buffer, (size_t)slen); + } + break; + } + if (!sv) return -1; + if (vb->tainted) SvTAINT(sv); + av_push(av, sv); + } + return 0; +} + +/** Parse a Perl SV and create value boxes, appending to a list + * + * For parsing values passed back from a Perl subroutine + * + * When hashes are returned, first the key is added as a value box then the value + * + * @param[in] ctx to allocate boxes in. + * @param[out] list to append value boxes to. + * @param[in] request being handled - only used for debug messages + * @param[in] sv to parse + * @return + * - 0 on success + * - -1 on failure + */ +static int perl_sv_to_vblist(TALLOC_CTX *ctx, fr_value_box_list_t *list, request_t *request, SV *sv) { + fr_value_box_t *vb = NULL; + char *tmp; + STRLEN len; + AV *av; + HV *hv; + I32 sv_len, i; + int type; + + type = SvTYPE(sv); + + switch (type) { + case SVt_IV: + /* Integer or Reference */ + if (SvROK(sv)) { + DEBUG3("Reference returned"); + if (perl_sv_to_vblist(ctx, list, request, SvRV(sv)) < 0) return -1; + break; + } + DEBUG3("Integer returned"); + MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_INT32, NULL, SvTAINTED(sv))); + vb->vb_int32 = SvIV(sv); + break; + + case SVt_NV: + /* Float */ + DEBUG3("Float returned"); + MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_FLOAT64, NULL, SvTAINTED(sv))); + vb->vb_float64 = SvNV(sv); + break; + + case SVt_PV: + /* String */ + DEBUG3("String returned"); + tmp = SvPVutf8(sv, len); + MEM(vb = fr_value_box_alloc_null(ctx)); + if (fr_value_box_bstrndup(ctx, vb, NULL, tmp, len, SvTAINTED(sv)) < 0) { + talloc_free(vb); + RPEDEBUG("Failed to allocate %ld for output", len); + return -1; + } + break; + + case SVt_PVAV: + /* Array */ + { + SV **av_sv; + DEBUG3("Array returned"); + av = (AV*)sv; + sv_len = av_len(av); + for (i = 0; i <= sv_len; i++) { + av_sv = av_fetch(av, i, 0); + if (SvOK(*av_sv)) { + if (perl_sv_to_vblist(ctx, list, request, *av_sv) < 0) return -1; + } + } + } + break; + + case SVt_PVHV: + /* Hash */ + { + SV *hv_sv; + DEBUG3("Hash returned"); + hv = (HV*)sv; + for (i = hv_iterinit(hv); i > 0; i--) { + hv_sv = hv_iternextsv(hv, &tmp, &sv_len); + /* + * Add key first + */ + MEM(vb = fr_value_box_alloc_null(ctx)); + if (fr_value_box_bstrndup(ctx, vb, NULL, tmp, sv_len, SvTAINTED(hv_sv)) < 0) { + talloc_free(vb); + RPEDEBUG("Failed to allocate %d for output", sv_len); + return -1; + } + fr_dlist_insert_tail(list, vb); + + /* + * Now process value + */ + if (perl_sv_to_vblist(ctx, list, request, hv_sv) < 0) return -1; + + } + /* + * Box has already been added to list - return + */ + return 0; + } + + case SVt_NULL: + break; + + default: + RPEDEBUG("Perl returned unsupported data type %d", type); + return -1; + + } + + if (vb) fr_dlist_insert_tail(list, vb); + + return 0; +} + +static int mod_xlat_instantiate(void *xlat_inst, UNUSED xlat_exp_t const *exp, void *uctx) +{ + rlm_perl_t *inst = talloc_get_type_abort(uctx, rlm_perl_t); + rlm_perl_xlat_t *xi = talloc_get_type_abort(xlat_inst, rlm_perl_xlat_t); + + xi->inst = inst; + + return 0; +} + +static xlat_arg_parser_t const perl_xlat_args[] = { + { .required = true, .single = true, .type = FR_TYPE_STRING }, + { .variadic = true, .type = FR_TYPE_VOID }, + XLAT_ARG_PARSER_TERMINATOR +}; + /** Call perl code using an xlat * * @ingroup xlat_functions */ -static ssize_t perl_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen, - void const *mod_inst, UNUSED void const *xlat_inst, - request_t *request, char const *fmt) +static xlat_action_t perl_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, request_t *request, + void const *xlat_inst, UNUSED void *xlat_thread_inst, + fr_value_box_list_t *in) { + rlm_perl_xlat_t const *xi = talloc_get_type_abort(UNCONST(void *, xlat_inst), rlm_perl_xlat_t); + rlm_perl_t *inst = xi->inst; + int count, i; + xlat_action_t ret = XLAT_ACTION_FAIL; + STRLEN n_a; + fr_value_box_t *func = fr_dlist_pop_head(in); + fr_value_box_t *arg = NULL, *child; + SV *sv; + AV *av; + fr_value_box_list_t list, sub_list; + fr_value_box_t *vb = NULL; - rlm_perl_t *inst; - char *tmp; - char const *p, *q; - int count; - size_t ret = 0; - STRLEN n_a; - - memcpy(&inst, &mod_inst, sizeof(inst)); + fr_value_box_list_init(&list); + fr_value_box_list_init(&sub_list); #ifdef USE_ITHREADS PerlInterpreter *interp; @@ -388,48 +580,64 @@ static ssize_t perl_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen, PUSHMARK(SP); - p = q = fmt; - while (*p == ' ') { - p++; - q++; - } - while (*q) { - if (*q == ' ') { - XPUSHs(sv_2mortal(newSVpvn(p, q - p))); - p = q + 1; + while ((arg = fr_dlist_next(in, arg))) { + fr_assert(arg->type == FR_TYPE_GROUP); + if (fr_dlist_empty(&arg->vb_group)) continue; + if (fr_dlist_num_elements(&arg->vb_group) == 1) { + child = fr_dlist_head(&arg->vb_group); /* - * Don't use an empty string + * Single child value - add as scalar */ - while (*p == ' ') p++; - q = p; + if (child->length == 0) continue; + DEBUG3("Passing single value %pV", child); + sv = newSVpvn(child->vb_strvalue, child->length); + if (child->tainted) SvTAINT(sv); + XPUSHs(sv_2mortal(sv)); + continue; } - q++; - } - /* - * And the last bit. - */ - if (*p) { - XPUSHs(sv_2mortal(newSVpvn(p, strlen(p)))); + /* + * Multiple child values - create array and pass reference + */ + av = newAV(); + perl_vblist_to_av(av, &arg->vb_group); + DEBUG3("Passing list as array %pM", &arg->vb_group); + sv = newRV_inc((SV *)av); + XPUSHs(sv_2mortal(sv)); } PUTBACK; - count = call_pv(inst->func_xlat, G_SCALAR | G_EVAL); + count = call_pv(func->vb_strvalue, G_ARRAY | G_EVAL); SPAGAIN; if (SvTRUE(ERRSV)) { REDEBUG("Exit %s", SvPV(ERRSV,n_a)); (void)POPs; - } else if (count > 0) { - tmp = POPp; - strlcpy(*out, tmp, outlen); - ret = strlen(*out); + goto cleanup; + } + + /* + * As results are popped from a stack, they are in reverse + * sequence. Add to a temporary list and then prepend to + * main list. + */ + for (i = 0; i < count; i++) { + sv = POPs; + if (perl_sv_to_vblist(ctx, &sub_list, request, sv) < 0) goto cleanup; + fr_dlist_move_head(&list, &sub_list); + } + ret = XLAT_ACTION_DONE; - RDEBUG2("Len is %zu , out is %s freespace is %zu", ret, *out, outlen); + /* + * Move the assembled list of boxes to the output + */ + while ((vb = fr_dlist_pop_head(&list))) { + fr_dcursor_append(out, vb); } + cleanup: PUTBACK ; FREETMPS ; LEAVE ; @@ -507,13 +715,15 @@ static void perl_parse_config(CONF_SECTION *cs, int lvl, HV *rad_hv) static int mod_bootstrap(void *instance, CONF_SECTION *conf) { rlm_perl_t *inst = instance; - + xlat_t *xlat; char const *xlat_name; xlat_name = cf_section_name2(conf); if (!xlat_name) xlat_name = cf_section_name1(conf); - xlat_register_legacy(inst, xlat_name, perl_xlat, NULL, NULL, 0, XLAT_DEFAULT_BUF_LEN); + xlat = xlat_register(NULL, xlat_name, perl_xlat, false); + xlat_func_args(xlat, perl_xlat_args); + xlat_async_instantiate_set(xlat, mod_xlat_instantiate, rlm_perl_xlat_t, NULL, inst); return 0; } diff --git a/src/tests/keywords/perl b/src/tests/keywords/perl new file mode 100644 index 00000000000..5d7d7ebd3c2 --- /dev/null +++ b/src/tests/keywords/perl @@ -0,0 +1,97 @@ +# +# PRE: update +# +# TODO +# A number of these tests return multiple values - either arrays, or hashes. +# Currently xlats have all returned values concatenated into a single value box - +# once multiple retuned boxes are handled to produce multiple attributes the tests +# will need amending. + +update request { + &Tmp-String-0 := "hello,goodbye,welcome,farewell" + &Tmp-String-1 := "foo,bar" +} +update request{ + &Tmp-String-2 := "%(perl:xlat %{Tmp-String-0})" +} + +if (&Tmp-String-2 != "hello|goodbye|welcome|farewell") { + test_fail +} + +# Check for multiple arguments to perl function +update request { + &Tmp-String-3 := "%(perl:xlat %{Tmp-String-0} %{Tmp-String-1})" +} + +if (&Tmp-String-3 != "hello|goodbye|welcome|farewell#foo|bar") { + test_fail +} + +update request { + &Tmp-Integer-0 := "%(perl:add 1 2 3)" +} + +if (&Tmp-Integer-0 != 6) { + test_fail +} + + +update request { + &Tmp-String-0 := "hello" + &Tmp-String-0 += "goodbye" + &Tmp-String-0 += "welcome" +} + +# Pass a list as an array +update request { + &Tmp-String-2 := "%(perl:xlatarray %{Tmp-String-0[*]})" +} + +if (&Tmp-String-2 != "hello|goodbye|welcome") { + test_fail +} + +update request { + &Tmp-String-0 := "aa bb cc dd ee" +} + +# Expect an array of returned values +update request { + &Tmp-String-2 := "%(perl:xlatscalar2array %{Tmp-String-0})" +} + +if (&Tmp-String-2 != "aabbccddee") { + test_fail +} + +update request { + &Tmp-String-1 := "ff gg hh ii" +} + +# Expect an array of array ref returned values +update request { + &Tmp-String-2 := "%(perl:xlatscalar2arrayref %{Tmp-String-0} %{Tmp-String-1})" +} + +if (&Tmp-String-2 != "aabbccddeeffgghhii") { + test_fail +} + +update request { + &Tmp-String-0 := "a" + &Tmp-String-0 += "b" + &Tmp-String-0 += "c" +} + +# Returns a hash with each element in the provided array converted to Vn->value +update request { + &Tmp-String-2 := "%(perl:xlatarray2hash %{Tmp-String-0[*]})" +} + +# Note: hashes don't have a defined sequence so these are all the possible return values +if (&Tmp-String-2 != "V1aV2bV3c") && (&Tmp-String-2 != "V1aV3cV2b") && (&Tmp-String-2 != "V2bV1aV3c") && (&Tmp-String-2 != "V2bV3cV1a") && (&Tmp-String-2 != "V3cV1aV2b") && (&Tmp-String-2 != "V3cV2bV1a") { + test_fail +} + +success diff --git a/src/tests/keywords/perl.conf b/src/tests/keywords/perl.conf new file mode 100644 index 00000000000..0a8a0c72636 --- /dev/null +++ b/src/tests/keywords/perl.conf @@ -0,0 +1,73 @@ +# +# Test code for use testing xlat functionality of rlm_perl +# + +use strict; +use warnings; + +use constant { + L_AUTH => 2, + L_INFO => 3, + L_ERR => 4, + L_WARN => 5, + L_PROXY => 6, + L_ACCT => 7, + L_DBG => 16, + L_DBG_WARN => 17, + L_DBG_ERR => 18, + L_DBG_WARN_REQ => 19, + L_DBG_ERR_REQ => 20, +}; + +# Function to handle xlat +# Just do something simple with all parameters provided and return to the caller +sub xlat { + + radiusd::log(L_DBG, 'From xlat '.join(' ', @_)); + + for (my $i = 0; $i <= $#_; $i++) { + $_[$i] = join('|', split(',', $_[$i])); + } + + return join('#', @_); +} + +# Simple function that returns an integer +sub add { + my $ret = 0; + for (my $i = 0; $i <= $#_; $i++) { + $ret += $_[$i]; + } + return $ret; +} + +# Function which expects the first argument to be an array ref +sub xlatarray{ + return join('|', @{ $_[0] }); +} + +# Take a scalar and return an array +sub xlatscalar2array { + return split(/ /, $_[0]); +} + +# Take an arbitary number of scalars and retun an array of array refs +sub xlatscalar2arrayref { + my @array; + for (my $i = 0; $i <= $#_; $i++) { + my @subarray = split(/ /, $_[$i]); + push (@array, \@subarray); + } + return @array; +} + +# Function which receives an array and returns a hash +sub xlatarray2hash { + my %hash; + my $i = 1; + foreach my $v (@{ $_[0] }) { + $hash{'V'.$i} = $v; + $i++; + } + return %hash; +} diff --git a/src/tests/keywords/radius.conf b/src/tests/keywords/radius.conf index 336d3753d79..995177e1dfa 100644 --- a/src/tests/keywords/radius.conf +++ b/src/tests/keywords/radius.conf @@ -62,6 +62,10 @@ modules { } + perl { + filename = ${keyword}/perl.conf + func_xlat = xlat + } } policy { diff --git a/src/tests/modules/perl/auth.attrs b/src/tests/modules/perl/auth.attrs new file mode 100644 index 00000000000..91f0a86e07d --- /dev/null +++ b/src/tests/modules/perl/auth.attrs @@ -0,0 +1,11 @@ +# +# Input packet +# +Packet-Type = Access-Request +User-Name = "baduser" +User-Password = "hello" + +# +# Expected answer +# +Packet-Type == Access-Accept diff --git a/src/tests/modules/perl/auth.unlang b/src/tests/modules/perl/auth.unlang new file mode 100644 index 00000000000..aef2b3c664a --- /dev/null +++ b/src/tests/modules/perl/auth.unlang @@ -0,0 +1,36 @@ +# Initial user will be rejected by the perl script. +perl.authenticate + +# fail has been used as the return code so the test doesn't exit. +if (!notfound) { + test_fail +} + +if (&reply.Reply-Message != "Denied access by rlm_perl function") { + test_fail +} + +update reply { + &Reply-Message !* ANY +} + +# User will not be rejected - an xlat will be called setting a reply attribute +update request { + &User-Name := 'bob' +} + +perl.authenticate + +if (!ok) { + test_fail +} + +if (&reply.Vendor-Specific.Cisco.h323-credit-amount != 100) { + test_fail +} + +update reply { + &Vendor-Specific.Cisco.h323-credit-amount !* ANY +} + +test_pass diff --git a/src/tests/modules/perl/module.conf b/src/tests/modules/perl/module.conf index 2a5dc325def..c4ea5b5f693 100644 --- a/src/tests/modules/perl/module.conf +++ b/src/tests/modules/perl/module.conf @@ -22,3 +22,7 @@ perl { # } # } } + +client { + +} \ No newline at end of file diff --git a/src/tests/modules/perl/test.pl b/src/tests/modules/perl/test.pl index 9eecf91dcb4..da244920d52 100644 --- a/src/tests/modules/perl/test.pl +++ b/src/tests/modules/perl/test.pl @@ -67,14 +67,15 @@ sub authenticate { if ($RAD_REQUEST{'User-Name'} =~ /^baduser/i) { # Reject user and tell him why $RAD_REPLY{'Reply-Message'} = "Denied access by rlm_perl function"; - return RLM_MODULE_REJECT; + # For testing return NOTFOUND - returning REJECT immediatly rejects the packet so fails the test + return RLM_MODULE_NOTFOUND; } else { # Accept user and set some attribute if (&radiusd::xlat("%(client:group)") eq 'UltraAllInclusive') { # User called from NAS with unlim plan set, set higher limits - $RAD_REPLY{'h323-credit-amount'} = "1000000"; + $RAD_REPLY{'Vendor-Specific.Cisco.h323-credit-amount'} = "1000000"; } else { - $RAD_REPLY{'h323-credit-amount'} = "100"; + $RAD_REPLY{'Vendor-Specific.Cisco.h323-credit-amount'} = "100"; } return RLM_MODULE_OK; } @@ -130,8 +131,8 @@ sub xlat { # Loads some external perl and evaluate it my ($filename,$a,$b,$c,$d) = @_; - radiusd::radlog(L_DBG, "From xlat $filename"); - radiusd::radlog(L_DBG,"From xlat $a $b $c $d"); + radiusd::log(L_DBG, "From xlat $filename"); + radiusd::log(L_DBG,"From xlat $a $b $c $d"); open(my $FH, '<', $filename) or die "open '$filename' $!"; local($/) = undef; my $sub = <$FH>; @@ -159,6 +160,6 @@ sub log_request_attributes { # This shouldn't be done in production environments! # This is only meant for debugging! for (keys %RAD_REQUEST) { - radiusd::radlog(L_DBG, "RAD_REQUEST: $_ = $RAD_REQUEST{$_}"); + radiusd::log(L_DBG, "RAD_REQUEST: $_ = $RAD_REQUEST{$_}"); } }