]> git.proxmox.com Git - mirror_frr.git/blob - lib/frrlua.c
lib: Add int encoder/decoder
[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 /* Lua stuff */
33
34 /*
35 * FRR convenience functions.
36 *
37 * This section has convenience functions used to make interacting with the Lua
38 * stack easier.
39 */
40
41 int frrlua_table_get_integer(lua_State *L, const char *key)
42 {
43 int result;
44
45 lua_pushstring(L, key);
46 lua_gettable(L, -2);
47
48 result = lua_tointeger(L, -1);
49 lua_pop(L, 1);
50
51 return result;
52 }
53
54 /*
55 * This section has functions that convert internal FRR datatypes into Lua
56 * datatypes: one encoder function and two decoder functions for each type.
57 *
58 */
59
60 void lua_pushprefix(lua_State *L, const struct prefix *prefix)
61 {
62 char buffer[PREFIX_STRLEN];
63
64 lua_newtable(L);
65 lua_pushstring(L, prefix2str(prefix, buffer, PREFIX_STRLEN));
66 lua_setfield(L, -2, "network");
67 lua_pushinteger(L, prefix->prefixlen);
68 lua_setfield(L, -2, "length");
69 lua_pushinteger(L, prefix->family);
70 lua_setfield(L, -2, "family");
71 }
72
73 void lua_decode_prefix(lua_State *L, int idx, struct prefix *prefix)
74 {
75 lua_getfield(L, idx, "network");
76 (void)str2prefix(lua_tostring(L, -1), prefix);
77 lua_pop(L, 1);
78 /* pop the table */
79 lua_pop(L, 1);
80 }
81
82 void *lua_toprefix(lua_State *L, int idx)
83 {
84 struct prefix *p = XCALLOC(MTYPE_TMP, sizeof(struct prefix));
85 lua_decode_prefix(L, idx, p);
86 return p;
87 }
88
89 void lua_pushinterface(lua_State *L, const struct interface *ifp)
90 {
91 lua_newtable(L);
92 lua_pushstring(L, ifp->name);
93 lua_setfield(L, -2, "name");
94 lua_pushinteger(L, ifp->ifindex);
95 lua_setfield(L, -2, "ifindex");
96 lua_pushinteger(L, ifp->status);
97 lua_setfield(L, -2, "status");
98 lua_pushinteger(L, ifp->flags);
99 lua_setfield(L, -2, "flags");
100 lua_pushinteger(L, ifp->metric);
101 lua_setfield(L, -2, "metric");
102 lua_pushinteger(L, ifp->speed);
103 lua_setfield(L, -2, "speed");
104 lua_pushinteger(L, ifp->mtu);
105 lua_setfield(L, -2, "mtu");
106 lua_pushinteger(L, ifp->mtu6);
107 lua_setfield(L, -2, "mtu6");
108 lua_pushinteger(L, ifp->bandwidth);
109 lua_setfield(L, -2, "bandwidth");
110 lua_pushinteger(L, ifp->link_ifindex);
111 lua_setfield(L, -2, "link_ifindex");
112 lua_pushinteger(L, ifp->ll_type);
113 lua_setfield(L, -2, "linklayer_type");
114 }
115
116 void lua_decode_interface(lua_State *L, int idx, struct interface *ifp)
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 /* pop the table */
152 lua_pop(L, 1);
153 }
154 void *lua_tointerface(lua_State *L, int idx)
155 {
156 struct interface *ifp = XCALLOC(MTYPE_TMP, sizeof(struct interface));
157
158 lua_decode_interface(L, idx, ifp);
159 return ifp;
160 }
161
162 void lua_pushinaddr(lua_State *L, const struct in_addr *addr)
163 {
164 char buf[INET_ADDRSTRLEN];
165
166 inet_ntop(AF_INET, addr, buf, sizeof(buf));
167
168 lua_newtable(L);
169 lua_pushinteger(L, addr->s_addr);
170 lua_setfield(L, -2, "value");
171 lua_pushstring(L, buf);
172 lua_setfield(L, -2, "string");
173 }
174
175 void lua_decode_inaddr(lua_State *L, int idx, struct in_addr *inaddr)
176 {
177 lua_getfield(L, idx, "value");
178 inaddr->s_addr = lua_tointeger(L, -1);
179 lua_pop(L, 1);
180 /* pop the table */
181 lua_pop(L, 1);
182 }
183
184 void *lua_toinaddr(lua_State *L, int idx)
185 {
186 struct in_addr *inaddr = XCALLOC(MTYPE_TMP, sizeof(struct in_addr));
187 lua_decode_inaddr(L, idx, inaddr);
188 return inaddr;
189 }
190
191
192 void lua_pushin6addr(lua_State *L, const struct in6_addr *addr)
193 {
194 char buf[INET6_ADDRSTRLEN];
195
196 inet_ntop(AF_INET6, addr, buf, sizeof(buf));
197
198 lua_newtable(L);
199 lua_pushlstring(L, (const char *)addr->s6_addr, 16);
200 lua_setfield(L, -2, "value");
201 lua_pushstring(L, buf);
202 lua_setfield(L, -2, "string");
203 }
204
205 void lua_decode_in6addr(lua_State *L, int idx, struct in6_addr *in6addr)
206 {
207 lua_getfield(L, idx, "string");
208 inet_pton(AF_INET6, lua_tostring(L, -1), in6addr);
209 lua_pop(L, 1);
210 /* pop the table */
211 lua_pop(L, 1);
212 }
213
214 void *lua_toin6addr(lua_State *L, int idx)
215 {
216 struct in6_addr *in6addr = XCALLOC(MTYPE_TMP, sizeof(struct in6_addr));
217 lua_decode_in6addr(L, idx, in6addr);
218 return in6addr;
219 }
220
221 void lua_pushsockunion(lua_State *L, const union sockunion *su)
222 {
223 char buf[SU_ADDRSTRLEN];
224
225 sockunion2str(su, buf, sizeof(buf));
226
227 lua_newtable(L);
228 lua_pushlstring(L, (const char *)sockunion_get_addr(su),
229 sockunion_get_addrlen(su));
230 lua_setfield(L, -2, "value");
231 lua_pushstring(L, buf);
232 lua_setfield(L, -2, "string");
233 }
234
235 void lua_decode_sockunion(lua_State *L, int idx, union sockunion *su)
236 {
237 lua_getfield(L, idx, "string");
238 str2sockunion(lua_tostring(L, -1), su);
239 lua_pop(L, 1);
240 /* pop the table */
241 lua_pop(L, 1);
242 }
243
244 void *lua_tosockunion(lua_State *L, int idx)
245 {
246 union sockunion *su = XCALLOC(MTYPE_TMP, sizeof(union sockunion));
247
248 lua_decode_sockunion(L, idx, su);
249 return su;
250 }
251
252 void lua_pushtimet(lua_State *L, const time_t *time)
253 {
254 lua_pushinteger(L, *time);
255 }
256
257 void lua_decode_timet(lua_State *L, int idx, time_t *t)
258 {
259 *t = lua_tointeger(L, idx);
260 lua_pop(L, 1);
261 }
262
263 void *lua_totimet(lua_State *L, int idx)
264 {
265 time_t *t = XCALLOC(MTYPE_TMP, sizeof(time_t));
266
267 lua_decode_timet(L, idx, t);
268 return t;
269 }
270
271 void lua_pushintegerp(lua_State *L, const long long *num)
272 {
273 lua_pushinteger(L, *num);
274 }
275
276 void lua_decode_integerp(lua_State *L, int idx, long long *num)
277 {
278 int isnum;
279 *num = lua_tonumberx(L, idx, &isnum);
280 lua_pop(L, 1);
281 assert(isnum);
282 }
283
284 void *lua_tointegerp(lua_State *L, int idx)
285 {
286 long long *num = XCALLOC(MTYPE_TMP, sizeof(long long));
287
288 lua_decode_integerp(L, idx, num);
289 return num;
290 }
291
292 void lua_decode_stringp(lua_State *L, int idx, char *str)
293 {
294 strlcpy(str, lua_tostring(L, idx), strlen(str) + 1);
295 lua_pop(L, 1);
296 }
297
298 void *lua_tostringp(lua_State *L, int idx)
299 {
300 char *string = XSTRDUP(MTYPE_TMP, lua_tostring(L, idx));
301
302 return string;
303 }
304
305 /*
306 * Decoder for const values, since we cannot modify them.
307 */
308 void lua_decode_noop(lua_State *L, int idx, const void *ptr)
309 {
310 }
311
312
313 /*
314 * Noop decoder for int.
315 */
316 void lua_decode_int_noop(lua_State *L, int idx, int i)
317 {
318 }
319
320 /*
321 * Logging.
322 *
323 * Lua-compatible wrappers for FRR logging functions.
324 */
325 static const char *frrlua_log_thunk(lua_State *L)
326 {
327 int nargs;
328
329 nargs = lua_gettop(L);
330 assert(nargs == 1);
331
332 return lua_tostring(L, 1);
333 }
334
335 static int frrlua_log_debug(lua_State *L)
336 {
337 zlog_debug("%s", frrlua_log_thunk(L));
338 return 0;
339 }
340
341 static int frrlua_log_info(lua_State *L)
342 {
343 zlog_info("%s", frrlua_log_thunk(L));
344 return 0;
345 }
346
347 static int frrlua_log_notice(lua_State *L)
348 {
349 zlog_notice("%s", frrlua_log_thunk(L));
350 return 0;
351 }
352
353 static int frrlua_log_warn(lua_State *L)
354 {
355 zlog_warn("%s", frrlua_log_thunk(L));
356 return 0;
357 }
358
359 static int frrlua_log_error(lua_State *L)
360 {
361 zlog_err("%s", frrlua_log_thunk(L));
362 return 0;
363 }
364
365 static const luaL_Reg log_funcs[] = {
366 {"debug", frrlua_log_debug},
367 {"info", frrlua_log_info},
368 {"notice", frrlua_log_notice},
369 {"warn", frrlua_log_warn},
370 {"error", frrlua_log_error},
371 {},
372 };
373
374 void frrlua_export_logging(lua_State *L)
375 {
376 lua_newtable(L);
377 luaL_setfuncs(L, log_funcs, 0);
378 lua_setglobal(L, "log");
379 }
380
381 /*
382 * Debugging.
383 */
384
385 char *frrlua_stackdump(lua_State *L)
386 {
387 int top = lua_gettop(L);
388
389 char tmpbuf[64];
390 struct buffer *buf = buffer_new(4098);
391
392 for (int i = 1; i <= top; i++) {
393 int t = lua_type(L, i);
394
395 switch (t) {
396 case LUA_TSTRING: /* strings */
397 snprintf(tmpbuf, sizeof(tmpbuf), "\"%s\"\n",
398 lua_tostring(L, i));
399 buffer_putstr(buf, tmpbuf);
400 break;
401 case LUA_TBOOLEAN: /* booleans */
402 snprintf(tmpbuf, sizeof(tmpbuf), "%s\n",
403 lua_toboolean(L, i) ? "true" : "false");
404 buffer_putstr(buf, tmpbuf);
405 break;
406 case LUA_TNUMBER: /* numbers */
407 snprintf(tmpbuf, sizeof(tmpbuf), "%g\n",
408 lua_tonumber(L, i));
409 buffer_putstr(buf, tmpbuf);
410 break;
411 default: /* other values */
412 snprintf(tmpbuf, sizeof(tmpbuf), "%s\n",
413 lua_typename(L, t));
414 buffer_putstr(buf, tmpbuf);
415 break;
416 }
417 }
418
419 char *result = XSTRDUP(MTYPE_TMP, buffer_getstr(buf));
420
421 buffer_free(buf);
422
423 return result;
424 }
425
426 #endif /* HAVE_SCRIPTING */