]> git.proxmox.com Git - mirror_frr.git/blob - lib/frrlua.c
Merge pull request #9455 from LabNConsulting/chopps/fix-zebtest-fixed-sleep
[mirror_frr.git] / lib / frrlua.c
1 /*
2 * This file defines the lua interface into
3 * FRRouting.
4 *
5 * Copyright (C) 2016-2019 Cumulus Networks, Inc.
6 * Donald Sharp, Quentin Young
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include <zebra.h>
24
25 #ifdef HAVE_SCRIPTING
26
27 #include "prefix.h"
28 #include "frrlua.h"
29 #include "log.h"
30 #include "buffer.h"
31
32 DEFINE_MTYPE(LIB, SCRIPT_RES, "Scripting results");
33
34 /* Lua stuff */
35
36 /*
37 * FRR convenience functions.
38 *
39 * This section has convenience functions used to make interacting with the Lua
40 * stack easier.
41 */
42
43 int frrlua_table_get_integer(lua_State *L, const char *key)
44 {
45 int result;
46
47 lua_pushstring(L, key);
48 lua_gettable(L, -2);
49
50 result = lua_tointeger(L, -1);
51 lua_pop(L, 1);
52
53 return result;
54 }
55
56 /*
57 * This section has functions that convert internal FRR datatypes into Lua
58 * datatypes: one encoder function and two decoder functions for each type.
59 *
60 */
61
62 void lua_pushprefix(lua_State *L, const struct prefix *prefix)
63 {
64 char buffer[PREFIX_STRLEN];
65
66 lua_newtable(L);
67 lua_pushstring(L, prefix2str(prefix, buffer, PREFIX_STRLEN));
68 lua_setfield(L, -2, "network");
69 lua_pushinteger(L, prefix->prefixlen);
70 lua_setfield(L, -2, "length");
71 lua_pushinteger(L, prefix->family);
72 lua_setfield(L, -2, "family");
73 }
74
75 void lua_decode_prefix(lua_State *L, int idx, struct prefix *prefix)
76 {
77 lua_getfield(L, idx, "network");
78 (void)str2prefix(lua_tostring(L, -1), prefix);
79 lua_pop(L, 1);
80 /* pop the table */
81 lua_pop(L, 1);
82 }
83
84 void *lua_toprefix(lua_State *L, int idx)
85 {
86 struct prefix *p = XCALLOC(MTYPE_SCRIPT_RES, sizeof(struct prefix));
87 lua_decode_prefix(L, idx, p);
88 return p;
89 }
90
91 void lua_pushinterface(lua_State *L, const struct interface *ifp)
92 {
93 lua_newtable(L);
94 lua_pushstring(L, ifp->name);
95 lua_setfield(L, -2, "name");
96 lua_pushinteger(L, ifp->ifindex);
97 lua_setfield(L, -2, "ifindex");
98 lua_pushinteger(L, ifp->status);
99 lua_setfield(L, -2, "status");
100 lua_pushinteger(L, ifp->flags);
101 lua_setfield(L, -2, "flags");
102 lua_pushinteger(L, ifp->metric);
103 lua_setfield(L, -2, "metric");
104 lua_pushinteger(L, ifp->speed);
105 lua_setfield(L, -2, "speed");
106 lua_pushinteger(L, ifp->mtu);
107 lua_setfield(L, -2, "mtu");
108 lua_pushinteger(L, ifp->mtu6);
109 lua_setfield(L, -2, "mtu6");
110 lua_pushinteger(L, ifp->bandwidth);
111 lua_setfield(L, -2, "bandwidth");
112 lua_pushinteger(L, ifp->link_ifindex);
113 lua_setfield(L, -2, "link_ifindex");
114 lua_pushinteger(L, ifp->ll_type);
115 lua_setfield(L, -2, "linklayer_type");
116 }
117
118 void lua_decode_interface(lua_State *L, int idx, struct interface *ifp)
119 {
120 lua_getfield(L, idx, "name");
121 strlcpy(ifp->name, lua_tostring(L, -1), sizeof(ifp->name));
122 lua_pop(L, 1);
123 lua_getfield(L, idx, "ifindex");
124 ifp->ifindex = lua_tointeger(L, -1);
125 lua_pop(L, 1);
126 lua_getfield(L, idx, "status");
127 ifp->status = lua_tointeger(L, -1);
128 lua_pop(L, 1);
129 lua_getfield(L, idx, "flags");
130 ifp->flags = lua_tointeger(L, -1);
131 lua_pop(L, 1);
132 lua_getfield(L, idx, "metric");
133 ifp->metric = lua_tointeger(L, -1);
134 lua_pop(L, 1);
135 lua_getfield(L, idx, "speed");
136 ifp->speed = lua_tointeger(L, -1);
137 lua_pop(L, 1);
138 lua_getfield(L, idx, "mtu");
139 ifp->mtu = lua_tointeger(L, -1);
140 lua_pop(L, 1);
141 lua_getfield(L, idx, "mtu6");
142 ifp->mtu6 = lua_tointeger(L, -1);
143 lua_pop(L, 1);
144 lua_getfield(L, idx, "bandwidth");
145 ifp->bandwidth = lua_tointeger(L, -1);
146 lua_pop(L, 1);
147 lua_getfield(L, idx, "link_ifindex");
148 ifp->link_ifindex = lua_tointeger(L, -1);
149 lua_pop(L, 1);
150 lua_getfield(L, idx, "linklayer_type");
151 ifp->ll_type = lua_tointeger(L, -1);
152 lua_pop(L, 1);
153 /* pop the table */
154 lua_pop(L, 1);
155 }
156 void *lua_tointerface(lua_State *L, int idx)
157 {
158 struct interface *ifp =
159 XCALLOC(MTYPE_SCRIPT_RES, sizeof(struct interface));
160
161 lua_decode_interface(L, idx, ifp);
162 return ifp;
163 }
164
165 void lua_pushinaddr(lua_State *L, const struct in_addr *addr)
166 {
167 char buf[INET_ADDRSTRLEN];
168
169 inet_ntop(AF_INET, addr, buf, sizeof(buf));
170
171 lua_newtable(L);
172 lua_pushinteger(L, addr->s_addr);
173 lua_setfield(L, -2, "value");
174 lua_pushstring(L, buf);
175 lua_setfield(L, -2, "string");
176 }
177
178 void lua_decode_inaddr(lua_State *L, int idx, struct in_addr *inaddr)
179 {
180 lua_getfield(L, idx, "value");
181 inaddr->s_addr = lua_tointeger(L, -1);
182 lua_pop(L, 1);
183 /* pop the table */
184 lua_pop(L, 1);
185 }
186
187 void *lua_toinaddr(lua_State *L, int idx)
188 {
189 struct in_addr *inaddr =
190 XCALLOC(MTYPE_SCRIPT_RES, sizeof(struct in_addr));
191 lua_decode_inaddr(L, idx, inaddr);
192 return inaddr;
193 }
194
195
196 void lua_pushin6addr(lua_State *L, const struct in6_addr *addr)
197 {
198 char buf[INET6_ADDRSTRLEN];
199
200 inet_ntop(AF_INET6, addr, buf, sizeof(buf));
201
202 lua_newtable(L);
203 lua_pushlstring(L, (const char *)addr->s6_addr, 16);
204 lua_setfield(L, -2, "value");
205 lua_pushstring(L, buf);
206 lua_setfield(L, -2, "string");
207 }
208
209 void lua_decode_in6addr(lua_State *L, int idx, struct in6_addr *in6addr)
210 {
211 lua_getfield(L, idx, "string");
212 inet_pton(AF_INET6, lua_tostring(L, -1), in6addr);
213 lua_pop(L, 1);
214 /* pop the table */
215 lua_pop(L, 1);
216 }
217
218 void *lua_toin6addr(lua_State *L, int idx)
219 {
220 struct in6_addr *in6addr =
221 XCALLOC(MTYPE_SCRIPT_RES, sizeof(struct in6_addr));
222 lua_decode_in6addr(L, idx, in6addr);
223 return in6addr;
224 }
225
226 void lua_pushsockunion(lua_State *L, const union sockunion *su)
227 {
228 char buf[SU_ADDRSTRLEN];
229
230 sockunion2str(su, buf, sizeof(buf));
231
232 lua_newtable(L);
233 lua_pushlstring(L, (const char *)sockunion_get_addr(su),
234 sockunion_get_addrlen(su));
235 lua_setfield(L, -2, "value");
236 lua_pushstring(L, buf);
237 lua_setfield(L, -2, "string");
238 }
239
240 void lua_decode_sockunion(lua_State *L, int idx, union sockunion *su)
241 {
242 lua_getfield(L, idx, "string");
243 (void)str2sockunion(lua_tostring(L, -1), su);
244 lua_pop(L, 1);
245 /* pop the table */
246 lua_pop(L, 1);
247 }
248
249 void *lua_tosockunion(lua_State *L, int idx)
250 {
251 union sockunion *su =
252 XCALLOC(MTYPE_SCRIPT_RES, sizeof(union sockunion));
253
254 lua_decode_sockunion(L, idx, su);
255 return su;
256 }
257
258 void lua_pushtimet(lua_State *L, const time_t *time)
259 {
260 lua_pushinteger(L, *time);
261 }
262
263 void lua_decode_timet(lua_State *L, int idx, time_t *t)
264 {
265 *t = lua_tointeger(L, idx);
266 lua_pop(L, 1);
267 }
268
269 void *lua_totimet(lua_State *L, int idx)
270 {
271 time_t *t = XCALLOC(MTYPE_SCRIPT_RES, sizeof(time_t));
272
273 lua_decode_timet(L, idx, t);
274 return t;
275 }
276
277 void lua_pushintegerp(lua_State *L, const long long *num)
278 {
279 lua_pushinteger(L, *num);
280 }
281
282 void lua_decode_integerp(lua_State *L, int idx, long long *num)
283 {
284 int isnum;
285 *num = lua_tonumberx(L, idx, &isnum);
286 lua_pop(L, 1);
287 assert(isnum);
288 }
289
290 void *lua_tointegerp(lua_State *L, int idx)
291 {
292 long long *num = XCALLOC(MTYPE_SCRIPT_RES, sizeof(long long));
293
294 lua_decode_integerp(L, idx, num);
295 return num;
296 }
297
298 void lua_decode_stringp(lua_State *L, int idx, char *str)
299 {
300 strlcpy(str, lua_tostring(L, idx), strlen(str) + 1);
301 lua_pop(L, 1);
302 }
303
304 void *lua_tostringp(lua_State *L, int idx)
305 {
306 char *string = XSTRDUP(MTYPE_SCRIPT_RES, lua_tostring(L, idx));
307
308 return string;
309 }
310
311 /*
312 * Decoder for const values, since we cannot modify them.
313 */
314 void lua_decode_noop(lua_State *L, int idx, const void *ptr)
315 {
316 }
317
318
319 /*
320 * Noop decoder for int.
321 */
322 void lua_decode_integer_noop(lua_State *L, int idx, int i)
323 {
324 }
325
326 /*
327 * Logging.
328 *
329 * Lua-compatible wrappers for FRR logging functions.
330 */
331 static const char *frrlua_log_thunk(lua_State *L)
332 {
333 int nargs;
334
335 nargs = lua_gettop(L);
336 assert(nargs == 1);
337
338 return lua_tostring(L, 1);
339 }
340
341 static int frrlua_log_debug(lua_State *L)
342 {
343 zlog_debug("%s", frrlua_log_thunk(L));
344 return 0;
345 }
346
347 static int frrlua_log_info(lua_State *L)
348 {
349 zlog_info("%s", frrlua_log_thunk(L));
350 return 0;
351 }
352
353 static int frrlua_log_notice(lua_State *L)
354 {
355 zlog_notice("%s", frrlua_log_thunk(L));
356 return 0;
357 }
358
359 static int frrlua_log_warn(lua_State *L)
360 {
361 zlog_warn("%s", frrlua_log_thunk(L));
362 return 0;
363 }
364
365 static int frrlua_log_error(lua_State *L)
366 {
367 zlog_err("%s", frrlua_log_thunk(L));
368 return 0;
369 }
370
371 static const luaL_Reg log_funcs[] = {
372 {"debug", frrlua_log_debug},
373 {"info", frrlua_log_info},
374 {"notice", frrlua_log_notice},
375 {"warn", frrlua_log_warn},
376 {"error", frrlua_log_error},
377 {},
378 };
379
380 void frrlua_export_logging(lua_State *L)
381 {
382 lua_newtable(L);
383 luaL_setfuncs(L, log_funcs, 0);
384 lua_setglobal(L, "log");
385 }
386
387 /*
388 * Debugging.
389 */
390
391 char *frrlua_stackdump(lua_State *L)
392 {
393 int top = lua_gettop(L);
394
395 char tmpbuf[64];
396 struct buffer *buf = buffer_new(4098);
397
398 for (int i = 1; i <= top; i++) {
399 int t = lua_type(L, i);
400
401 switch (t) {
402 case LUA_TSTRING: /* strings */
403 snprintf(tmpbuf, sizeof(tmpbuf), "\"%s\"\n",
404 lua_tostring(L, i));
405 buffer_putstr(buf, tmpbuf);
406 break;
407 case LUA_TBOOLEAN: /* booleans */
408 snprintf(tmpbuf, sizeof(tmpbuf), "%s\n",
409 lua_toboolean(L, i) ? "true" : "false");
410 buffer_putstr(buf, tmpbuf);
411 break;
412 case LUA_TNUMBER: /* numbers */
413 snprintf(tmpbuf, sizeof(tmpbuf), "%g\n",
414 lua_tonumber(L, i));
415 buffer_putstr(buf, tmpbuf);
416 break;
417 default: /* other values */
418 snprintf(tmpbuf, sizeof(tmpbuf), "%s\n",
419 lua_typename(L, t));
420 buffer_putstr(buf, tmpbuf);
421 break;
422 }
423 }
424
425 char *result = XSTRDUP(MTYPE_TMP, buffer_getstr(buf));
426
427 buffer_free(buf);
428
429 return result;
430 }
431
432 #endif /* HAVE_SCRIPTING */