26RCSID(
"$Id: 512484de8948670daf8972da4476ce30b25aab4c $")
28#define LOG_PREFIX mctx->mi->name
30#include <freeradius-devel/server/base.h>
31#include <freeradius-devel/util/debug.h>
40#define RLM_LUA_STACK_SET() int _fr_lua_stack_state = lua_gettop(L)
41#define RLM_LUA_STACK_RESET() lua_settop(L, _fr_lua_stack_state)
69#if PTRDIFF_MAX < INT64_MAX
70#define IN_RANGE_INTEGER_SIGNED(_x) \
72 if ((((int64_t)(_x)) < PTRDIFF_MIN) || (((int64_t)(_x)) > PTRDIFF_MAX)) { \
73 REDEBUG("Value (%" PRId64 ") cannot be represented as Lua integer. Must be between %td-%td", \
74 (int64_t)(_x), (ptrdiff_t)PTRDIFF_MIN, (ptrdiff_t)PTRDIFF_MAX); \
79#define IN_RANGE_INTEGER_UNSIGNED(_x) \
81 if (((uint64_t)(_x)) > PTRDIFF_MAX) { \
82 REDEBUG("Value (%" PRIu64 ") cannot be represented as Lua integer. Must be between 0-%td", \
83 (uint64_t)(_x), (ptrdiff_t)PTRDIFF_MAX); \
88#define IN_RANGE_INTEGER_SIGNED(_x) \
92#define IN_RANGE_INTEGER_UNSIGNED(_x) \
97#define IN_RANGE_FLOAT_SIGNED(_x) \
99 if ((((double)(_x)) < DBL_MIN) || (((double)(_x)) > DBL_MAX)) { \
100 REDEBUG("Value (%f) cannot be represented as Lua number. Must be between %f-%f", \
101 (double)(_x), DBL_MIN, DBL_MAX); \
106 switch (
vp->vp_type) {
122 REDEBUG(
"Cannot convert %s to Lua type, insufficient buffer space",
127 lua_pushlstring(
L,
buff, (
size_t)slen);
132 lua_pushlstring(
L,
vp->vp_strvalue,
vp->vp_length);
136 lua_pushlstring(
L, (
char const *)
vp->vp_octets,
vp->vp_length);
140 lua_pushinteger(
L, (lua_Integer)(
vp->vp_bool ? 1 : 0));
144 lua_pushinteger(
L, (lua_Integer)
vp->vp_uint8);
148 lua_pushinteger(
L, (lua_Integer)
vp->vp_uint16);
152 lua_pushinteger(
L, (lua_Integer)
vp->vp_uint32);
157 lua_pushinteger(
L, (lua_Integer)
vp->vp_uint64);
161 lua_pushinteger(
L, (lua_Integer)
vp->vp_int8);
165 lua_pushinteger(
L, (lua_Integer)
vp->vp_int16);
169 lua_pushinteger(
L, (lua_Integer)
vp->vp_int32);
174 lua_pushinteger(
L, (lua_Integer)
vp->vp_int64);
183 lua_pushnumber(
L, (lua_Number)
vp->vp_float32);
188 lua_pushnumber(
L, (lua_Number)
vp->vp_float64);
193 lua_pushinteger(
L, (lua_Integer)
vp->vp_size);
221 switch (lua_type(
L, -1)) {
232 "fr_value_box_t field smaller than return from lua_tointeger");
235 "fr_value_box_t field smaller than return from lua_tonumber");
247 vb.vb_float64 = lua_tonumber(
L, -1);
252 vb.vb_int64 = lua_tointeger(
L, -1);
258 RPEDEBUG(
"Failed unmarshalling Lua number for \"%s\"", da->name);
270 p = (
char const *)lua_tolstring(
L, -1, &len);
272 REDEBUG(
"Unmarshalling failed, Lua bstring was NULL");
279 RPEDEBUG(
"Failed unmarshalling Lua string for \"%s\"", da->name);
285 case LUA_TLIGHTUSERDATA:
291 len = lua_objlen(
L, -1);
293 REDEBUG(
"Unmarshalling failed, can't determine length of user data");
296 p = lua_touserdata(
L, -1);
298 REDEBUG(
"Unmarshalling failed, user data was NULL");
306 int type = lua_type(
L, -1);
307 REDEBUG(
"Unmarshalling failed, unsupported Lua type %s (%i)", lua_typename(
L,
type),
type);
324 if (pair_data->
idx > 1) {
327 RERROR(
"Attempt to set instance %d when only %d exist", pair_data->
idx,
count);
333 &pair_data->
parent->
vp->vp_group, pair_data->
da) < 0)
return -1;
357 if (!lua_isnumber(
L, -2)) {
358 RERROR(
"Attempt to %s attribute \"%s\" table.", lua_isnil(
L, -1) ?
"delete" :
"set value on", lua_tostring(
L, -2));
359 RWARN(
"Values should be manipulated using <list>['<attr>'][idx] = <value> where idx is the attribute instance (starting at 1)");
363 index = lua_tointeger(
L, -2);
365 RERROR(
"Invalid attribute index %ld", index);
369 pair_data = lua_touserdata(
L, lua_upvalueindex(1));
373 RERROR(
"Values cannot be assigned to structural attribute \"%s\"", da->name);
381 if (lua_isnil(
L, -1)) {
382 if (!pair_data->
parent->
vp)
return 0;
385 if (pair_data->
vp ==
vp) pair_data->
vp = NULL;
400 if (!
vp && (index > 1)) {
402 if (
count < (index - 1)) {
403 RERROR(
"Attempt to set instance %ld when only %d exist", index,
count);
410 RERROR(
"Failed to create attribute %s", da->name);
431 fr_assert(lua_isuserdata(
L, lua_upvalueindex(1)));
433 cursor = lua_touserdata(
L, lua_upvalueindex(1));
457 fr_assert(lua_isuserdata(
L, lua_upvalueindex(1)));
458 pair_data = lua_touserdata(
L, lua_upvalueindex(1));
463 REDEBUG(
"Failed allocating user data to hold cursor");
487 fr_assert(lua_isuserdata(
L, lua_upvalueindex(1)));
489 cursor = lua_touserdata(
L, lua_upvalueindex(1));
498 lua_pushstring(
L,
vp->
da->name);
509 lua_pushstring(
L, child->
da->name);
510 lua_rawseti(
L, -2, i++);
530 fr_assert(lua_isuserdata(
L, lua_upvalueindex(1)));
531 pair_data = lua_touserdata(
L, lua_upvalueindex(1));
532 if (!pair_data->
vp)
return 0;
536 REDEBUG(
"Failed allocating user data to hold cursor");
573 fr_assert(lua_isuserdata(
L, lua_upvalueindex(1)));
575 pair_data = (
fr_lua_pair_t *)lua_touserdata(
L, lua_upvalueindex(1));
577 if (lua_isnumber(
L, -1)) {
578 lua_Integer index = lua_tointeger(
L, -1);
581 RERROR(
"Invalid attribute index %ld", index);
587 if (index == 1 && pair_data->
vp) {
592 if (index == 1) pair_data->
vp =
vp;
614 char const *attr = lua_tostring(
L, -1);
617 RERROR(
"Failed retrieving field name from lua stack");
631 RERROR(
"Unknown or invalid attribute name \"%s\"", attr);
639 lua_getfield(
L, -1, attr);
654 lua_getglobal(
L,
"jit");
655 if (lua_isnil(
L, -1))
goto done;
669 lua_getglobal(
L,
"jit");
670 if (!lua_isnil(
L, -1)) {
671 lua_getfield(
L, -1,
"version");
673 lua_getglobal(
L,
"_VERSION");
676 if (lua_isnil(
L, -1) || !(version = lua_tostring(
L, -1))) {
677 return "unknown version";
700 if (
name == NULL)
return 0;
702 lua_getglobal(
L,
name);
707 type = lua_type(
L, -1);
713 ERROR(
"Function \"%s\" not found ",
name);
718 ERROR(
"Value found at index \"%s\" is not a function (is a %s)",
name, lua_typename(
L,
type));
741 char const *p = field, *q;
746 if (lua_isnil(
L, -1)) {
748 REMARKER(field, p - field,
"Field does not exist");
754 if ((
size_t) (q - p) >=
sizeof(
buff)) {
756 REDEBUG(
"Field name too long, expected < %zu, got %zu", q - p,
sizeof(
buff));
761 lua_getglobal(
L,
buff);
762 if (lua_isnil(
L, -1))
goto does_not_exist;
765 while ((q = strchr(p,
'.'))) {
766 if ((
size_t) (q - p) >=
sizeof(
buff))
goto too_long;
769 lua_getfield(
L, -1,
buff);
770 if (lua_isnil(
L, -1))
goto does_not_exist;
774 lua_getfield(
L, -1, p);
775 if (lua_isnil(
L, -1))
goto does_not_exist;
816 lua_setfield(
L, -2,
"pairs");
820 lua_pushlightuserdata(
L, pair_data);
822 lua_setfield(
L, -2,
"__index");
824 lua_pushlightuserdata(
L, pair_data);
826 lua_setfield(
L, -2,
"__newindex");
827 lua_setmetatable(
L, -2);
833 lua_getglobal(
L,
"fr");
834 luaL_checktype(
L, -1, LUA_TTABLE);
837 lua_pushstring(
L,
"request");
841 lua_pushstring(
L,
"reply");
845 lua_pushstring(
L,
"control");
849 lua_pushstring(
L,
"session-state");
878 if (!lua_isfunction(
L, -1)) {
879 int type = lua_type(
L, -1);
885 if (lua_pcall(
L, 0, 1, 0) != 0) {
886 char const *
msg = lua_tostring(
L, -1);
895 if (!lua_isnoneornil(
L, -1)) {
899 if (lua_isnumber(
L, -1)) {
900 rcode = lua_tointeger(
L, -1);
907 if (lua_isstring(
L, -1)) {
909 if ((
int)rcode != -1)
goto done;
912 ROPTIONAL(
RDEBUG2,
DEBUG2,
"Lua function %s() rcodeurned invalid rcode \"%s\"", funcname, lua_tostring(
L, -1));
930 RWDEBUG(
"You can't modify the table 'fr.rcode.{}' (read-only)");
937 char const *key = lua_tostring(
L, -1);
942 lua_pushinteger(
L, ret);
946 lua_pushfstring(
L,
"The fr.rcode.%s is not found", key);
956 lua_pushfstring(
L,
"The pairs(fr.rcode) is not available. Access directly! e.g: 'fr.rcode.reject'");
962 const luaL_Reg metatable[] = {
973 lua_getglobal(
L,
"fr");
974 luaL_checktype(
L, -1, LUA_TTABLE);
979 luaL_register(
L,
name, metatable);
980 lua_setmetatable(
L, -2);
981 lua_setfield(
L, -2,
name);
1000 L = luaL_newstate();
1002 ERROR(
"Failed initialising Lua state");
1011 if (luaL_loadfile(
L,
inst->module) != 0) {
1012 ERROR(
"Failed loading file: %s", lua_gettop(
L) ? lua_tostring(
L, -1) :
"Unknown error");
1021 if (lua_pcall(
L, 0, LUA_MULTRET, 0) != 0) {
1022 ERROR(
"Failed executing script: %s", lua_gettop(
L) ? lua_tostring(
L, -1) :
"Unknown error");
1036 DEBUG4(
"Initialised new LuaJIT interpreter %p",
L);
1039 DEBUG4(
"Initialised new Lua interpreter %p",
L);
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
#define L(_str)
Helper for initialising arrays of string literals.
#define SIZEOF_MEMBER(_t, _m)
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
static void * fr_dcursor_current(fr_dcursor_t *cursor)
Return the item the cursor current points to.
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.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
fr_dict_t const * fr_dict_internal(void)
#define ROPTIONAL(_l_request, _l_global, _fmt,...)
Use different logging functions depending on whether request is NULL or not.
#define REMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
#define RPEDEBUG(fmt,...)
#define RLM_LUA_STACK_RESET()
static int _lua_rcode_table_newindex(UNUSED lua_State *L)
static void _lua_fr_request_register(lua_State *L, request_t *request)
unlang_action_t fr_lua_run(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request, char const *funcname)
static int fr_lua_get_field(lua_State *L, request_t *request, char const *field)
Resolve a path string to a field value in Lua.
static int _lua_pair_setter(lua_State *L)
Set an instance of an attribute.
#define RLM_LUA_STACK_SET()
char const * fr_lua_version(lua_State *L)
static int fr_lua_marshall(request_t *request, lua_State *L, fr_pair_t const *vp)
Convert fr_pair_ts to Lua values.
static int fr_lua_unmarshall(TALLOC_CTX *ctx, fr_value_box_t *out_vb, request_t *request, lua_State *L, fr_dict_attr_t const *da)
Use Lua values to populate a fr_value_box_t.
static int _lua_list_iterator(lua_State *L)
Iterate over attributes in a list.
static int _lua_pair_iterator_init(lua_State *L)
Initiate an iterator to return all the values of a given attribute.
static int fr_lua_pair_parent_build(request_t *request, fr_lua_pair_t *pair_data)
Build parent structural pairs needed when a leaf node is set.
static void _lua_pair_init(lua_State *L, fr_pair_t *vp, fr_dict_attr_t const *da, unsigned int idx, fr_lua_pair_t *parent)
Initialise a table representing a pair.
fr_dict_attr_t const * da
static int _lua_list_iterator_init(lua_State *L)
Initialise a new structural iterator.
bool fr_lua_isjit(lua_State *L)
Check whether the Lua interpreter were actually linked to is LuaJIT.
int fr_lua_check_func(module_inst_ctx_t const *mctx, lua_State *L, char const *name)
Check if a given function was loaded into an index in the global table.
static int _lua_rcode_table_pairs(lua_State *L)
static int _lua_pair_iterator(lua_State *L)
Iterate over instances of a leaf attribute.
#define IN_RANGE_FLOAT_SIGNED(_x)
#define IN_RANGE_INTEGER_UNSIGNED(_x)
int fr_lua_init(lua_State **out, module_inst_ctx_t const *mctx)
Initialise a new Lua/LuaJIT interpreter.
static int _lua_rcode_table_index(lua_State *L)
struct fr_lua_pair_s fr_lua_pair_t
static int _lua_pair_accessor(lua_State *L)
Get an attribute or an instance of an attribute.
#define IN_RANGE_INTEGER_SIGNED(_x)
static void fr_lua_rcode_register(lua_State *L, char const *name)
Library function signatures for lua module.
int fr_lua_util_jit_log_register(lua_State *L)
Insert cdefs into the lua environment.
void fr_lua_util_set_mctx(module_ctx_t const *mctx)
Set the thread local instance.
request_t * fr_lua_util_get_request(void)
Get the thread local request.
void fr_lua_util_set_request(request_t *request)
Set the thread local request.
void fr_lua_util_fr_register(lua_State *L)
int fr_lua_util_log_register(lua_State *L)
Register utililiary functions in the lua environment.
lua_State * interpreter
Thread specific interpreter.
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_FLOAT32
Single precision floating point.
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_INT8
8 Bit signed integer.
@ FR_TYPE_ETHERNET
48 Bit Mac-Address.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_INT64
64 Bit signed integer.
@ FR_TYPE_INT16
16 Bit signed integer.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_COMBO_IP_PREFIX
IPv4 or IPv6 address prefix depending on length.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_INT32
32 Bit signed integer.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
@ FR_TYPE_IFID
Interface ID.
@ FR_TYPE_OCTETS
Raw octets.
@ FR_TYPE_FLOAT64
Double precision floating point.
void * thread
Thread specific instance data.
#define MODULE_CTX_FROM_INST(_mctx)
Wrapper to create a module_ctx_t as a compound literal from a module_inst_ctx_t.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for instantiation calls.
fr_pair_t * fr_pair_list_parent(fr_pair_list_t const *list)
Return a pointer to the parent pair which contains this list.
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.
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)
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.
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.
int fr_pair_delete(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list and free.
fr_table_num_sorted_t const rcode_table[]
#define RETURN_MODULE_RCODE(_rcode)
#define RETURN_MODULE_FAIL
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_OK
The module is OK, continue.
#define FR_SBUFF_OUT(_start, _len_or_end)
void * data
Module's instance data.
static char buff[sizeof("18446744073709551615")+3]
eap_aka_sim_process_conf_t * inst
fr_aka_sim_id_type_t type
size_t strlcpy(char *dst, char const *src, size_t siz)
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
#define talloc_get_type_abort_const
static int64_t fr_unix_time_to_sec(fr_unix_time_t delta)
#define fr_pair_dcursor_by_da_init(_cursor, _list, _da)
Initialise a cursor that will return only attributes matching the specified fr_dict_attr_t.
fr_pair_t * fr_pair_list_next(fr_pair_list_t const *list, fr_pair_t const *item))
Get the next item in a valuepair list after a specific entry.
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.
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
size_t fr_pair_list_num_elements(fr_pair_list_t const *list)
Get the length of a list of fr_pair_t.
#define fr_type_is_group(_x)
#define fr_type_is_structural(_x)
#define fr_type_is_leaf(_x)
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
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.
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.
int fr_value_box_memdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Copy a buffer to a fr_value_box_t.
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
static size_t char ** out