]> git.proxmox.com Git - mirror_frr.git/blob - lib/frrlua.c
Merge pull request #9457 from anlancs/ospf6-void
[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 if (str2sockunion(lua_tostring(L, -1), su) < 0)
244 zlog_err("Lua hook call: Failed to decode sockunion");
245
246 lua_pop(L, 1);
247 /* pop the table */
248 lua_pop(L, 1);
249 }
250
251 void *lua_tosockunion(lua_State *L, int idx)
252 {
253 union sockunion *su =
254 XCALLOC(MTYPE_SCRIPT_RES, sizeof(union sockunion));
255
256 lua_decode_sockunion(L, idx, su);
257 return su;
258 }
259
260 void lua_pushtimet(lua_State *L, const time_t *time)
261 {
262 lua_pushinteger(L, *time);
263 }
264
265 void lua_decode_timet(lua_State *L, int idx, time_t *t)
266 {
267 *t = lua_tointeger(L, idx);
268 lua_pop(L, 1);
269 }
270
271 void *lua_totimet(lua_State *L, int idx)
272 {
273 time_t *t = XCALLOC(MTYPE_SCRIPT_RES, sizeof(time_t));
274
275 lua_decode_timet(L, idx, t);
276 return t;
277 }
278
279 void lua_pushintegerp(lua_State *L, const long long *num)
280 {
281 lua_pushinteger(L, *num);
282 }
283
284 void lua_decode_integerp(lua_State *L, int idx, long long *num)
285 {
286 int isnum;
287 *num = lua_tonumberx(L, idx, &isnum);
288 lua_pop(L, 1);
289 assert(isnum);
290 }
291
292 void *lua_tointegerp(lua_State *L, int idx)
293 {
294 long long *num = XCALLOC(MTYPE_SCRIPT_RES, sizeof(long long));
295
296 lua_decode_integerp(L, idx, num);
297 return num;
298 }
299
300 void lua_decode_stringp(lua_State *L, int idx, char *str)
301 {
302 strlcpy(str, lua_tostring(L, idx), strlen(str) + 1);
303 lua_pop(L, 1);
304 }
305
306 void *lua_tostringp(lua_State *L, int idx)
307 {
308 char *string = XSTRDUP(MTYPE_SCRIPT_RES, lua_tostring(L, idx));
309
310 return string;
311 }
312
313 /*
314 * Decoder for const values, since we cannot modify them.
315 */
316 void lua_decode_noop(lua_State *L, int idx, const void *ptr)
317 {
318 }
319
320
321 /*
322 * Noop decoder for int.
323 */
324 void lua_decode_integer_noop(lua_State *L, int idx, int i)
325 {
326 }
327
328 /*
329 * Logging.
330 *
331 * Lua-compatible wrappers for FRR logging functions.
332 */
333 static const char *frrlua_log_thunk(lua_State *L)
334 {
335 int nargs;
336
337 nargs = lua_gettop(L);
338 assert(nargs == 1);
339
340 return lua_tostring(L, 1);
341 }
342
343 static int frrlua_log_debug(lua_State *L)
344 {
345 zlog_debug("%s", frrlua_log_thunk(L));
346 return 0;
347 }
348
349 static int frrlua_log_info(lua_State *L)
350 {
351 zlog_info("%s", frrlua_log_thunk(L));
352 return 0;
353 }
354
355 static int frrlua_log_notice(lua_State *L)
356 {
357 zlog_notice("%s", frrlua_log_thunk(L));
358 return 0;
359 }
360
361 static int frrlua_log_warn(lua_State *L)
362 {
363 zlog_warn("%s", frrlua_log_thunk(L));
364 return 0;
365 }
366
367 static int frrlua_log_error(lua_State *L)
368 {
369 zlog_err("%s", frrlua_log_thunk(L));
370 return 0;
371 }
372
373 static const luaL_Reg log_funcs[] = {
374 {"debug", frrlua_log_debug},
375 {"info", frrlua_log_info},
376 {"notice", frrlua_log_notice},
377 {"warn", frrlua_log_warn},
378 {"error", frrlua_log_error},
379 {},
380 };
381
382 void frrlua_export_logging(lua_State *L)
383 {
384 lua_newtable(L);
385 luaL_setfuncs(L, log_funcs, 0);
386 lua_setglobal(L, "log");
387 }
388
389 /*
390 * Debugging.
391 */
392
393 char *frrlua_stackdump(lua_State *L)
394 {
395 int top = lua_gettop(L);
396
397 char tmpbuf[64];
398 struct buffer *buf = buffer_new(4098);
399
400 for (int i = 1; i <= top; i++) {
401 int t = lua_type(L, i);
402
403 switch (t) {
404 case LUA_TSTRING: /* strings */
405 snprintf(tmpbuf, sizeof(tmpbuf), "\"%s\"\n",
406 lua_tostring(L, i));
407 buffer_putstr(buf, tmpbuf);
408 break;
409 case LUA_TBOOLEAN: /* booleans */
410 snprintf(tmpbuf, sizeof(tmpbuf), "%s\n",
411 lua_toboolean(L, i) ? "true" : "false");
412 buffer_putstr(buf, tmpbuf);
413 break;
414 case LUA_TNUMBER: /* numbers */
415 snprintf(tmpbuf, sizeof(tmpbuf), "%g\n",
416 lua_tonumber(L, i));
417 buffer_putstr(buf, tmpbuf);
418 break;
419 default: /* other values */
420 snprintf(tmpbuf, sizeof(tmpbuf), "%s\n",
421 lua_typename(L, t));
422 buffer_putstr(buf, tmpbuf);
423 break;
424 }
425 }
426
427 char *result = XSTRDUP(MTYPE_TMP, buffer_getstr(buf));
428
429 buffer_free(buf);
430
431 return result;
432 }
433
434 #endif /* HAVE_SCRIPTING */