26 RCSID(
"$Id: 40c93863c0c8d0913633f4b1d04ab1f3a1c0881d $")
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)
59 #if PTRDIFF_MAX < INT64_MAX
60 #define IN_RANGE_INTEGER_SIGNED(_x) \
62 if ((((int64_t)(_x)) < PTRDIFF_MIN) || (((int64_t)(_x)) > PTRDIFF_MAX)) { \
63 REDEBUG("Value (%" PRId64 ") cannot be represented as Lua integer. Must be between %td-%td", \
64 (int64_t)(_x), (ptrdiff_t)PTRDIFF_MIN, (ptrdiff_t)PTRDIFF_MAX); \
69 #define IN_RANGE_INTEGER_UNSIGNED(_x) \
71 if (((uint64_t)(_x)) > PTRDIFF_MAX) { \
72 REDEBUG("Value (%" PRIu64 ") cannot be represented as Lua integer. Must be between 0-%td", \
73 (uint64_t)(_x), (ptrdiff_t)PTRDIFF_MAX); \
78 #define IN_RANGE_INTEGER_SIGNED(_x) \
82 #define IN_RANGE_INTEGER_UNSIGNED(_x) \
87 #define IN_RANGE_FLOAT_SIGNED(_x) \
89 if ((((double)(_x)) < DBL_MIN) || (((double)(_x)) > DBL_MAX)) { \
90 REDEBUG("Value (%f) cannot be represented as Lua number. Must be between %f-%f", \
91 (double)(_x), DBL_MIN, DBL_MAX); \
96 switch (
vp->vp_type) {
112 REDEBUG(
"Cannot convert %s to Lua type, insufficient buffer space",
117 lua_pushlstring(
L,
buff, (
size_t)slen);
122 lua_pushlstring(
L,
vp->vp_strvalue,
vp->vp_length);
126 lua_pushlstring(
L, (
char const *)
vp->vp_octets,
vp->vp_length);
130 lua_pushinteger(
L, (lua_Integer)(
vp->vp_bool ? 1 : 0));
134 lua_pushinteger(
L, (lua_Integer)
vp->vp_uint8);
138 lua_pushinteger(
L, (lua_Integer)
vp->vp_uint16);
142 lua_pushinteger(
L, (lua_Integer)
vp->vp_uint32);
147 lua_pushinteger(
L, (lua_Integer)
vp->vp_uint64);
151 lua_pushinteger(
L, (lua_Integer)
vp->vp_int8);
155 lua_pushinteger(
L, (lua_Integer)
vp->vp_int16);
159 lua_pushinteger(
L, (lua_Integer)
vp->vp_int32);
164 lua_pushinteger(
L, (lua_Integer)
vp->vp_int64);
173 lua_pushnumber(
L, (lua_Number)
vp->vp_float32);
178 lua_pushnumber(
L, (lua_Number)
vp->vp_float64);
183 lua_pushinteger(
L, (lua_Integer)
vp->vp_size);
215 switch (lua_type(
L, -1)) {
226 "fr_value_box_t field smaller than return from lua_tointeger");
229 "fr_value_box_t field smaller than return from lua_tonumber");
231 switch (
vp->vp_type) {
241 vb.vb_float64 = lua_tonumber(
L, -1);
246 vb.vb_int64 = lua_tointeger(
L, -1);
252 RPEDEBUG(
"Failed unmarshalling Lua number for \"%s\"",
vp->
da->name);
264 p = (
char const *)lua_tolstring(
L, -1, &len);
266 REDEBUG(
"Unmarshalling failed, Lua bstring was NULL");
273 RPEDEBUG(
"Failed unmarshalling Lua string for \"%s\"",
vp->
da->name);
279 case LUA_TLIGHTUSERDATA:
285 len = lua_objlen(
L, -1);
287 REDEBUG(
"Unmarshalling failed, can't determine length of user data");
290 p = lua_touserdata(
L, -1);
292 REDEBUG(
"Unmarshalling failed, user data was NULL");
300 int type = lua_type(
L, -1);
301 REDEBUG(
"Unmarshalling failed, unsupported Lua type %s (%i)", lua_typename(
L,
type),
type);
332 fr_assert(lua_islightuserdata(
L, lua_upvalueindex(1)));
334 da = lua_touserdata(
L, lua_upvalueindex(1));
342 for (index = (
int) lua_tointeger(
L, -1); index >= 0; index--) {
379 fr_assert(lua_islightuserdata(
L, lua_upvalueindex(1)));
381 da = lua_touserdata(
L, lua_upvalueindex(1));
384 delete = lua_isnil(
L, -1);
391 for (index = lua_tointeger(
L, -2); index >= 0; index--) {
432 fr_assert(lua_isuserdata(
L, lua_upvalueindex(1)));
434 cursor = lua_touserdata(
L, lua_upvalueindex(1));
461 fr_assert(lua_isuserdata(
L, lua_upvalueindex(2)));
463 da = lua_touserdata(
L, lua_upvalueindex(2));
468 REDEBUG(
"Failed allocating user data to hold cursor");
485 fr_assert(lua_isuserdata(
L, lua_upvalueindex(1)));
487 cursor = lua_touserdata(
L, lua_upvalueindex(1));
500 lua_pushstring(
L,
vp->
da->name);
519 REDEBUG(
"Failed allocating user data to hold cursor");
524 lua_pushlightuserdata(
L, cursor);
541 attr = lua_tostring(
L, -1);
543 REDEBUG(
"Failed retrieving field name from lua stack");
549 REDEBUG(
"Unknown or invalid attribute name \"%s\"", attr);
562 lua_pushlightuserdata(
L, &request->request_pairs);
563 lua_pushlightuserdata(
L, up);
565 lua_setfield(
L, -2,
"pairs");
571 lua_pushlightuserdata(
L, up);
573 lua_setfield(
L, -2,
"__index");
575 lua_pushlightuserdata(
L, up);
577 lua_setfield(
L, -2,
"__newindex");
579 lua_setmetatable(
L, -2);
581 lua_getfield(
L, -1, attr);
595 lua_getglobal(
L,
"jit");
596 if (lua_isnil(
L, -1))
goto done;
610 lua_getglobal(
L,
"jit");
611 if (!lua_isnil(
L, -1)) {
612 lua_getfield(
L, -1,
"version");
614 lua_getglobal(
L,
"_VERSION");
617 if (lua_isnil(
L, -1) || !(version = lua_tostring(
L, -1))) {
618 return "unknown version";
641 if (
name == NULL)
return 0;
643 lua_getglobal(
L,
name);
648 type = lua_type(
L, -1);
654 ERROR(
"Function \"%s\" not found ",
name);
659 ERROR(
"Value found at index \"%s\" is not a function (is a %s)",
name, lua_typename(
L,
type));
682 char const *p = field, *q;
687 if (lua_isnil(
L, -1)) {
689 REMARKER(field, p - field,
"Field does not exist");
695 if ((
size_t) (q - p) >=
sizeof(
buff)) {
697 REDEBUG(
"Field name too long, expected < %zu, got %zu", q - p,
sizeof(
buff));
702 lua_getglobal(
L,
buff);
703 if (lua_isnil(
L, -1))
goto does_not_exist;
706 while ((q = strchr(p,
'.'))) {
707 if ((
size_t) (q - p) >=
sizeof(
buff))
goto too_long;
710 lua_getfield(
L, -1,
buff);
711 if (lua_isnil(
L, -1))
goto does_not_exist;
715 lua_getfield(
L, -1, p);
716 if (lua_isnil(
L, -1))
goto does_not_exist;
724 lua_getglobal(
L,
"fr");
725 luaL_checktype(
L, -1, LUA_TTABLE);
740 lua_pushlightuserdata(
L, &cursor);
742 lua_setfield(
L, -2,
"pairs");
747 lua_setfield(
L, -2,
"__index");
748 lua_setmetatable(
L, -2);
751 lua_setfield(
L, -2,
"request");
778 if (!lua_isfunction(
L, -1)) {
779 int type = lua_type(
L, -1);
785 if (lua_pcall(
L, 0, 1, 0) != 0) {
786 char const *
msg = lua_tostring(
L, -1);
795 if (!lua_isnoneornil(
L, -1)) {
799 if (lua_isnumber(
L, -1)) {
800 rcode = lua_tointeger(
L, -1);
807 if (lua_isstring(
L, -1)) {
809 if ((
int)rcode != -1)
goto done;
812 ROPTIONAL(
RDEBUG2,
DEBUG2,
"Lua function %s() rcodeurned invalid rcode \"%s\"", funcname, lua_tostring(
L, -1));
830 RWDEBUG(
"You can't modify the table 'fr.rcode.{}' (read-only)");
837 char const *key = lua_tostring(
L, -1);
842 lua_pushinteger(
L, ret);
846 lua_pushfstring(
L,
"The fr.rcode.%s is not found", key);
856 lua_pushfstring(
L,
"The pairs(fr.rcode) is not available. Access directly! e.g: 'fr.rcode.reject'");
862 const luaL_Reg metatable[] = {
873 lua_getglobal(
L,
"fr");
874 luaL_checktype(
L, -1, LUA_TTABLE);
879 luaL_register(
L,
name, metatable);
880 lua_setmetatable(
L, -2);
881 lua_setfield(
L, -2,
name);
902 ERROR(
"Failed initialising Lua state");
911 if (luaL_loadfile(
L,
inst->module) != 0) {
912 ERROR(
"Failed loading file: %s", lua_gettop(
L) ? lua_tostring(
L, -1) :
"Unknown error");
921 if (lua_pcall(
L, 0, LUA_MULTRET, 0) != 0) {
922 ERROR(
"Failed executing script: %s", lua_gettop(
L) ? lua_tostring(
L, -1) :
"Unknown error");
936 DEBUG4(
"Initialised new LuaJIT interpreter %p",
L);
939 DEBUG4(
"Initialised new Lua interpreter %p",
L);
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define L(_str)
Helper for initialising arrays of string literals.
#define static_assert
For systems with an old version libc, define static_assert.
#define SIZEOF_MEMBER(_t, _m)
static void * fr_dcursor_remove(fr_dcursor_t *cursor)
Remove the current item.
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
static void * fr_dcursor_replace(fr_dcursor_t *cursor, void *r)
Replace the current 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.
#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_set(lua_State *L)
Set an instance of an attribute.
#define RLM_LUA_STACK_SET()
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_pair_t **out, UNUSED rlm_lua_t const *inst, request_t *request, lua_State *L, fr_dict_attr_t const *da)
Convert Lua values to fr_pair_ts.
static int _lua_list_iterator(lua_State *L)
static int _lua_pair_iterator_init(lua_State *L)
char const * fr_lua_version(lua_State *L)
static int _lua_list_iterator_init(lua_State *L)
Initialise a new top level list iterator.
bool fr_lua_isjit(lua_State *L)
Check whether the Lua interpreter were actually linked to is LuaJIT.
static int _lua_pair_get(lua_State *L)
Get an instance of an attribute.
static int _lua_rcode_table_pairs(lua_State *L)
static int _lua_pair_iterator(lua_State *L)
#define IN_RANGE_FLOAT_SIGNED(_x)
#define IN_RANGE_INTEGER_UNSIGNED(_x)
static 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.
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)
static int _lua_pair_accessor_init(lua_State *L)
Initialise and return a new accessor table.
#define IN_RANGE_INTEGER_SIGNED(_x)
static void fr_lua_rcode_register(lua_State *L, char const *name)
Library function signatures for lua module.
module_ctx_t const * fr_lua_util_get_mctx(void)
Get the thread local instance.
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.
void fr_lua_util_set_request(request_t *request)
Set the thread local request.
void fr_lua_util_fr_register(lua_State *L)
request_t * fr_lua_util_get_request(void)
Get the thread local request.
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.
module_instance_t const * mi
Instance of the module being instantiated.
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_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
int fr_pair_value_memdup(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Copy data into an "octets" data type.
int8_t fr_pair_cmp_by_da(void const *a, void const *b)
Order attributes by their da, and tag.
fr_table_num_sorted_t const rcode_table[]
#define RETURN_MODULE_RCODE(_rcode)
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_OK
The module is OK, continue.
fr_dict_attr_t const * request_attr_request
#define FR_SBUFF_OUT(_start, _len_or_end)
void * data
Module's instance data.
static char buff[sizeof("18446744073709551615")+3]
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
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.
void fr_pair_list_sort(fr_pair_list_t *list, fr_cmp_t cmp)
Sort a doubly linked list of fr_pair_ts using merge sort.
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.
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
#define fr_type_is_structural(_x)
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.
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
static size_t char ** out