]> git.proxmox.com Git - mirror_frr.git/blame - lib/frrlua.c
Merge pull request #13278 from FRRouting/mergify/bp/stable/8.5/pr-13269
[mirror_frr.git] / lib / frrlua.c
CommitLineData
634949ae
DS
1/*
2 * This file defines the lua interface into
3 * FRRouting.
4 *
60219659
QY
5 * Copyright (C) 2016-2019 Cumulus Networks, Inc.
6 * Donald Sharp, Quentin Young
634949ae 7 *
60219659
QY
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.
634949ae 12 *
60219659
QY
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.
634949ae
DS
17 *
18 * You should have received a copy of the GNU General Public License along
60219659
QY
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
634949ae 21 */
fa22080d 22
634949ae
DS
23#include <zebra.h>
24
fa22080d
QY
25#ifdef HAVE_SCRIPTING
26
634949ae 27#include "prefix.h"
5dbb0a7b 28#include "frrlua.h"
634949ae 29#include "log.h"
e93f19fb 30#include "buffer.h"
5f98c815 31
78f1ac25
DL
32DEFINE_MTYPE(LIB, SCRIPT_RES, "Scripting results");
33
5f98c815 34/* Lua stuff */
634949ae 35
60219659
QY
36/*
37 * FRR convenience functions.
38 *
39 * This section has convenience functions used to make interacting with the Lua
40 * stack easier.
41 */
42
60219659 43int frrlua_table_get_integer(lua_State *L, const char *key)
634949ae
DS
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
60219659 56/*
60219659 57 * This section has functions that convert internal FRR datatypes into Lua
19eee398
DL
58 * datatypes: one encoder function and two decoder functions for each type.
59 *
60219659 60 */
634949ae 61
47dd8736 62void lua_pushprefix(lua_State *L, const struct prefix *prefix)
634949ae 63{
bf6e7265 64 char buffer[PREFIX_STRLEN];
634949ae
DS
65
66 lua_newtable(L);
bf6e7265 67 lua_pushstring(L, prefix2str(prefix, buffer, PREFIX_STRLEN));
00d9e83a
QY
68 lua_setfield(L, -2, "network");
69 lua_pushinteger(L, prefix->prefixlen);
70 lua_setfield(L, -2, "length");
634949ae
DS
71 lua_pushinteger(L, prefix->family);
72 lua_setfield(L, -2, "family");
634949ae
DS
73}
74
3a3cfe47 75void lua_decode_prefix(lua_State *L, int idx, struct prefix *prefix)
f869ab17 76{
f869ab17 77 lua_getfield(L, idx, "network");
3a3cfe47 78 (void)str2prefix(lua_tostring(L, -1), prefix);
f869ab17 79 lua_pop(L, 1);
8192b471
DL
80 /* pop the table */
81 lua_pop(L, 1);
3a3cfe47 82}
f869ab17 83
3a3cfe47
DL
84void *lua_toprefix(lua_State *L, int idx)
85{
78f1ac25 86 struct prefix *p = XCALLOC(MTYPE_SCRIPT_RES, sizeof(struct prefix));
3a3cfe47 87 lua_decode_prefix(L, idx, p);
f869ab17
QY
88 return p;
89}
90
47dd8736 91void lua_pushinterface(lua_State *L, const struct interface *ifp)
cd6ca660 92{
cd6ca660
QY
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
3a3cfe47 118void lua_decode_interface(lua_State *L, int idx, struct interface *ifp)
f869ab17 119{
f869ab17
QY
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);
8192b471
DL
153 /* pop the table */
154 lua_pop(L, 1);
3a3cfe47
DL
155}
156void *lua_tointerface(lua_State *L, int idx)
157{
78f1ac25
DL
158 struct interface *ifp =
159 XCALLOC(MTYPE_SCRIPT_RES, sizeof(struct interface));
f869ab17 160
3a3cfe47 161 lua_decode_interface(L, idx, ifp);
f869ab17
QY
162 return ifp;
163}
164
47dd8736 165void lua_pushinaddr(lua_State *L, const struct in_addr *addr)
42ae55b5 166{
42ae55b5 167 char buf[INET_ADDRSTRLEN];
3a3cfe47 168
42ae55b5
QY
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");
42ae55b5
QY
176}
177
3a3cfe47 178void lua_decode_inaddr(lua_State *L, int idx, struct in_addr *inaddr)
f869ab17 179{
f869ab17
QY
180 lua_getfield(L, idx, "value");
181 inaddr->s_addr = lua_tointeger(L, -1);
182 lua_pop(L, 1);
8192b471
DL
183 /* pop the table */
184 lua_pop(L, 1);
3a3cfe47 185}
f869ab17 186
3a3cfe47
DL
187void *lua_toinaddr(lua_State *L, int idx)
188{
78f1ac25
DL
189 struct in_addr *inaddr =
190 XCALLOC(MTYPE_SCRIPT_RES, sizeof(struct in_addr));
3a3cfe47 191 lua_decode_inaddr(L, idx, inaddr);
f869ab17
QY
192 return inaddr;
193}
194
42ae55b5 195
47dd8736 196void lua_pushin6addr(lua_State *L, const struct in6_addr *addr)
42ae55b5 197{
42ae55b5 198 char buf[INET6_ADDRSTRLEN];
3a3cfe47 199
42ae55b5
QY
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");
42ae55b5
QY
207}
208
3a3cfe47 209void lua_decode_in6addr(lua_State *L, int idx, struct in6_addr *in6addr)
f869ab17 210{
f869ab17
QY
211 lua_getfield(L, idx, "string");
212 inet_pton(AF_INET6, lua_tostring(L, -1), in6addr);
213 lua_pop(L, 1);
8192b471
DL
214 /* pop the table */
215 lua_pop(L, 1);
3a3cfe47 216}
f869ab17 217
3a3cfe47
DL
218void *lua_toin6addr(lua_State *L, int idx)
219{
78f1ac25
DL
220 struct in6_addr *in6addr =
221 XCALLOC(MTYPE_SCRIPT_RES, sizeof(struct in6_addr));
3a3cfe47 222 lua_decode_in6addr(L, idx, in6addr);
f869ab17
QY
223 return in6addr;
224}
225
e6f42b94
DL
226void lua_pushipaddr(lua_State *L, const struct ipaddr *addr)
227{
228 if (IS_IPADDR_V4(addr))
229 lua_pushinaddr(L, &addr->ipaddr_v4);
230 else
231 lua_pushin6addr(L, &addr->ipaddr_v6);
232}
233
234void lua_pushethaddr(lua_State *L, const struct ethaddr *addr)
235{
236 lua_newtable(L);
237 lua_pushinteger(L, *(addr->octet));
238 lua_setfield(L, -2, "octet");
239}
240
47dd8736 241void lua_pushsockunion(lua_State *L, const union sockunion *su)
42ae55b5 242{
42ae55b5 243 char buf[SU_ADDRSTRLEN];
3a3cfe47 244
42ae55b5
QY
245 sockunion2str(su, buf, sizeof(buf));
246
247 lua_newtable(L);
248 lua_pushlstring(L, (const char *)sockunion_get_addr(su),
249 sockunion_get_addrlen(su));
250 lua_setfield(L, -2, "value");
251 lua_pushstring(L, buf);
252 lua_setfield(L, -2, "string");
42ae55b5
QY
253}
254
3a3cfe47 255void lua_decode_sockunion(lua_State *L, int idx, union sockunion *su)
f869ab17 256{
f869ab17 257 lua_getfield(L, idx, "string");
0db2bfc5 258 if (str2sockunion(lua_tostring(L, -1), su) < 0)
a852e5a6 259 zlog_err("Lua hook call: Failed to decode sockunion");
0db2bfc5 260
8192b471
DL
261 lua_pop(L, 1);
262 /* pop the table */
263 lua_pop(L, 1);
3a3cfe47
DL
264}
265
266void *lua_tosockunion(lua_State *L, int idx)
267{
78f1ac25
DL
268 union sockunion *su =
269 XCALLOC(MTYPE_SCRIPT_RES, sizeof(union sockunion));
f869ab17 270
3a3cfe47 271 lua_decode_sockunion(L, idx, su);
f869ab17
QY
272 return su;
273}
274
47dd8736 275void lua_pushtimet(lua_State *L, const time_t *time)
42ae55b5
QY
276{
277 lua_pushinteger(L, *time);
42ae55b5
QY
278}
279
3a3cfe47
DL
280void lua_decode_timet(lua_State *L, int idx, time_t *t)
281{
282 *t = lua_tointeger(L, idx);
8192b471 283 lua_pop(L, 1);
3a3cfe47
DL
284}
285
f869ab17
QY
286void *lua_totimet(lua_State *L, int idx)
287{
78f1ac25 288 time_t *t = XCALLOC(MTYPE_SCRIPT_RES, sizeof(time_t));
f869ab17 289
3a3cfe47 290 lua_decode_timet(L, idx, t);
f869ab17
QY
291 return t;
292}
293
294void lua_pushintegerp(lua_State *L, const long long *num)
eeb61724
QY
295{
296 lua_pushinteger(L, *num);
297}
298
3a3cfe47 299void lua_decode_integerp(lua_State *L, int idx, long long *num)
f869ab17
QY
300{
301 int isnum;
f869ab17 302 *num = lua_tonumberx(L, idx, &isnum);
8192b471 303 lua_pop(L, 1);
f869ab17 304 assert(isnum);
3a3cfe47
DL
305}
306
307void *lua_tointegerp(lua_State *L, int idx)
308{
78f1ac25 309 long long *num = XCALLOC(MTYPE_SCRIPT_RES, sizeof(long long));
f869ab17 310
3a3cfe47 311 lua_decode_integerp(L, idx, num);
f869ab17
QY
312 return num;
313}
314
9b851b74
DL
315void lua_pushnexthop(lua_State *L, const struct nexthop *nexthop)
316{
317 lua_newtable(L);
318 lua_pushinteger(L, nexthop->vrf_id);
319 lua_setfield(L, -2, "vrf_id");
320 lua_pushinteger(L, nexthop->ifindex);
321 lua_setfield(L, -2, "ifindex");
322 lua_pushinteger(L, nexthop->type);
323 lua_setfield(L, -2, "type");
324 lua_pushinteger(L, nexthop->flags);
325 lua_setfield(L, -2, "flags");
326 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) {
327 lua_pushinteger(L, nexthop->bh_type);
328 lua_setfield(L, -2, "bh_type");
329 } else if (nexthop->type == NEXTHOP_TYPE_IPV4) {
330 lua_pushinaddr(L, &nexthop->gate.ipv4);
331 lua_setfield(L, -2, "gate");
332 } else if (nexthop->type == NEXTHOP_TYPE_IPV6) {
333 lua_pushin6addr(L, &nexthop->gate.ipv6);
334 lua_setfield(L, -2, "gate");
335 }
336 lua_pushinteger(L, nexthop->nh_label_type);
337 lua_setfield(L, -2, "nh_label_type");
338 lua_pushinteger(L, nexthop->weight);
339 lua_setfield(L, -2, "weight");
340 lua_pushinteger(L, nexthop->backup_num);
341 lua_setfield(L, -2, "backup_num");
342 lua_pushinteger(L, *(nexthop->backup_idx));
343 lua_setfield(L, -2, "backup_idx");
344 if (nexthop->nh_encap_type == NET_VXLAN) {
345 lua_pushinteger(L, nexthop->nh_encap.vni);
346 lua_setfield(L, -2, "vni");
347 }
348 lua_pushinteger(L, nexthop->nh_encap_type);
349 lua_setfield(L, -2, "nh_encap_type");
350 lua_pushinteger(L, nexthop->srte_color);
351 lua_setfield(L, -2, "srte_color");
352}
353
354void lua_pushnexthop_group(lua_State *L, const struct nexthop_group *ng)
355{
356 lua_newtable(L);
357 struct nexthop *nexthop;
358 int i = 0;
359
360 for (ALL_NEXTHOPS_PTR(ng, nexthop)) {
361 lua_pushnexthop(L, nexthop);
362 lua_seti(L, -2, i);
363 i++;
364 }
365}
366
3a3cfe47
DL
367void lua_decode_stringp(lua_State *L, int idx, char *str)
368{
369 strlcpy(str, lua_tostring(L, idx), strlen(str) + 1);
370 lua_pop(L, 1);
371}
372
f869ab17
QY
373void *lua_tostringp(lua_State *L, int idx)
374{
78f1ac25 375 char *string = XSTRDUP(MTYPE_SCRIPT_RES, lua_tostring(L, idx));
f869ab17
QY
376
377 return string;
378}
379
19eee398
DL
380/*
381 * Decoder for const values, since we cannot modify them.
382 */
7e058da5
DL
383void lua_decode_noop(lua_State *L, int idx, const void *ptr)
384{
385}
386
2b67227e
DL
387
388/*
389 * Noop decoder for int.
390 */
36cf58c7 391void lua_decode_integer_noop(lua_State *L, int idx, int i)
2b67227e
DL
392{
393}
394
d473bdc7
QY
395/*
396 * Logging.
397 *
398 * Lua-compatible wrappers for FRR logging functions.
399 */
400static const char *frrlua_log_thunk(lua_State *L)
401{
402 int nargs;
403
404 nargs = lua_gettop(L);
405 assert(nargs == 1);
406
407 return lua_tostring(L, 1);
408}
409
410static int frrlua_log_debug(lua_State *L)
411{
412 zlog_debug("%s", frrlua_log_thunk(L));
413 return 0;
414}
415
416static int frrlua_log_info(lua_State *L)
417{
418 zlog_info("%s", frrlua_log_thunk(L));
419 return 0;
420}
421
422static int frrlua_log_notice(lua_State *L)
423{
424 zlog_notice("%s", frrlua_log_thunk(L));
425 return 0;
426}
427
428static int frrlua_log_warn(lua_State *L)
429{
430 zlog_warn("%s", frrlua_log_thunk(L));
431 return 0;
432}
433
434static int frrlua_log_error(lua_State *L)
435{
436 zlog_err("%s", frrlua_log_thunk(L));
437 return 0;
438}
439
440static const luaL_Reg log_funcs[] = {
441 {"debug", frrlua_log_debug},
442 {"info", frrlua_log_info},
443 {"notice", frrlua_log_notice},
444 {"warn", frrlua_log_warn},
445 {"error", frrlua_log_error},
446 {},
447};
448
449void frrlua_export_logging(lua_State *L)
450{
451 lua_newtable(L);
452 luaL_setfuncs(L, log_funcs, 0);
a3ce06c4 453 lua_setglobal(L, "log");
d473bdc7
QY
454}
455
e93f19fb
QY
456/*
457 * Debugging.
458 */
459
460char *frrlua_stackdump(lua_State *L)
461{
462 int top = lua_gettop(L);
463
464 char tmpbuf[64];
465 struct buffer *buf = buffer_new(4098);
466
467 for (int i = 1; i <= top; i++) {
468 int t = lua_type(L, i);
469
470 switch (t) {
471 case LUA_TSTRING: /* strings */
472 snprintf(tmpbuf, sizeof(tmpbuf), "\"%s\"\n",
473 lua_tostring(L, i));
474 buffer_putstr(buf, tmpbuf);
475 break;
476 case LUA_TBOOLEAN: /* booleans */
477 snprintf(tmpbuf, sizeof(tmpbuf), "%s\n",
478 lua_toboolean(L, i) ? "true" : "false");
479 buffer_putstr(buf, tmpbuf);
480 break;
481 case LUA_TNUMBER: /* numbers */
482 snprintf(tmpbuf, sizeof(tmpbuf), "%g\n",
483 lua_tonumber(L, i));
484 buffer_putstr(buf, tmpbuf);
485 break;
486 default: /* other values */
487 snprintf(tmpbuf, sizeof(tmpbuf), "%s\n",
488 lua_typename(L, t));
489 buffer_putstr(buf, tmpbuf);
490 break;
491 }
492 }
493
494 char *result = XSTRDUP(MTYPE_TMP, buffer_getstr(buf));
495
496 buffer_free(buf);
497
498 return result;
499}
500
fa22080d 501#endif /* HAVE_SCRIPTING */