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: eb23db1b23124097286a47fe48d3e19347a679f1 $
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: eb23db1b23124097286a47fe48d3e19347a679f1 $")
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 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 }
301 fr_value_box_memdup(ctx, out_vb, da, p, len, true);
302 }
303 break;
304
305 default:
306 {
307 int type = lua_type(L, -1);
308 REDEBUG("Unmarshalling failed, unsupported Lua type %s (%i)", lua_typename(L, type), type);
309
310 return -1;
311 }
312 }
313
314 return 0;
315}
316
317/** Build parent structural pairs needed when a leaf node is set
318 *
319 */
320static int fr_lua_pair_parent_build(request_t *request, fr_lua_pair_t *pair_data)
321{
322 if (!pair_data->parent->vp) {
323 if (fr_lua_pair_parent_build(request, pair_data->parent) < 0) return -1;
324 }
325 if (pair_data->idx > 1) {
326 unsigned int count = fr_pair_count_by_da(&pair_data->parent->vp->vp_group, pair_data->da);
327 if (count < (pair_data->idx - 1)) {
328 RERROR("Attempt to set instance %d when only %d exist", pair_data->idx, count);
329 return -1;
330 }
331 }
332
333 if (fr_pair_append_by_da(pair_data->parent->vp, &pair_data->vp,
334 &pair_data->parent->vp->vp_group, pair_data->da) < 0) return -1;
335 return 0;
336}
337
338/** Set an instance of an attribute
339 *
340 * @note Should only be present in the Lua environment as a closure.
341 * @note Takes one upvalue - the fr_lua_pair_t representing this pair as user data.
342 * @note Is called as an __newindex metamethod, so takes the table (can be ignored),
343 * the field (an integer index value) and the new value.
344 *
345 * @param[in] L Lua state.
346 * @return
347 * - 0 on success.
348 * - -1 on failure.
349 */
350static int _lua_pair_setter(lua_State *L)
351{
353 fr_lua_pair_t *pair_data, *parent;
354 fr_dict_attr_t const *da;
355 fr_pair_t *vp;
356 lua_Integer index;
357
358 if (!lua_isnumber(L, -2)) {
359 RERROR("Attempt to %s attribute \"%s\" table.", lua_isnil(L, -1) ? "delete" : "set value on", lua_tostring(L, -2));
360 RWARN("Values should be manipulated using <list>['<attr>'][idx] = <value> where idx is the attribute instance (starting at 1)");
361 return -1;
362 }
363
364 index = lua_tointeger(L, -2);
365 if (index < 1) {
366 RERROR("Invalid attribute index %ld", index);
367 return -1;
368 }
369
370 pair_data = lua_touserdata(L, lua_upvalueindex(1));
371 da = pair_data->da;
372
373 if (!fr_type_is_leaf(da->type)) {
374 RERROR("Values cannot be assigned to structural attribute \"%s\"", da->name);
375 return -1;
376 }
377 parent = pair_data->parent;
378
379 /*
380 * If the value of the Lua stack was nil, we delete the attribute if it exists.
381 */
382 if (lua_isnil(L, -1)) {
383 if (!pair_data->parent->vp) return 0;
384 vp = fr_pair_find_by_da_idx(&parent->vp->vp_group, da, index - 1);
385 if (!vp) return 0;
386 if (pair_data->vp == vp) pair_data->vp = NULL;
387 fr_pair_delete(&parent->vp->vp_group, vp);
388 return 0;
389 }
390
391 if (!parent->vp) {
392 if (fr_lua_pair_parent_build(request, parent) < 0) return -1;
393 }
394
395 vp = fr_pair_find_by_da_idx(&parent->vp->vp_group, da, index - 1);
396
397 /*
398 * Asked to add a pair we don't have - check we're not being asked
399 * to add a gap.
400 */
401 if (!vp && (index > 1)) {
402 unsigned int count = fr_pair_count_by_da(&parent->vp->vp_group, da);
403 if (count < (index - 1)) {
404 RERROR("Attempt to set instance %ld when only %d exist", index, count);
405 return -1;
406 }
407 }
408
409 if (!vp) {
410 if (fr_pair_append_by_da(parent->vp, &vp, &parent->vp->vp_group, da) < 0) {
411 RERROR("Failed to create attribute %s", da->name);
412 return -1;
413 }
414 }
415 if (fr_lua_unmarshall(vp, &vp->data, request, L, da) < 0) return -1;
416
417 return 0;
418}
419
420/** Iterate over instances of a leaf attribute
421 *
422 * Each call returns with the value of the next instance of the attribute
423 * on the Lua stack, or nil, when there are no more instances.
424 *
425 */
426static int _lua_pair_iterator(lua_State *L)
427{
429 fr_dcursor_t *cursor;
430 fr_pair_t *vp;
431
432 fr_assert(lua_isuserdata(L, lua_upvalueindex(1)));
433
434 cursor = lua_touserdata(L, lua_upvalueindex(1));
435 fr_assert(cursor);
436
437 vp = fr_dcursor_current(cursor);
438 if (!vp) {
439 lua_pushnil(L);
440 return 1;
441 }
442
443 if (fr_lua_marshall(request, L, vp) < 0) return -1;
444
445 fr_dcursor_next(cursor);
446 return 1;
447}
448
449/** Initiate an iterator to return all the values of a given attribute
450 *
451 */
452static int _lua_pair_iterator_init(lua_State *L)
453{
455 fr_dcursor_t *cursor;
456 fr_lua_pair_t *pair_data;
457
458 fr_assert(lua_isuserdata(L, lua_upvalueindex(1)));
459 pair_data = lua_touserdata(L, lua_upvalueindex(1));
460 fr_assert(pair_data);
461
462 cursor = (fr_dcursor_t*) lua_newuserdata(L, sizeof(fr_dcursor_t));
463 if (!cursor) {
464 REDEBUG("Failed allocating user data to hold cursor");
465 return -1;
466 }
467 fr_pair_dcursor_by_da_init(cursor, &pair_data->parent->vp->vp_group, pair_data->da);
468
469 lua_pushcclosure(L, _lua_pair_iterator, 1);
470
471 return 1;
472}
473
474/** Iterate over attributes in a list
475 *
476 * Each call returns with two values on the Lua stack
477 * - the name of the next attribute
478 * - the value of the next attribute, or an array of child attribute names
479 *
480 * or, nil is pushed to the stack when there are no more attributes in the list.
481 */
482static int _lua_list_iterator(lua_State *L)
483{
485 fr_dcursor_t *cursor;
486 fr_pair_t *vp;
487
488 fr_assert(lua_isuserdata(L, lua_upvalueindex(1)));
489
490 cursor = lua_touserdata(L, lua_upvalueindex(1));
491 fr_assert(cursor);
492
493 vp = fr_dcursor_current(cursor);
494 if(!vp) {
495 lua_pushnil(L);
496 return 1;
497 }
498
499 lua_pushstring(L, vp->da->name);
500
501 /*
502 * For structural attributes return an array of the child names
503 */
504 if (fr_type_is_structural(vp->da->type)) {
505 fr_pair_t *child = NULL;
506 unsigned int i = 1;
507
508 lua_createtable(L, fr_pair_list_num_elements(&vp->vp_group), 0);
509 while ((child = fr_pair_list_next(&vp->vp_group, child))) {
510 lua_pushstring(L, child->da->name);
511 lua_rawseti(L, -2, i++);
512 }
513 } else {
514 if (fr_lua_marshall(request, L, vp) < 0) return -1;
515 }
516
517 fr_dcursor_next(cursor);
518
519 return 2;
520}
521
522/** Initialise a new structural iterator
523 *
524 */
525static int _lua_list_iterator_init(lua_State *L)
526{
528 fr_dcursor_t *cursor;
529 fr_lua_pair_t *pair_data;
530
531 fr_assert(lua_isuserdata(L, lua_upvalueindex(1)));
532 pair_data = lua_touserdata(L, lua_upvalueindex(1));
533 if (!pair_data->vp) return 0;
534
535 cursor = (fr_dcursor_t*) lua_newuserdata(L, sizeof(fr_dcursor_t));
536 if (!cursor) {
537 REDEBUG("Failed allocating user data to hold cursor");
538 return -1;
539 }
540 fr_pair_dcursor_init(cursor, &pair_data->vp->vp_group);
541
542 lua_pushcclosure(L, _lua_list_iterator, 1);
543
544 return 1;
545}
546
547/** Get an attribute or an instance of an attribute
548 *
549 * When called with a numeric index, it is the instance of the attribute
550 * which is being requested.
551 * Otherwise, the index is an attribute name.
552 *
553 * @note Should only be present in the Lua environment as a closure.
554 * @note Takes one upvalue - the fr_lua_pair_t representing either this
555 * attribute in the case it is an index being requested, or the
556 * parent in the case an attribute is being requested.
557 * @note Is called as an __index metamethod, so takes the table (can be ignored)
558 * and the field (integer index for instance or string for attribute)
559 *
560 * @param[in] L Lua interpreter.
561 * @return
562 * - -1 on failure.
563 * - 0 (no results) on success.
564 * - 1 on success with:
565 * - the fr_pair_t value on the stack for leaf values.
566 * - a lua table for structural items.
567 */
568static int _lua_pair_accessor(lua_State *L)
569{
571 fr_lua_pair_t *pair_data;
572 fr_pair_t *vp = NULL;
573
574 fr_assert(lua_isuserdata(L, lua_upvalueindex(1)));
575
576 pair_data = (fr_lua_pair_t *)lua_touserdata(L, lua_upvalueindex(1));
577
578 if (lua_isnumber(L, -1)) {
579 lua_Integer index = lua_tointeger(L, -1);
580
581 if (index < 1) {
582 RERROR("Invalid attribute index %ld", index);
583 return -1;
584 }
585
586 if (!pair_data->parent || !pair_data->parent->vp) return 0;
587
588 if (index == 1 && pair_data->vp) {
589 vp = pair_data->vp;
590 } else {
591 // Lua array indexes are 1 based, not 0 based.
592 vp = fr_pair_find_by_da_idx(&pair_data->parent->vp->vp_group, pair_data->da, index - 1);
593 if (index == 1) pair_data->vp = vp;
594 }
595 /*
596 * Retrieving an instance of a leaf gives the actual attribute
597 * value (if it exists)
598 */
599 if (fr_type_is_leaf(pair_data->da->type)) {
600 if (!vp) return 0;
601 if (fr_lua_marshall(request, L, vp) < 0) return -1;
602 return 1;
603 }
604
605 fr_assert(fr_type_is_structural(pair_data->da->type));
606
607 /*
608 * Retrieving a structural attribute returns a new table.
609 */
610 lua_newtable(L);
611 _lua_pair_init(L, vp, pair_data->da, index, pair_data->parent);
612
613 } else {
614 fr_dict_attr_t const *da;
615 char const *attr = lua_tostring(L, -1);
616
617 if (!attr) {
618 RERROR("Failed retrieving field name from lua stack");
619 return -1;
620 }
621
622 da = fr_dict_attr_by_name(NULL, pair_data->da, attr);
623
624 /*
625 * Allow fallback to internal attributes if the parent is a group or dictionary root.
626 */
627 if (!da && (fr_type_is_group(pair_data->da->type) || pair_data->da->flags.is_root)) {
629 }
630
631 if (!da) {
632 RERROR("Unknown or invalid attribute name \"%s\"", attr);
633 return -1;
634 }
635
636 if (pair_data->vp) vp = fr_pair_find_by_da(&pair_data->vp->vp_group, NULL, da);
637 _lua_pair_init(L, vp, da, 1, pair_data);
638
639 lua_rawset(L, -3); /* Cache the attribute manipulation object */
640 lua_getfield(L, -1, attr); /* and return it */
641 }
642
643 return 1;
644}
645
646/** Check whether the Lua interpreter were actually linked to is LuaJIT
647 *
648 * @param L Lua interpreter.
649 * @return true if were running with LuaJIT else false.
650 */
651bool fr_lua_isjit(lua_State *L)
652{
653 bool ret = false;
655 lua_getglobal(L, "jit");
656 if (lua_isnil(L, -1)) goto done;
657
658 ret = true;
659done:
661
662 return ret;
663}
664
665char const *fr_lua_version(lua_State *L)
666{
667 char const *version;
668
670 lua_getglobal(L, "jit");
671 if (!lua_isnil(L, -1)) {
672 lua_getfield(L, -1, "version"); /* Version field in jit table */
673 } else {
674 lua_getglobal(L, "_VERSION"); /* Version global */
675 }
676
677 if (lua_isnil(L, -1) || !(version = lua_tostring(L, -1))) {
678 return "unknown version";
679 }
681
682 return version;
683}
684
685/** Check if a given function was loaded into an index in the global table
686 *
687 * Also check what was loaded there is a function and that it accepts the correct arguments.
688 *
689 * @param[in] mctx module instantiation data.
690 * @param[in] L the lua state.
691 * @param[in] name of function to check.
692 * @returns 0 on success (function is present and correct), or -1 on failure.
693 */
694int fr_lua_check_func(module_inst_ctx_t const *mctx, lua_State *L, char const *name)
695{
696 int ret;
697 int type;
698
700
701 if (name == NULL) return 0;
702
703 lua_getglobal(L, name);
704
705 /*
706 * Check the global is a function.
707 */
708 type = lua_type(L, -1);
709 switch (type) {
710 case LUA_TFUNCTION:
711 break;
712
713 case LUA_TNIL:
714 ERROR("Function \"%s\" not found ", name);
715 ret = -1;
716 goto done;
717
718 default:
719 ERROR("Value found at index \"%s\" is not a function (is a %s)", name, lua_typename(L, type));
720 ret = -1;
721 goto done;
722 }
723 ret = 0;
724done:
726 return ret;
727}
728
729/** Resolve a path string to a field value in Lua
730 *
731 * Parses a string in the format
732 * @verbatim obj0[.obj1][.objN] @endverbatim, adding all tables it traverses
733 * to the stack.
734 *
735 * All paths are assumed to start at a global, so the first field
736 * will be looked up in the global table.
737 *
738 */
739static int fr_lua_get_field(module_ctx_t const *mctx, lua_State *L, request_t *request, char const *field)
740{
741 char buff[512];
742 char const *p = field, *q;
743
744 q = strchr(p, '.');
745 if (!q) { /* No field, just global */
746 lua_getglobal(L, p);
747 if (lua_isnil(L, -1)) {
748 does_not_exist:
749 if (request) {
750 REMARKER(field, p - field, "Field does not exist");
751 } else {
752 EMARKER(field, p - field, "Field does not exist");
753 }
754 return -1;
755 }
756 return 0;
757 }
758
759 if ((size_t) (q - p) >= sizeof(buff)) {
760 too_long:
761 ROPTIONAL(REDEBUG, ERROR, "Field name too long, expected < %zu, got %zu", q - p, sizeof(buff));
762 return -1;
763 }
764
765 strlcpy(buff, p, (q - p) + 1);
766 lua_getglobal(L, buff);
767 if (lua_isnil(L, -1)) goto does_not_exist;
768 p = q + 1; /* Skip the '.' */
769
770 while ((q = strchr(p, '.'))) {
771 if ((size_t) (q - p) >= sizeof(buff)) goto too_long;
772
773 strlcpy(buff, p, (q - p) + 1);
774 lua_getfield(L, -1, buff);
775 if (lua_isnil(L, -1)) goto does_not_exist;
776 p = q + 1;
777 }
778
779 lua_getfield(L, -1, p);
780 if (lua_isnil(L, -1)) goto does_not_exist;
781
782 return 0;
783}
784
785/** Initialise a table representing a pair
786 *
787 * After calling this function, a new table will be on the lua stack which represents the pair.
788 *
789 * The pair may not exist - e.g. when setting a new nested attribute, parent pairs may not
790 * have been created yet. In that case, this holds the da and index of the instance which
791 * will be created when the leaf is assigned a value.
792 *
793 * @param[in] L the lua state
794 * @param[in] vp the actual pair instance being represented, if it already exists
795 * @param[in] da dictionary attribute for this pair
796 * @param[in] idx index of the attribute instance (starting at 1)
797 * @param[in] parent lua userdata for the parent of this attribute.
798 */
799static 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)
800{
801 fr_lua_pair_t *pair_data;
802
803 lua_newtable(L);
804
805 /*
806 * The userdata associated with the meta functions
807 * __index and __newindex, and the .pairs() field.
808 */
809 pair_data = lua_newuserdata(L, sizeof(fr_lua_pair_t));
810 *pair_data = (fr_lua_pair_t) {
811 .da = da,
812 .idx = idx,
813 .vp = vp,
814 .parent = parent
815 };
816 if (fr_type_is_structural(da->type)) {
817 lua_pushcclosure(L, _lua_list_iterator_init, 1);
818 } else {
819 lua_pushcclosure(L, _lua_pair_iterator_init, 1);
820 }
821 lua_setfield(L, -2, "pairs");
822
823 lua_newtable(L); /* Metatable for index functions*/
824
825 lua_pushlightuserdata(L, pair_data);
826 lua_pushcclosure(L, _lua_pair_accessor, 1);
827 lua_setfield(L, -2, "__index");
828
829 lua_pushlightuserdata(L, pair_data);
830 lua_pushcclosure(L, _lua_pair_setter, 1);
831 lua_setfield(L, -2, "__newindex");
832 lua_setmetatable(L, -2);
833}
834
835static void _lua_fr_request_register(lua_State *L, request_t *request)
836{
837 /* fr = {} */
838 lua_getglobal(L, "fr");
839 luaL_checktype(L, -1, LUA_TTABLE);
840
841 /* fr = { request {} } */
842 lua_pushstring(L, "request");
843 _lua_pair_init(L, fr_pair_list_parent(&request->request_pairs), fr_dict_root(request->proto_dict), 1, NULL);
844 lua_rawset(L, -3);
845
846 lua_pushstring(L, "reply");
847 _lua_pair_init(L, fr_pair_list_parent(&request->reply_pairs), fr_dict_root(request->proto_dict), 1, NULL);
848 lua_rawset(L, -3);
849
850 lua_pushstring(L, "control");
851 _lua_pair_init(L, fr_pair_list_parent(&request->control_pairs), fr_dict_root(request->proto_dict), 1, NULL);
852 lua_rawset(L, -3);
853
854 lua_pushstring(L, "session-state");
855 _lua_pair_init(L, fr_pair_list_parent(&request->session_state_pairs), fr_dict_root(request->proto_dict), 1, NULL);
856 lua_rawset(L, -3);
857}
858
859unlang_action_t fr_lua_run(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request, char const *funcname)
860{
861 rlm_lua_thread_t *thread = talloc_get_type_abort(mctx->thread, rlm_lua_thread_t);
862 lua_State *L = thread->interpreter;
864
867
868 ROPTIONAL(RDEBUG2, DEBUG2, "Calling %s() in interpreter %p", funcname, L);
869
870 if (request) _lua_fr_request_register(L, request);
871
872 /*
873 * Get the function were going to be calling
874 */
875 if (fr_lua_get_field(mctx, L, request, funcname) < 0) {
876error:
879
881 }
882
883 if (!lua_isfunction(L, -1)) {
884 int type = lua_type(L, -1);
885
886 ROPTIONAL(RDEBUG2, DEBUG2, "'%s' is not a function, is a %s (%i)", funcname, lua_typename(L, type), type);
887 goto error;
888 }
889
890 if (lua_pcall(L, 0, 1, 0) != 0) {
891 char const *msg = lua_tostring(L, -1);
892
893 ROPTIONAL(RDEBUG2, DEBUG2, "Call to %s failed: %s", funcname, msg ? msg : "unknown error");
894 goto error;
895 }
896
897 /*
898 * functions without rcodeurn or rcodeurning none/nil will be RLM_MODULE_OK
899 */
900 if (!lua_isnoneornil(L, -1)) {
901 /*
902 * e.g: rcodeurn 2, rcodeurn "2", rcodeurn fr.handled, fr.fail, ...
903 */
904 if (lua_isnumber(L, -1)) {
905 rcode = lua_tointeger(L, -1);
906 if (fr_table_str_by_value(rcode_table, rcode, NULL) != NULL) goto done;
907 }
908
909 /*
910 * e.g: rcodeurn "handled", "ok", "fail", ...
911 */
912 if (lua_isstring(L, -1)) {
913 rcode = fr_table_value_by_str(rcode_table, lua_tostring(L, -1), -1);
914 if ((int)rcode != -1) goto done;
915 }
916
917 ROPTIONAL(RDEBUG2, DEBUG2, "Lua function %s() rcodeurned invalid rcode \"%s\"", funcname, lua_tostring(L, -1));
918 goto error;
919 }
920
921done:
924
925 RETURN_UNLANG_RCODE(rcode);
926}
927
928/*
929 * Initialise the table "fr." with all valid return codes.
930 */
931static int _lua_rcode_table_newindex(UNUSED lua_State *L)
932{
934
935 RWDEBUG("You can't modify the table 'fr.rcode.{}' (read-only)");
936
937 return 1;
938}
939
940static int _lua_rcode_table_index(lua_State *L)
941{
942 char const *key = lua_tostring(L, -1);
943 int ret;
944
945 ret = fr_table_value_by_str(rcode_table, key, -1);
946 if (ret != -1) {
947 lua_pushinteger(L, ret);
948 return 1;
949 }
950
951 lua_pushfstring(L, "The fr.rcode.%s is not found", key);
952 return -1;
953}
954
955/*
956 * As can be seen in http://luajit.org/extensions.html, the pairs() is disabled by default.
957 * ps: We add pairs() method just to inform the user that it does not work.
958 */
959static int _lua_rcode_table_pairs(lua_State *L)
960{
961 lua_pushfstring(L, "The pairs(fr.rcode) is not available. Access directly! e.g: 'fr.rcode.reject'");
962 return -1;
963}
964
965static void fr_lua_rcode_register(lua_State *L, char const *name)
966{
967 const luaL_Reg metatable[] = {
968 { "__index", _lua_rcode_table_index },
969 { "__newindex", _lua_rcode_table_newindex },
970 { "__pairs", _lua_rcode_table_pairs },
971#ifdef HAVE_LUAJIT_H
972 { "pairs", _lua_rcode_table_pairs },
973#endif
974 { NULL, NULL }
975 };
976
977 /* fr = {} */
978 lua_getglobal(L, "fr");
979 luaL_checktype(L, -1, LUA_TTABLE);
980
981 /* fr = { rcode = {} } */
982 lua_newtable(L);
983 {
984 luaL_register(L, name, metatable);
985 lua_setmetatable(L, -2);
986 lua_setfield(L, -2, name);
987 }
988}
989
990/** Initialise a new Lua/LuaJIT interpreter
991 *
992 * Creates a new lua_State and verifies all required functions have been loaded correctly.
993 *
994 * @param[in] out Where to write a pointer to the new state.
995 * @param[in] mctx configuration data for the
996 * @return 0 on success else -1.
997 */
998int fr_lua_init(lua_State **out, module_inst_ctx_t const *mctx)
999{
1001 lua_State *L;
1002
1004
1005 L = luaL_newstate();
1006 if (!L) {
1007 ERROR("Failed initialising Lua state");
1008 return -1;
1009 }
1010
1011 luaL_openlibs(L);
1012
1013 /*
1014 * Load the Lua file into our environment.
1015 */
1016 if (luaL_loadfile(L, inst->module) != 0) {
1017 ERROR("Failed loading file: %s", lua_gettop(L) ? lua_tostring(L, -1) : "Unknown error");
1018
1019 error:
1020 *out = NULL;
1022 lua_close(L);
1023 return -1;
1024 }
1025
1026 if (lua_pcall(L, 0, LUA_MULTRET, 0) != 0) {
1027 ERROR("Failed executing script: %s", lua_gettop(L) ? lua_tostring(L, -1) : "Unknown error");
1028
1029 goto error;
1030 }
1031
1032 /*
1033 * Setup "fr.{}"
1034 */
1036
1037 /*
1038 * Setup "fr.log.{}"
1039 */
1040 if (inst->jit) {
1041 DEBUG4("Initialised new LuaJIT interpreter %p", L);
1042 if (fr_lua_util_jit_log_register(L) < 0) goto error;
1043 } else {
1044 DEBUG4("Initialised new Lua interpreter %p", L);
1045 if (fr_lua_util_log_register(L) < 0) goto error;
1046 }
1047
1048 /*
1049 * Setup the "fr.rcode.{}" with all RLM_MODULE_*
1050 * e.g: "fr.rcode.reject", "fr.rcode.ok", ...
1051 */
1052 fr_lua_rcode_register(L, "rcode");
1053
1054 /*
1055 * Verify all the functions were provided.
1056 */
1057 if (fr_lua_check_func(mctx, L, inst->func_instantiate)
1058 || fr_lua_check_func(mctx, L, inst->func_detach)
1059 || fr_lua_check_func(mctx, L, inst->func_xlat)) {
1060 goto error;
1061 }
1062
1063 *out = L;
1064 return 0;
1065}
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:3359
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2496
fr_dict_t const * fr_dict_internal(void)
Definition dict_util.c:4749
#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 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: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:931
static void _lua_fr_request_register(lua_State *L, request_t *request)
Definition lua.c:835
static int _lua_pair_setter(lua_State *L)
Set an instance of an attribute.
Definition lua.c:350
#define RLM_LUA_STACK_SET()
Definition lua.c:40
char const * fr_lua_version(lua_State *L)
Definition lua.c:665
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:482
static int _lua_pair_iterator_init(lua_State *L)
Initiate an iterator to return all the values of a given attribute.
Definition lua.c:452
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:859
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:320
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:799
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:525
bool fr_lua_isjit(lua_State *L)
Check whether the Lua interpreter were actually linked to is LuaJIT.
Definition lua.c:651
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:694
fr_pair_t * vp
Definition lua.c:46
static int _lua_rcode_table_pairs(lua_State *L)
Definition lua.c:959
static int _lua_pair_iterator(lua_State *L)
Iterate over instances of a leaf attribute.
Definition lua.c:426
#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:998
static int _lua_rcode_table_index(lua_State *L)
Definition lua.c:940
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:568
#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:739
static void fr_lua_rcode_register(lua_State *L, char const *name)
Definition lua.c:965
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:963
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:677
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:1464
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:700
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:748
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:1824
#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_UNLANG_RCODE(_rcode)
Definition rcode.h:57
#define RETURN_UNLANG_FAIL
Definition rcode.h:59
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:45
static char const * name
#define FR_SBUFF_OUT(_start, _len_or_end)
void * data
Module's instance data.
Definition module.h:291
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:624
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:589
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:841
#define fr_type_is_group(_x)
Definition types.h:377
#define fr_type_is_structural(_x)
Definition types.h:393
@ FR_TYPE_ATTR
A contains an attribute reference.
Definition types.h:84
#define FR_TYPE_NON_LEAF
Definition types.h:319
#define fr_type_is_leaf(_x)
Definition types.h:394
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:455
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:3730
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:4673
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:4830
#define vb_int64
Definition value.h:280
#define vb_float64
Definition value.h:283
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
Definition value.h:609
static size_t char ** out
Definition value.h:1023