The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
lua.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, version 2 if the
4 * License as published by the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
14 */
15
16/**
17 * $Id: 512484de8948670daf8972da4476ce30b25aab4c $
18 * @file lua.c
19 * @brief Library functions for the lua module.
20 *
21 * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org)
22 * @author Artur Malinowski (artur@wow.com)
23 *
24 * @copyright 2015 The FreeRADIUS Server Project.
25 */
26RCSID("$Id: 512484de8948670daf8972da4476ce30b25aab4c $")
27
28#define LOG_PREFIX mctx->mi->name
29
30#include <freeradius-devel/server/base.h>
31#include <freeradius-devel/util/debug.h>
32
33#include "config.h"
34#include "lua.h"
35
36#include <float.h>
37#include <lauxlib.h>
38#include <lualib.h>
39
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)
42
50
51static 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);
52
53DIAG_OFF(type-limits)
54/** Convert fr_pair_ts to Lua values
55 *
56 * Pushes a Lua representation of an attribute value onto the stack.
57 *
58 * @param[in] request The current request.
59 * @param[in] L Lua interpreter.
60 * @param[in] vp to convert.
61 * @return
62 * - 0 on success.
63 * - -1 on failure.
64 */
65static int fr_lua_marshall(request_t *request, lua_State *L, fr_pair_t const *vp)
66{
67 if (!vp) return -1;
68
69#if PTRDIFF_MAX < INT64_MAX
70#define IN_RANGE_INTEGER_SIGNED(_x) \
71 do { \
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); \
75 return -1; \
76 } \
77 } while (0)
78
79#define IN_RANGE_INTEGER_UNSIGNED(_x) \
80 do { \
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); \
84 return -1; \
85 } \
86 } while (0)
87#else
88#define IN_RANGE_INTEGER_SIGNED(_x) \
89 do { \
90 } while (0)
91
92#define IN_RANGE_INTEGER_UNSIGNED(_x) \
93 do { \
94 } while (0)
95#endif
96
97#define IN_RANGE_FLOAT_SIGNED(_x) \
98 do { \
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); \
102 return -1; \
103 } \
104 } while (0)
105
106 switch (vp->vp_type) {
107 case FR_TYPE_ETHERNET:
114 case FR_TYPE_IFID:
116 {
117 char buff[128];
118 ssize_t slen;
119
121 if (slen < 0) {
122 REDEBUG("Cannot convert %s to Lua type, insufficient buffer space",
123 fr_type_to_str(vp->vp_type));
124 return -1;
125 }
126
127 lua_pushlstring(L, buff, (size_t)slen);
128 }
129 break;
130
131 case FR_TYPE_STRING:
132 lua_pushlstring(L, vp->vp_strvalue, vp->vp_length);
133 break;
134
135 case FR_TYPE_OCTETS:
136 lua_pushlstring(L, (char const *)vp->vp_octets, vp->vp_length); /* lstring variant is embedded NULL safe */
137 break;
138
139 case FR_TYPE_BOOL:
140 lua_pushinteger(L, (lua_Integer)(vp->vp_bool ? 1 : 0));
141 break;
142
143 case FR_TYPE_UINT8:
144 lua_pushinteger(L, (lua_Integer)vp->vp_uint8);
145 break;
146
147 case FR_TYPE_UINT16:
148 lua_pushinteger(L, (lua_Integer)vp->vp_uint16);
149 break;
150
151 case FR_TYPE_UINT32:
152 lua_pushinteger(L, (lua_Integer)vp->vp_uint32);
153 break;
154
155 case FR_TYPE_UINT64:
156 IN_RANGE_INTEGER_UNSIGNED(vp->vp_uint64);
157 lua_pushinteger(L, (lua_Integer)vp->vp_uint64);
158 break;
159
160 case FR_TYPE_INT8:
161 lua_pushinteger(L, (lua_Integer)vp->vp_int8);
162 break;
163
164 case FR_TYPE_INT16:
165 lua_pushinteger(L, (lua_Integer)vp->vp_int16);
166 break;
167
168 case FR_TYPE_INT32:
169 lua_pushinteger(L, (lua_Integer)vp->vp_int32);
170 break;
171
172 case FR_TYPE_INT64:
173 IN_RANGE_INTEGER_SIGNED(vp->vp_int64);
174 lua_pushinteger(L, (lua_Integer)vp->vp_int64);
175 break;
176
177 case FR_TYPE_DATE:
178 lua_pushinteger(L, (lua_Integer) fr_unix_time_to_sec(vp->vp_date));
179 break;
180
181 case FR_TYPE_FLOAT32:
182 IN_RANGE_FLOAT_SIGNED(vp->vp_float32);
183 lua_pushnumber(L, (lua_Number)vp->vp_float32);
184 break;
185
186 case FR_TYPE_FLOAT64:
187 IN_RANGE_FLOAT_SIGNED(vp->vp_float64);
188 lua_pushnumber(L, (lua_Number)vp->vp_float64);
189 break;
190
191 case FR_TYPE_SIZE:
193 lua_pushinteger(L, (lua_Integer)vp->vp_size);
194 break;
195
196 case FR_TYPE_NON_LEAF:
197 REDEBUG("Cannot convert %s to Lua type", fr_type_to_str(vp->vp_type));
198 return -1;
199 }
200 return 0;
201}
202DIAG_ON(type-limits)
203
204/** Use Lua values to populate a fr_value_box_t
205 *
206 * Convert Lua values to fr_value_box_t. How the Lua value is converted is dependent
207 * on the type of the box.
208 *
209 * @param[in] ctx To allocate new fr_pair_t in.
210 * @param[out] out_vb Value box to populate.
211 * @param[in] request the current request.
212 * @param[in] L Lua interpreter.
213 * @param[in] da specifying the type of attribute the box represent.
214 * @return
215 * - 0 on success.
216 * - -1 on failure.
217 */
218static int fr_lua_unmarshall(TALLOC_CTX *ctx, fr_value_box_t *out_vb, request_t *request,
219 lua_State *L, fr_dict_attr_t const *da)
220{
221 switch (lua_type(L, -1)) {
222 case LUA_TNUMBER:
223 {
225
226 /*
227 * lua_tonumber actually returns ptrdiff_t
228 * so we need to check if our input box
229 * type is the same width or greater.
230 */
231 static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_int64) >= sizeof(ptrdiff_t),
232 "fr_value_box_t field smaller than return from lua_tointeger");
233
234 static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_float64) >= sizeof(double),
235 "fr_value_box_t field smaller than return from lua_tonumber");
236
237 switch (da->type) {
238 /*
239 * Preserve decimal precision.
240 *
241 * Our FR_TYPE_FLOAT64 is a double, which is apparently
242 * what lua_tonumber returns on most platforms.
243 */
244 case FR_TYPE_FLOAT32:
245 case FR_TYPE_FLOAT64:
246 fr_value_box_init(&vb, FR_TYPE_FLOAT64, NULL, true);
247 vb.vb_float64 = lua_tonumber(L, -1);
248 break;
249
250 default:
251 fr_value_box_init(&vb, FR_TYPE_INT64, NULL, true);
252 vb.vb_int64 = lua_tointeger(L, -1);
253 break;
254 }
255
256
257 if (fr_value_box_cast(ctx, out_vb, da->type, da, &vb) < 0) {
258 RPEDEBUG("Failed unmarshalling Lua number for \"%s\"", da->name);
259 return -1;
260 }
261 }
262 break;
263
264 case LUA_TSTRING:
265 {
267 char const *p;
268 size_t len;
269
270 p = (char const *)lua_tolstring(L, -1, &len);
271 if (!p) {
272 REDEBUG("Unmarshalling failed, Lua bstring was NULL");
273 return -1;
274 }
275
276 fr_value_box_bstrndup_shallow(&vb, NULL, p, len, true);
277
278 if (fr_value_box_cast(ctx, out_vb, da->type, da, &vb) < 0) {
279 RPEDEBUG("Failed unmarshalling Lua string for \"%s\"", da->name);
280 return -1;
281 }
282 }
283 break;
284
285 case LUA_TLIGHTUSERDATA:
286 case LUA_TUSERDATA:
287 {
288 size_t len;
289 uint8_t *p;
290
291 len = lua_objlen(L, -1);
292 if (len == 0) {
293 REDEBUG("Unmarshalling failed, can't determine length of user data");
294 return -1;
295 }
296 p = lua_touserdata(L, -1);
297 if (!p) {
298 REDEBUG("Unmarshalling failed, user data was NULL");
299 }
300 fr_value_box_memdup(ctx, out_vb, da, p, len, true);
301 }
302 break;
303
304 default:
305 {
306 int type = lua_type(L, -1);
307 REDEBUG("Unmarshalling failed, unsupported Lua type %s (%i)", lua_typename(L, type), type);
308
309 return -1;
310 }
311 }
312
313 return 0;
314}
315
316/** Build parent structural pairs needed when a leaf node is set
317 *
318 */
319static int fr_lua_pair_parent_build(request_t *request, fr_lua_pair_t *pair_data)
320{
321 if (!pair_data->parent->vp) {
322 if (fr_lua_pair_parent_build(request, pair_data->parent) < 0) return -1;
323 }
324 if (pair_data->idx > 1) {
325 unsigned int count = fr_pair_count_by_da(&pair_data->parent->vp->vp_group, pair_data->da);
326 if (count < (pair_data->idx - 1)) {
327 RERROR("Attempt to set instance %d when only %d exist", pair_data->idx, count);
328 return -1;
329 }
330 }
331
332 if (fr_pair_append_by_da(pair_data->parent->vp, &pair_data->vp,
333 &pair_data->parent->vp->vp_group, pair_data->da) < 0) return -1;
334 return 0;
335}
336
337/** Set an instance of an attribute
338 *
339 * @note Should only be present in the Lua environment as a closure.
340 * @note Takes one upvalue - the fr_lua_pair_t representing this pair as user data.
341 * @note Is called as an __newindex metamethod, so takes the table (can be ignored),
342 * the field (an integer index value) and the new value.
343 *
344 * @param[in] L Lua state.
345 * @return
346 * - 0 on success.
347 * - -1 on failure.
348 */
349static int _lua_pair_setter(lua_State *L)
350{
352 fr_lua_pair_t *pair_data, *parent;
353 fr_dict_attr_t const *da;
354 fr_pair_t *vp;
355 lua_Integer index;
356
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)");
360 return -1;
361 }
362
363 index = lua_tointeger(L, -2);
364 if (index < 1) {
365 RERROR("Invalid attribute index %ld", index);
366 return -1;
367 }
368
369 pair_data = lua_touserdata(L, lua_upvalueindex(1));
370 da = pair_data->da;
371
372 if (!fr_type_is_leaf(da->type)) {
373 RERROR("Values cannot be assigned to structural attribute \"%s\"", da->name);
374 return -1;
375 }
376 parent = pair_data->parent;
377
378 /*
379 * If the value of the Lua stack was nil, we delete the attribute if it exists.
380 */
381 if (lua_isnil(L, -1)) {
382 if (!pair_data->parent->vp) return 0;
383 vp = fr_pair_find_by_da_idx(&parent->vp->vp_group, da, index - 1);
384 if (!vp) return 0;
385 if (pair_data->vp == vp) pair_data->vp = NULL;
386 fr_pair_delete(&parent->vp->vp_group, vp);
387 return 0;
388 }
389
390 if (!parent->vp) {
391 if (fr_lua_pair_parent_build(request, parent) < 0) return -1;
392 }
393
394 vp = fr_pair_find_by_da_idx(&parent->vp->vp_group, da, index - 1);
395
396 /*
397 * Asked to add a pair we don't have - check we're not being asked
398 * to add a gap.
399 */
400 if (!vp && (index > 1)) {
401 unsigned int count = fr_pair_count_by_da(&parent->vp->vp_group, da);
402 if (count < (index - 1)) {
403 RERROR("Attempt to set instance %ld when only %d exist", index, count);
404 return -1;
405 }
406 }
407
408 if (!vp) {
409 if (fr_pair_append_by_da(parent->vp, &vp, &parent->vp->vp_group, da) < 0) {
410 RERROR("Failed to create attribute %s", da->name);
411 return -1;
412 }
413 }
414 if (fr_lua_unmarshall(vp, &vp->data, request, L, da) < 0) return -1;
415
416 return 0;
417}
418
419/** Iterate over instances of a leaf attribute
420 *
421 * Each call returns with the value of the next instance of the attribute
422 * on the Lua stack, or nil, when there are no more instances.
423 *
424 */
425static int _lua_pair_iterator(lua_State *L)
426{
428 fr_dcursor_t *cursor;
429 fr_pair_t *vp;
430
431 fr_assert(lua_isuserdata(L, lua_upvalueindex(1)));
432
433 cursor = lua_touserdata(L, lua_upvalueindex(1));
434 fr_assert(cursor);
435
436 vp = fr_dcursor_current(cursor);
437 if (!vp) {
438 lua_pushnil(L);
439 return 1;
440 }
441
442 if (fr_lua_marshall(request, L, vp) < 0) return -1;
443
444 fr_dcursor_next(cursor);
445 return 1;
446}
447
448/** Initiate an iterator to return all the values of a given attribute
449 *
450 */
451static int _lua_pair_iterator_init(lua_State *L)
452{
454 fr_dcursor_t *cursor;
455 fr_lua_pair_t *pair_data;
456
457 fr_assert(lua_isuserdata(L, lua_upvalueindex(1)));
458 pair_data = lua_touserdata(L, lua_upvalueindex(1));
459 fr_assert(pair_data);
460
461 cursor = (fr_dcursor_t*) lua_newuserdata(L, sizeof(fr_dcursor_t));
462 if (!cursor) {
463 REDEBUG("Failed allocating user data to hold cursor");
464 return -1;
465 }
466 fr_pair_dcursor_by_da_init(cursor, &pair_data->parent->vp->vp_group, pair_data->da);
467
468 lua_pushcclosure(L, _lua_pair_iterator, 1);
469
470 return 1;
471}
472
473/** Iterate over attributes in a list
474 *
475 * Each call returns with two values on the Lua stack
476 * - the name of the next attribute
477 * - the value of the next attribute, or an array of child attribute names
478 *
479 * or, nil is pushed to the stack when there are no more attributes in the list.
480 */
481static int _lua_list_iterator(lua_State *L)
482{
484 fr_dcursor_t *cursor;
485 fr_pair_t *vp;
486
487 fr_assert(lua_isuserdata(L, lua_upvalueindex(1)));
488
489 cursor = lua_touserdata(L, lua_upvalueindex(1));
490 fr_assert(cursor);
491
492 vp = fr_dcursor_current(cursor);
493 if(!vp) {
494 lua_pushnil(L);
495 return 1;
496 }
497
498 lua_pushstring(L, vp->da->name);
499
500 /*
501 * For structural attributes return an array of the child names
502 */
503 if (fr_type_is_structural(vp->da->type)) {
504 fr_pair_t *child = NULL;
505 unsigned int i = 1;
506
507 lua_createtable(L, fr_pair_list_num_elements(&vp->vp_group), 0);
508 while ((child = fr_pair_list_next(&vp->vp_group, child))) {
509 lua_pushstring(L, child->da->name);
510 lua_rawseti(L, -2, i++);
511 }
512 } else {
513 if (fr_lua_marshall(request, L, vp) < 0) return -1;
514 }
515
516 fr_dcursor_next(cursor);
517
518 return 2;
519}
520
521/** Initialise a new structural iterator
522 *
523 */
524static int _lua_list_iterator_init(lua_State *L)
525{
527 fr_dcursor_t *cursor;
528 fr_lua_pair_t *pair_data;
529
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;
533
534 cursor = (fr_dcursor_t*) lua_newuserdata(L, sizeof(fr_dcursor_t));
535 if (!cursor) {
536 REDEBUG("Failed allocating user data to hold cursor");
537 return -1;
538 }
539 fr_pair_dcursor_init(cursor, &pair_data->vp->vp_group);
540
541 lua_pushcclosure(L, _lua_list_iterator, 1);
542
543 return 1;
544}
545
546/** Get an attribute or an instance of an attribute
547 *
548 * When called with a numeric index, it is the instance of the attribute
549 * which is being requested.
550 * Otherwise, the index is an attribute name.
551 *
552 * @note Should only be present in the Lua environment as a closure.
553 * @note Takes one upvalue - the fr_lua_pair_t representing either this
554 * attribute in the case it is an index being requested, or the
555 * parent in the case an attribute is being requested.
556 * @note Is called as an __index metamethod, so takes the table (can be ignored)
557 * and the field (integer index for instance or string for attribute)
558 *
559 * @param[in] L Lua interpreter.
560 * @return
561 * - -1 on failure.
562 * - 0 (no results) on success.
563 * - 1 on success with:
564 * - the fr_pair_t value on the stack for leaf values.
565 * - a lua table for structural items.
566 */
567static int _lua_pair_accessor(lua_State *L)
568{
570 fr_lua_pair_t *pair_data;
571 fr_pair_t *vp = NULL;
572
573 fr_assert(lua_isuserdata(L, lua_upvalueindex(1)));
574
575 pair_data = (fr_lua_pair_t *)lua_touserdata(L, lua_upvalueindex(1));
576
577 if (lua_isnumber(L, -1)) {
578 lua_Integer index = lua_tointeger(L, -1);
579
580 if (index < 1) {
581 RERROR("Invalid attribute index %ld", index);
582 return -1;
583 }
584
585 if (!pair_data->parent || !pair_data->parent->vp) return 0;
586
587 if (index == 1 && pair_data->vp) {
588 vp = pair_data->vp;
589 } else {
590 // Lua array indexes are 1 based, not 0 based.
591 vp = fr_pair_find_by_da_idx(&pair_data->parent->vp->vp_group, pair_data->da, index - 1);
592 if (index == 1) pair_data->vp = vp;
593 }
594 /*
595 * Retrieving an instance of a leaf gives the actual attribute
596 * value (if it exists)
597 */
598 if (fr_type_is_leaf(pair_data->da->type)) {
599 if (!vp) return 0;
600 if (fr_lua_marshall(request, L, vp) < 0) return -1;
601 return 1;
602 }
603
604 fr_assert(fr_type_is_structural(pair_data->da->type));
605
606 /*
607 * Retrieving a structural attribute returns a new table.
608 */
609 lua_newtable(L);
610 _lua_pair_init(L, vp, pair_data->da, index, pair_data->parent);
611
612 } else {
613 fr_dict_attr_t const *da;
614 char const *attr = lua_tostring(L, -1);
615
616 if (!attr) {
617 RERROR("Failed retrieving field name from lua stack");
618 return -1;
619 }
620
621 da = fr_dict_attr_by_name(NULL, pair_data->da, attr);
622
623 /*
624 * Allow fallback to internal attributes if the parent is a group or dictionary root.
625 */
626 if (!da && (fr_type_is_group(pair_data->da->type) || pair_data->da->flags.is_root)) {
628 }
629
630 if (!da) {
631 RERROR("Unknown or invalid attribute name \"%s\"", attr);
632 return -1;
633 }
634
635 if (pair_data->vp) vp = fr_pair_find_by_da(&pair_data->vp->vp_group, NULL, da);
636 _lua_pair_init(L, vp, da, 1, pair_data);
637
638 lua_rawset(L, -3); /* Cache the attribute manipulation object */
639 lua_getfield(L, -1, attr); /* and return it */
640 }
641
642 return 1;
643}
644
645/** Check whether the Lua interpreter were actually linked to is LuaJIT
646 *
647 * @param L Lua interpreter.
648 * @return true if were running with LuaJIT else false.
649 */
650bool fr_lua_isjit(lua_State *L)
651{
652 bool ret = false;
654 lua_getglobal(L, "jit");
655 if (lua_isnil(L, -1)) goto done;
656
657 ret = true;
658done:
660
661 return ret;
662}
663
664char const *fr_lua_version(lua_State *L)
665{
666 char const *version;
667
669 lua_getglobal(L, "jit");
670 if (!lua_isnil(L, -1)) {
671 lua_getfield(L, -1, "version"); /* Version field in jit table */
672 } else {
673 lua_getglobal(L, "_VERSION"); /* Version global */
674 }
675
676 if (lua_isnil(L, -1) || !(version = lua_tostring(L, -1))) {
677 return "unknown version";
678 }
680
681 return version;
682}
683
684/** Check if a given function was loaded into an index in the global table
685 *
686 * Also check what was loaded there is a function and that it accepts the correct arguments.
687 *
688 * @param[in] mctx module instantiation data.
689 * @param[in] L the lua state.
690 * @param[in] name of function to check.
691 * @returns 0 on success (function is present and correct), or -1 on failure.
692 */
693int fr_lua_check_func(module_inst_ctx_t const *mctx, lua_State *L, char const *name)
694{
695 int ret;
696 int type;
697
699
700 if (name == NULL) return 0;
701
702 lua_getglobal(L, name);
703
704 /*
705 * Check the global is a function.
706 */
707 type = lua_type(L, -1);
708 switch (type) {
709 case LUA_TFUNCTION:
710 break;
711
712 case LUA_TNIL:
713 ERROR("Function \"%s\" not found ", name);
714 ret = -1;
715 goto done;
716
717 default:
718 ERROR("Value found at index \"%s\" is not a function (is a %s)", name, lua_typename(L, type));
719 ret = -1;
720 goto done;
721 }
722 ret = 0;
723done:
725 return ret;
726}
727
728/** Resolve a path string to a field value in Lua
729 *
730 * Parses a string in the format
731 * @verbatim obj0[.obj1][.objN] @endverbatim, adding all tables it traverses
732 * to the stack.
733 *
734 * All paths are assumed to start at a global, so the first field
735 * will be looked up in the global table.
736 *
737 */
738static int fr_lua_get_field(lua_State *L, request_t *request, char const *field)
739{
740 char buff[512];
741 char const *p = field, *q;
742
743 q = strchr(p, '.');
744 if (!q) { /* No field, just global */
745 lua_getglobal(L, p);
746 if (lua_isnil(L, -1)) {
747 does_not_exist:
748 REMARKER(field, p - field, "Field does not exist");
749 return -1;
750 }
751 return 0;
752 }
753
754 if ((size_t) (q - p) >= sizeof(buff)) {
755 too_long:
756 REDEBUG("Field name too long, expected < %zu, got %zu", q - p, sizeof(buff));
757 return -1;
758 }
759
760 strlcpy(buff, p, (q - p) + 1);
761 lua_getglobal(L, buff);
762 if (lua_isnil(L, -1)) goto does_not_exist;
763 p = q + 1; /* Skip the '.' */
764
765 while ((q = strchr(p, '.'))) {
766 if ((size_t) (q - p) >= sizeof(buff)) goto too_long;
767
768 strlcpy(buff, p, (q - p) + 1);
769 lua_getfield(L, -1, buff);
770 if (lua_isnil(L, -1)) goto does_not_exist;
771 p = q + 1;
772 }
773
774 lua_getfield(L, -1, p);
775 if (lua_isnil(L, -1)) goto does_not_exist;
776
777 return 0;
778}
779
780/** Initialise a table representing a pair
781 *
782 * After calling this function, a new table will be on the lua stack which represents the pair.
783 *
784 * The pair may not exist - e.g. when setting a new nested attribute, parent pairs may not
785 * have been created yet. In that case, this holds the da and index of the instance which
786 * will be created when the leaf is assigned a value.
787 *
788 * @param[in] L the lua state
789 * @param[in] vp the actual pair instance being represented, if it already exists
790 * @param[in] da dictionary attribute for this pair
791 * @param[in] idx index of the attribute instance (starting at 1)
792 * @param[in] parent lua userdata for the parent of this attribute.
793 */
794static 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)
795{
796 fr_lua_pair_t *pair_data;
797
798 lua_newtable(L);
799
800 /*
801 * The userdata associated with the meta functions
802 * __index and __newindex, and the .pairs() field.
803 */
804 pair_data = lua_newuserdata(L, sizeof(fr_lua_pair_t));
805 *pair_data = (fr_lua_pair_t) {
806 .da = da,
807 .idx = idx,
808 .vp = vp,
809 .parent = parent
810 };
811 if (fr_type_is_structural(da->type)) {
812 lua_pushcclosure(L, _lua_list_iterator_init, 1);
813 } else {
814 lua_pushcclosure(L, _lua_pair_iterator_init, 1);
815 }
816 lua_setfield(L, -2, "pairs");
817
818 lua_newtable(L); /* Metatable for index functions*/
819
820 lua_pushlightuserdata(L, pair_data);
821 lua_pushcclosure(L, _lua_pair_accessor, 1);
822 lua_setfield(L, -2, "__index");
823
824 lua_pushlightuserdata(L, pair_data);
825 lua_pushcclosure(L, _lua_pair_setter, 1);
826 lua_setfield(L, -2, "__newindex");
827 lua_setmetatable(L, -2);
828}
829
830static void _lua_fr_request_register(lua_State *L, request_t *request)
831{
832 /* fr = {} */
833 lua_getglobal(L, "fr");
834 luaL_checktype(L, -1, LUA_TTABLE);
835
836 /* fr = { request {} } */
837 lua_pushstring(L, "request");
838 _lua_pair_init(L, fr_pair_list_parent(&request->request_pairs), fr_dict_root(request->proto_dict), 1, NULL);
839 lua_rawset(L, -3);
840
841 lua_pushstring(L, "reply");
842 _lua_pair_init(L, fr_pair_list_parent(&request->reply_pairs), fr_dict_root(request->proto_dict), 1, NULL);
843 lua_rawset(L, -3);
844
845 lua_pushstring(L, "control");
846 _lua_pair_init(L, fr_pair_list_parent(&request->control_pairs), fr_dict_root(request->proto_dict), 1, NULL);
847 lua_rawset(L, -3);
848
849 lua_pushstring(L, "session-state");
850 _lua_pair_init(L, fr_pair_list_parent(&request->session_state_pairs), fr_dict_root(request->proto_dict), 1, NULL);
851 lua_rawset(L, -3);
852}
853
854unlang_action_t fr_lua_run(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request, char const *funcname)
855{
856 rlm_lua_thread_t *thread = talloc_get_type_abort(mctx->thread, rlm_lua_thread_t);
857 lua_State *L = thread->interpreter;
859
862
863 ROPTIONAL(RDEBUG2, DEBUG2, "Calling %s() in interpreter %p", funcname, L);
864
865 if (request) _lua_fr_request_register(L, request);
866
867 /*
868 * Get the function were going to be calling
869 */
870 if (fr_lua_get_field(L, request, funcname) < 0) {
871error:
874
876 }
877
878 if (!lua_isfunction(L, -1)) {
879 int type = lua_type(L, -1);
880
881 ROPTIONAL(RDEBUG2, DEBUG2, "'%s' is not a function, is a %s (%i)", funcname, lua_typename(L, type), type);
882 goto error;
883 }
884
885 if (lua_pcall(L, 0, 1, 0) != 0) {
886 char const *msg = lua_tostring(L, -1);
887
888 ROPTIONAL(RDEBUG2, DEBUG2, "Call to %s failed: %s", funcname, msg ? msg : "unknown error");
889 goto error;
890 }
891
892 /*
893 * functions without rcodeurn or rcodeurning none/nil will be RLM_MODULE_OK
894 */
895 if (!lua_isnoneornil(L, -1)) {
896 /*
897 * e.g: rcodeurn 2, rcodeurn "2", rcodeurn fr.handled, fr.fail, ...
898 */
899 if (lua_isnumber(L, -1)) {
900 rcode = lua_tointeger(L, -1);
901 if (fr_table_str_by_value(rcode_table, rcode, NULL) != NULL) goto done;
902 }
903
904 /*
905 * e.g: rcodeurn "handled", "ok", "fail", ...
906 */
907 if (lua_isstring(L, -1)) {
908 rcode = fr_table_value_by_str(rcode_table, lua_tostring(L, -1), -1);
909 if ((int)rcode != -1) goto done;
910 }
911
912 ROPTIONAL(RDEBUG2, DEBUG2, "Lua function %s() rcodeurned invalid rcode \"%s\"", funcname, lua_tostring(L, -1));
913 goto error;
914 }
915
916done:
919
920 RETURN_MODULE_RCODE(rcode);
921}
922
923/*
924 * Initialise the table "fr." with all valid return codes.
925 */
926static int _lua_rcode_table_newindex(UNUSED lua_State *L)
927{
929
930 RWDEBUG("You can't modify the table 'fr.rcode.{}' (read-only)");
931
932 return 1;
933}
934
935static int _lua_rcode_table_index(lua_State *L)
936{
937 char const *key = lua_tostring(L, -1);
938 int ret;
939
940 ret = fr_table_value_by_str(rcode_table, key, -1);
941 if (ret != -1) {
942 lua_pushinteger(L, ret);
943 return 1;
944 }
945
946 lua_pushfstring(L, "The fr.rcode.%s is not found", key);
947 return -1;
948}
949
950/*
951 * As can be seen in http://luajit.org/extensions.html, the pairs() is disabled by default.
952 * ps: We add pairs() method just to inform the user that it does not work.
953 */
954static int _lua_rcode_table_pairs(lua_State *L)
955{
956 lua_pushfstring(L, "The pairs(fr.rcode) is not available. Access directly! e.g: 'fr.rcode.reject'");
957 return -1;
958}
959
960static void fr_lua_rcode_register(lua_State *L, char const *name)
961{
962 const luaL_Reg metatable[] = {
963 { "__index", _lua_rcode_table_index },
964 { "__newindex", _lua_rcode_table_newindex },
965 { "__pairs", _lua_rcode_table_pairs },
966#ifdef HAVE_LUAJIT_H
967 { "pairs", _lua_rcode_table_pairs },
968#endif
969 { NULL, NULL }
970 };
971
972 /* fr = {} */
973 lua_getglobal(L, "fr");
974 luaL_checktype(L, -1, LUA_TTABLE);
975
976 /* fr = { rcode = {} } */
977 lua_newtable(L);
978 {
979 luaL_register(L, name, metatable);
980 lua_setmetatable(L, -2);
981 lua_setfield(L, -2, name);
982 }
983}
984
985/** Initialise a new Lua/LuaJIT interpreter
986 *
987 * Creates a new lua_State and verifies all required functions have been loaded correctly.
988 *
989 * @param[in] out Where to write a pointer to the new state.
990 * @param[in] mctx configuration data for the
991 * @return 0 on success else -1.
992 */
993int fr_lua_init(lua_State **out, module_inst_ctx_t const *mctx)
994{
996 lua_State *L;
997
999
1000 L = luaL_newstate();
1001 if (!L) {
1002 ERROR("Failed initialising Lua state");
1003 return -1;
1004 }
1005
1006 luaL_openlibs(L);
1007
1008 /*
1009 * Load the Lua file into our environment.
1010 */
1011 if (luaL_loadfile(L, inst->module) != 0) {
1012 ERROR("Failed loading file: %s", lua_gettop(L) ? lua_tostring(L, -1) : "Unknown error");
1013
1014 error:
1015 *out = NULL;
1017 lua_close(L);
1018 return -1;
1019 }
1020
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");
1023
1024 goto error;
1025 }
1026
1027 /*
1028 * Setup "fr.{}"
1029 */
1031
1032 /*
1033 * Setup "fr.log.{}"
1034 */
1035 if (inst->jit) {
1036 DEBUG4("Initialised new LuaJIT interpreter %p", L);
1037 if (fr_lua_util_jit_log_register(L) < 0) goto error;
1038 } else {
1039 DEBUG4("Initialised new Lua interpreter %p", L);
1040 if (fr_lua_util_log_register(L) < 0) goto error;
1041 }
1042
1043 /*
1044 * Setup the "fr.rcode.{}" with all RLM_MODULE_*
1045 * e.g: "fr.rcode.reject", "fr.rcode.ok", ...
1046 */
1047 fr_lua_rcode_register(L, "rcode");
1048
1049 /*
1050 * Verify all the functions were provided.
1051 */
1052 if (fr_lua_check_func(mctx, L, inst->func_instantiate)
1053 || fr_lua_check_func(mctx, L, inst->func_detach)
1054 || fr_lua_check_func(mctx, L, inst->func_xlat)) {
1055 goto error;
1056 }
1057
1058 *out = L;
1059 return 0;
1060}
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
log_entry msg
Definition acutest.h:794
#define RCSID(id)
Definition build.h:485
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:209
#define DIAG_ON(_x)
Definition build.h:460
#define SIZEOF_MEMBER(_t, _m)
Definition build.h:338
#define UNUSED
Definition build.h:317
#define DIAG_OFF(_x)
Definition build.h:459
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition dcursor.h:290
static void * fr_dcursor_current(fr_dcursor_t *cursor)
Return the item the cursor current points to.
Definition dcursor.h:339
#define ERROR(fmt,...)
Definition dhcpclient.c:41
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:3266
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2403
fr_dict_t const * fr_dict_internal(void)
Definition dict_util.c:4654
#define ROPTIONAL(_l_request, _l_global, _fmt,...)
Use different logging functions depending on whether request is NULL or not.
Definition log.h:528
#define RWDEBUG(fmt,...)
Definition log.h:361
#define RWARN(fmt,...)
Definition log.h:297
#define RERROR(fmt,...)
Definition log.h:298
#define DEBUG4(_fmt,...)
Definition log.h:267
#define REMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
Definition log.h:498
#define RPEDEBUG(fmt,...)
Definition log.h:376
#define RLM_LUA_STACK_RESET()
Definition lua.c:41
static int _lua_rcode_table_newindex(UNUSED lua_State *L)
Definition lua.c:926
static void _lua_fr_request_register(lua_State *L, request_t *request)
Definition lua.c:830
unlang_action_t fr_lua_run(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request, char const *funcname)
Definition lua.c:854
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.
Definition lua.c:738
static int _lua_pair_setter(lua_State *L)
Set an instance of an attribute.
Definition lua.c:349
#define RLM_LUA_STACK_SET()
Definition lua.c:40
char const * fr_lua_version(lua_State *L)
Definition lua.c:664
static int fr_lua_marshall(request_t *request, lua_State *L, fr_pair_t const *vp)
Convert fr_pair_ts to Lua values.
Definition lua.c:65
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.
Definition lua.c:218
static int _lua_list_iterator(lua_State *L)
Iterate over attributes in a list.
Definition lua.c:481
static int _lua_pair_iterator_init(lua_State *L)
Initiate an iterator to return all the values of a given attribute.
Definition lua.c:451
unsigned int idx
Definition lua.c:47
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.
Definition lua.c:319
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.
Definition lua.c:794
fr_dict_attr_t const * da
Definition lua.c:45
static int _lua_list_iterator_init(lua_State *L)
Initialise a new structural iterator.
Definition lua.c:524
bool fr_lua_isjit(lua_State *L)
Check whether the Lua interpreter were actually linked to is LuaJIT.
Definition lua.c:650
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.
Definition lua.c:693
fr_pair_t * vp
Definition lua.c:46
static int _lua_rcode_table_pairs(lua_State *L)
Definition lua.c:954
static int _lua_pair_iterator(lua_State *L)
Iterate over instances of a leaf attribute.
Definition lua.c:425
#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.
Definition lua.c:993
static int _lua_rcode_table_index(lua_State *L)
Definition lua.c:935
fr_lua_pair_t * parent
Definition lua.c:48
struct fr_lua_pair_s fr_lua_pair_t
Definition lua.c:43
static int _lua_pair_accessor(lua_State *L)
Get an attribute or an instance of an attribute.
Definition lua.c:567
#define IN_RANGE_INTEGER_SIGNED(_x)
static void fr_lua_rcode_register(lua_State *L, char const *name)
Definition lua.c:960
Library function signatures for lua module.
int fr_lua_util_jit_log_register(lua_State *L)
Insert cdefs into the lua environment.
Definition util.c:202
void fr_lua_util_set_mctx(module_ctx_t const *mctx)
Set the thread local instance.
Definition util.c:321
request_t * fr_lua_util_get_request(void)
Get the thread local request.
Definition util.c:348
void fr_lua_util_set_request(request_t *request)
Set the thread local request.
Definition util.c:339
void fr_lua_util_fr_register(lua_State *L)
Definition util.c:40
int fr_lua_util_log_register(lua_State *L)
Register utililiary functions in the lua environment.
Definition util.c:280
lua_State * interpreter
Thread specific interpreter.
Definition lua.h:61
@ 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.
long int ssize_t
unsigned char uint8_t
void * thread
Thread specific instance data.
Definition module_ctx.h:43
#define MODULE_CTX_FROM_INST(_mctx)
Wrapper to create a module_ctx_t as a compound literal from a module_inst_ctx_t.
Definition module_ctx.h:138
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 instantiation calls.
Definition module_ctx.h:50
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:960
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:674
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:1472
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:697
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:745
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:1832
#define fr_assert(_expr)
Definition rad_assert.h:38
static bool done
Definition radclient.c:81
#define REDEBUG(fmt,...)
Definition radclient.h:52
#define RDEBUG2(fmt,...)
Definition radclient.h:54
#define DEBUG2(fmt,...)
Definition radclient.h:43
fr_table_num_sorted_t const rcode_table[]
Definition rcode.c:35
#define RETURN_MODULE_RCODE(_rcode)
Definition rcode.h:66
#define RETURN_MODULE_FAIL
Definition rcode.h:57
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
@ RLM_MODULE_OK
The module is OK, continue.
Definition rcode.h:43
static char const * name
#define FR_SBUFF_OUT(_start, _len_or_end)
void * data
Module's instance data.
Definition module.h:272
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
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition strlcpy.c:34
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 fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
Definition table.h:653
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:772
#define talloc_get_type_abort_const
Definition talloc.h:287
static int64_t fr_unix_time_to_sec(fr_unix_time_t delta)
Definition time.h:506
@ T_BARE_WORD
Definition token.h:120
#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.
Definition pair.h:628
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.
Definition pair_inline.c:69
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:53
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
Definition pair.h:591
size_t fr_pair_list_num_elements(fr_pair_list_t const *list)
Get the length of a list of fr_pair_t.
static fr_slen_t parent
Definition pair.h:845
#define fr_type_is_group(_x)
Definition types.h:372
#define fr_type_is_structural(_x)
Definition types.h:388
#define FR_TYPE_NON_LEAF
Definition types.h:314
#define fr_type_is_leaf(_x)
Definition types.h:389
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:450
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:3574
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:4463
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.
Definition value.c:4620
#define vb_int64
Definition value.h:277
#define vb_float64
Definition value.h:280
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
Definition value.h:606
static size_t char ** out
Definition value.h:1020