]> git.proxmox.com Git - mirror_frr.git/blame - lib/frrlua.c
bgpd: update routemap scripting example
[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 */
634949ae
DS
22#include <zebra.h>
23
24#if defined(HAVE_LUA)
25#include "prefix.h"
5dbb0a7b 26#include "frrlua.h"
634949ae 27#include "log.h"
e93f19fb 28#include "buffer.h"
5f98c815
QY
29
30/* Lua stuff */
634949ae 31
60219659
QY
32/*
33 * FRR convenience functions.
34 *
35 * This section has convenience functions used to make interacting with the Lua
36 * stack easier.
37 */
38
60219659 39int frrlua_table_get_integer(lua_State *L, const char *key)
634949ae
DS
40{
41 int result;
42
43 lua_pushstring(L, key);
44 lua_gettable(L, -2);
45
46 result = lua_tointeger(L, -1);
47 lua_pop(L, 1);
48
49 return result;
50}
51
60219659
QY
52/*
53 * Encoders.
54 *
55 * This section has functions that convert internal FRR datatypes into Lua
56 * datatypes.
57 */
634949ae 58
47dd8736 59void lua_pushprefix(lua_State *L, const struct prefix *prefix)
634949ae
DS
60{
61 char buffer[100];
62
60219659
QY
63 zlog_debug("frrlua: pushing prefix table");
64
634949ae
DS
65 lua_newtable(L);
66 lua_pushstring(L, prefix2str(prefix, buffer, 100));
00d9e83a
QY
67 lua_setfield(L, -2, "network");
68 lua_pushinteger(L, prefix->prefixlen);
69 lua_setfield(L, -2, "length");
634949ae
DS
70 lua_pushinteger(L, prefix->family);
71 lua_setfield(L, -2, "family");
634949ae
DS
72}
73
f869ab17
QY
74void *lua_toprefix(lua_State *L, int idx)
75{
76 struct prefix *p = XCALLOC(MTYPE_TMP, sizeof(struct prefix));
77
78 lua_getfield(L, idx, "network");
79 str2prefix(lua_tostring(L, -1), p);
80 lua_pop(L, 1);
81
82 return p;
83}
84
47dd8736 85void lua_pushinterface(lua_State *L, const struct interface *ifp)
cd6ca660
QY
86{
87 zlog_debug("frrlua: pushing interface table");
88
89 lua_newtable(L);
90 lua_pushstring(L, ifp->name);
91 lua_setfield(L, -2, "name");
92 lua_pushinteger(L, ifp->ifindex);
93 lua_setfield(L, -2, "ifindex");
94 lua_pushinteger(L, ifp->status);
95 lua_setfield(L, -2, "status");
96 lua_pushinteger(L, ifp->flags);
97 lua_setfield(L, -2, "flags");
98 lua_pushinteger(L, ifp->metric);
99 lua_setfield(L, -2, "metric");
100 lua_pushinteger(L, ifp->speed);
101 lua_setfield(L, -2, "speed");
102 lua_pushinteger(L, ifp->mtu);
103 lua_setfield(L, -2, "mtu");
104 lua_pushinteger(L, ifp->mtu6);
105 lua_setfield(L, -2, "mtu6");
106 lua_pushinteger(L, ifp->bandwidth);
107 lua_setfield(L, -2, "bandwidth");
108 lua_pushinteger(L, ifp->link_ifindex);
109 lua_setfield(L, -2, "link_ifindex");
110 lua_pushinteger(L, ifp->ll_type);
111 lua_setfield(L, -2, "linklayer_type");
112}
113
f869ab17
QY
114void *lua_tointerface(lua_State *L, int idx)
115{
116 struct interface *ifp = XCALLOC(MTYPE_TMP, sizeof(struct interface));
117
118 lua_getfield(L, idx, "name");
119 strlcpy(ifp->name, lua_tostring(L, -1), sizeof(ifp->name));
120 lua_pop(L, 1);
121 lua_getfield(L, idx, "ifindex");
122 ifp->ifindex = lua_tointeger(L, -1);
123 lua_pop(L, 1);
124 lua_getfield(L, idx, "status");
125 ifp->status = lua_tointeger(L, -1);
126 lua_pop(L, 1);
127 lua_getfield(L, idx, "flags");
128 ifp->flags = lua_tointeger(L, -1);
129 lua_pop(L, 1);
130 lua_getfield(L, idx, "metric");
131 ifp->metric = lua_tointeger(L, -1);
132 lua_pop(L, 1);
133 lua_getfield(L, idx, "speed");
134 ifp->speed = lua_tointeger(L, -1);
135 lua_pop(L, 1);
136 lua_getfield(L, idx, "mtu");
137 ifp->mtu = lua_tointeger(L, -1);
138 lua_pop(L, 1);
139 lua_getfield(L, idx, "mtu6");
140 ifp->mtu6 = lua_tointeger(L, -1);
141 lua_pop(L, 1);
142 lua_getfield(L, idx, "bandwidth");
143 ifp->bandwidth = lua_tointeger(L, -1);
144 lua_pop(L, 1);
145 lua_getfield(L, idx, "link_ifindex");
146 ifp->link_ifindex = lua_tointeger(L, -1);
147 lua_pop(L, 1);
148 lua_getfield(L, idx, "linklayer_type");
149 ifp->ll_type = lua_tointeger(L, -1);
150 lua_pop(L, 1);
151
152 return ifp;
153}
154
47dd8736 155void lua_pushinaddr(lua_State *L, const struct in_addr *addr)
42ae55b5
QY
156{
157 zlog_debug("frrlua: pushing inaddr table");
158
159 char buf[INET_ADDRSTRLEN];
160 inet_ntop(AF_INET, addr, buf, sizeof(buf));
161
162 lua_newtable(L);
163 lua_pushinteger(L, addr->s_addr);
164 lua_setfield(L, -2, "value");
165 lua_pushstring(L, buf);
166 lua_setfield(L, -2, "string");
42ae55b5
QY
167}
168
f869ab17
QY
169void *lua_toinaddr(lua_State *L, int idx)
170{
171 struct in_addr *inaddr = XCALLOC(MTYPE_TMP, sizeof(struct in_addr));
172
173 lua_getfield(L, idx, "value");
174 inaddr->s_addr = lua_tointeger(L, -1);
175 lua_pop(L, 1);
176
177 return inaddr;
178}
179
42ae55b5 180
47dd8736 181void lua_pushin6addr(lua_State *L, const struct in6_addr *addr)
42ae55b5
QY
182{
183 zlog_debug("frrlua: pushing in6addr table");
184
185 char buf[INET6_ADDRSTRLEN];
186 inet_ntop(AF_INET6, addr, buf, sizeof(buf));
187
188 lua_newtable(L);
189 lua_pushlstring(L, (const char *)addr->s6_addr, 16);
190 lua_setfield(L, -2, "value");
191 lua_pushstring(L, buf);
192 lua_setfield(L, -2, "string");
42ae55b5
QY
193}
194
f869ab17
QY
195void *lua_toin6addr(lua_State *L, int idx)
196{
197 struct in6_addr *in6addr = XCALLOC(MTYPE_TMP, sizeof(struct in6_addr));
198
199 lua_getfield(L, idx, "string");
200 inet_pton(AF_INET6, lua_tostring(L, -1), in6addr);
201 lua_pop(L, 1);
202
203 return in6addr;
204}
205
47dd8736 206void lua_pushsockunion(lua_State *L, const union sockunion *su)
42ae55b5
QY
207{
208 zlog_debug("frrlua: pushing sockunion table");
209
210 char buf[SU_ADDRSTRLEN];
211 sockunion2str(su, buf, sizeof(buf));
212
213 lua_newtable(L);
214 lua_pushlstring(L, (const char *)sockunion_get_addr(su),
215 sockunion_get_addrlen(su));
216 lua_setfield(L, -2, "value");
217 lua_pushstring(L, buf);
218 lua_setfield(L, -2, "string");
42ae55b5
QY
219}
220
f869ab17
QY
221void *lua_tosockunion(lua_State *L, int idx)
222{
223 union sockunion *su = XCALLOC(MTYPE_TMP, sizeof(union sockunion));
224
225 lua_getfield(L, idx, "string");
226 str2sockunion(lua_tostring(L, -1), su);
227
228 return su;
229}
230
47dd8736 231void lua_pushtimet(lua_State *L, const time_t *time)
42ae55b5
QY
232{
233 lua_pushinteger(L, *time);
42ae55b5
QY
234}
235
f869ab17
QY
236void *lua_totimet(lua_State *L, int idx)
237{
238 time_t *t = XCALLOC(MTYPE_TMP, sizeof(time_t));
239
240 *t = lua_tointeger(L, idx);
241
242 return t;
243}
244
245void lua_pushintegerp(lua_State *L, const long long *num)
eeb61724
QY
246{
247 lua_pushinteger(L, *num);
248}
249
f869ab17
QY
250void *lua_tointegerp(lua_State *L, int idx)
251{
252 int isnum;
253 long long *num = XCALLOC(MTYPE_TMP, sizeof(long long));
254
255 *num = lua_tonumberx(L, idx, &isnum);
256 assert(isnum);
257
258 return num;
259}
260
261void *lua_tostringp(lua_State *L, int idx)
262{
263 char *string = XSTRDUP(MTYPE_TMP, lua_tostring(L, idx));
264
265 return string;
266}
267
d473bdc7
QY
268/*
269 * Logging.
270 *
271 * Lua-compatible wrappers for FRR logging functions.
272 */
273static const char *frrlua_log_thunk(lua_State *L)
274{
275 int nargs;
276
277 nargs = lua_gettop(L);
278 assert(nargs == 1);
279
280 return lua_tostring(L, 1);
281}
282
283static int frrlua_log_debug(lua_State *L)
284{
285 zlog_debug("%s", frrlua_log_thunk(L));
286 return 0;
287}
288
289static int frrlua_log_info(lua_State *L)
290{
291 zlog_info("%s", frrlua_log_thunk(L));
292 return 0;
293}
294
295static int frrlua_log_notice(lua_State *L)
296{
297 zlog_notice("%s", frrlua_log_thunk(L));
298 return 0;
299}
300
301static int frrlua_log_warn(lua_State *L)
302{
303 zlog_warn("%s", frrlua_log_thunk(L));
304 return 0;
305}
306
307static int frrlua_log_error(lua_State *L)
308{
309 zlog_err("%s", frrlua_log_thunk(L));
310 return 0;
311}
312
313static const luaL_Reg log_funcs[] = {
314 {"debug", frrlua_log_debug},
315 {"info", frrlua_log_info},
316 {"notice", frrlua_log_notice},
317 {"warn", frrlua_log_warn},
318 {"error", frrlua_log_error},
319 {},
320};
321
322void frrlua_export_logging(lua_State *L)
323{
324 lua_newtable(L);
325 luaL_setfuncs(L, log_funcs, 0);
a3ce06c4 326 lua_setglobal(L, "log");
d473bdc7
QY
327}
328
e93f19fb
QY
329/*
330 * Debugging.
331 */
332
333char *frrlua_stackdump(lua_State *L)
334{
335 int top = lua_gettop(L);
336
337 char tmpbuf[64];
338 struct buffer *buf = buffer_new(4098);
339
340 for (int i = 1; i <= top; i++) {
341 int t = lua_type(L, i);
342
343 switch (t) {
344 case LUA_TSTRING: /* strings */
345 snprintf(tmpbuf, sizeof(tmpbuf), "\"%s\"\n",
346 lua_tostring(L, i));
347 buffer_putstr(buf, tmpbuf);
348 break;
349 case LUA_TBOOLEAN: /* booleans */
350 snprintf(tmpbuf, sizeof(tmpbuf), "%s\n",
351 lua_toboolean(L, i) ? "true" : "false");
352 buffer_putstr(buf, tmpbuf);
353 break;
354 case LUA_TNUMBER: /* numbers */
355 snprintf(tmpbuf, sizeof(tmpbuf), "%g\n",
356 lua_tonumber(L, i));
357 buffer_putstr(buf, tmpbuf);
358 break;
359 default: /* other values */
360 snprintf(tmpbuf, sizeof(tmpbuf), "%s\n",
361 lua_typename(L, t));
362 buffer_putstr(buf, tmpbuf);
363 break;
364 }
365 }
366
367 char *result = XSTRDUP(MTYPE_TMP, buffer_getstr(buf));
368
369 buffer_free(buf);
370
371 return result;
372}
373
634949ae 374#endif