XSRETURN_NO;
}
+/*
+ * This is a wraper for radius_axlat
+ * Now users are able to get data that is accessible only via xlat
+ * e.g. %{client:...}
+ * Call syntax is radiusd::xlat(string), string will be handled the
+ * same way it is described in EXPANSIONS section of man unlang
+ */
+static XS(XS_radiusd_xlat)
+{
+ dXSARGS;
+ char *in_str;
+ char *expanded;
+ ssize_t slen;
+ SV *rad_requestp_sv;
+ REQUEST *request;
+
+ if (items != 1) croak("Usage: radiusd::xlat(string)");
+
+ rad_requestp_sv = get_sv("RAD___REQUESTP", 0);
+ if (rad_requestp_sv == NULL) croak("Can not evalue xlat, RAD___REQUESTP is not set!");
+
+ request = INT2PTR(REQUEST *, SvIV(rad_requestp_sv));
+
+ in_str = (char *) SvPV(ST(0), PL_na);
+ expanded = NULL;
+ slen = radius_axlat(&expanded, request, in_str, NULL, NULL);
+
+ if (slen < 0) {
+ REDEBUG("Error parsing xlat '%s'", in_str);
+ XSRETURN_UNDEF;
+ }
+
+
+ XST_mPV(0, expanded);
+ talloc_free(expanded);
+ XSRETURN(1);
+}
+
static void xs_init(pTHX)
{
char const *file = __FILE__;
newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
newXS("radiusd::radlog",XS_radiusd_radlog, "rlm_perl");
+ newXS("radiusd::xlat",XS_radiusd_xlat, "rlm_perl");
}
/*
const char *hash_name, const char *list_name)
{
VALUE_PAIR *vp;
+ char *tbuff;
+ size_t tbufflen = 1024;
hv_undef(rad_hv);
vp_cursor_t cursor;
+ /*
+ * Find out how much room to allocate.
+ */
+ for (vp = fr_cursor_init(&cursor, vps);
+ vp;
+ vp = fr_cursor_next(&cursor)) {
+ if (((vp->length * 2) + 3) > tbufflen) {
+ tbufflen = (vp->vp_length * 2) + 3;
+ }
+ }
+ tbuff = talloc_array(request, char, tbufflen);
+
RINDENT();
fr_pair_list_sort(vps, fr_pair_cmp_by_da_tag);
for (vp = fr_cursor_init(&cursor, vps);
vp;
vp = fr_cursor_next(&cursor)) {
VALUE_PAIR *next;
-
char const *name;
- char namebuf[256];
- char buffer[1024];
-
size_t len;
+ char namebuf[256];
/*
* Tagged attributes are added to the hash with name
break;
default:
- len = vp_prints_value(buffer, sizeof(buffer), vp, 0);
+ len = vp_prints_value(tbuff, tbufflen, vp, 0);
RDEBUG("$%s{'%s'} = &%s:%s -> '%s'", hash_name, vp->da->name,
- list_name, vp->da->name, buffer);
+ list_name, vp->da->name, tbuff);
(void)hv_store(rad_hv, name, strlen(name),
- newSVpvn(buffer, truncate_len(len, sizeof(buffer))), 0);
+ newSVpvn(tbuff, truncate_len(len, tbufflen)), 0);
break;
}
}
REXDENT();
+
+ talloc_free(tbuff);
}
/*
VALUE_PAIR *vp;
STRLEN len;
- VERIFY_LIST(*vps);
-
if (!SvOK(sv)) {
- fail:
- REDEBUG("Failed to create pair &%s:%s %s $%s{'%s'} -> '%s'", list_name, key,
+ REDEBUG("Internal failure creating pair &%s:%s %s $%s{'%s'} -> '%s'", list_name, key,
fr_int2str(fr_tokens, op, "<INVALID>"), hash_name, key, (val ? val : "undef"));
return;
}
+
val = SvPV(sv, len);
vp = fr_pair_make(ctx, vps, key, NULL, op);
- if (!vp) goto fail;
+ if (!vp) {
+ fail:
+ REDEBUG("Failed to create pair - %s", fr_strerror());
+ REDEBUG(" &%s:%s %s $%s{'%s'} -> '%s'", list_name, key,
+ fr_int2str(fr_tokens, op, "<INVALID>"), hash_name, key, (val ? val : "undef"));
+ return;
+ }
switch (vp->da->type) {
case PW_TYPE_STRING:
pairadd_sv(ctx, request, vps, key, res_sv, T_OP_EQ, hash_name, list_name);
}
}
+
+ if (*vps) VERIFY_LIST(*vps);
}
/*
HV *rad_request_proxy_hv;
HV *rad_request_proxy_reply_hv;
#endif
+ SV *rad_requestp_sv;
/*
* Radius has told us to call this function, but none
rad_config_hv = get_hv("RAD_CONFIG", 1);
rad_request_hv = get_hv("RAD_REQUEST", 1);
rad_state_hv = get_hv("RAD_STATE", 1);
+ rad_requestp_sv = get_sv("RAD___REQUESTP", 1);
perl_store_vps(request->packet, request, &request->packet->vps, rad_request_hv, "RAD_REQUEST", "request");
perl_store_vps(request->reply, request, &request->reply->vps, rad_reply_hv, "RAD_REPLY", "reply");
}
#endif
+ /*
+ * Store pointer to request structure globally so xlat works
+ * We mark it read-only for interpreter so end users will not be
+ * in posession to change it and crash radiusd with bogus pointer
+ */
+ SvREADONLY_off(rad_requestp_sv);
+ sv_setiv(rad_requestp_sv, PTR2IV(request));
+ SvREADONLY_on(rad_requestp_sv);
+
PUSHMARK(SP);
/*
* This way %RAD_xx can be pushed onto stack as sub parameters.