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