]>
git.proxmox.com Git - mirror_frr.git/blob - lib/frrlua.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * This file defines the lua interface into
6 * Copyright (C) 2016-2019 Cumulus Networks, Inc.
7 * Donald Sharp, Quentin Young
19 DEFINE_MTYPE(LIB
, SCRIPT_RES
, "Scripting results");
24 * FRR convenience functions.
26 * This section has convenience functions used to make interacting with the Lua
30 int frrlua_table_get_integer(lua_State
*L
, const char *key
)
34 lua_pushstring(L
, key
);
37 result
= lua_tointeger(L
, -1);
44 * This section has functions that convert internal FRR datatypes into Lua
45 * datatypes: one encoder function and two decoder functions for each type.
49 void lua_pushprefix(lua_State
*L
, const struct prefix
*prefix
)
51 char buffer
[PREFIX_STRLEN
];
54 lua_pushstring(L
, prefix2str(prefix
, buffer
, PREFIX_STRLEN
));
55 lua_setfield(L
, -2, "network");
56 lua_pushinteger(L
, prefix
->prefixlen
);
57 lua_setfield(L
, -2, "length");
58 lua_pushinteger(L
, prefix
->family
);
59 lua_setfield(L
, -2, "family");
62 void lua_decode_prefix(lua_State
*L
, int idx
, struct prefix
*prefix
)
64 lua_getfield(L
, idx
, "network");
65 (void)str2prefix(lua_tostring(L
, -1), prefix
);
71 void *lua_toprefix(lua_State
*L
, int idx
)
73 struct prefix
*p
= XCALLOC(MTYPE_SCRIPT_RES
, sizeof(struct prefix
));
74 lua_decode_prefix(L
, idx
, p
);
78 void lua_pushinterface(lua_State
*L
, const struct interface
*ifp
)
81 lua_pushstring(L
, ifp
->name
);
82 lua_setfield(L
, -2, "name");
83 lua_pushinteger(L
, ifp
->ifindex
);
84 lua_setfield(L
, -2, "ifindex");
85 lua_pushinteger(L
, ifp
->status
);
86 lua_setfield(L
, -2, "status");
87 lua_pushinteger(L
, ifp
->flags
);
88 lua_setfield(L
, -2, "flags");
89 lua_pushinteger(L
, ifp
->metric
);
90 lua_setfield(L
, -2, "metric");
91 lua_pushinteger(L
, ifp
->speed
);
92 lua_setfield(L
, -2, "speed");
93 lua_pushinteger(L
, ifp
->mtu
);
94 lua_setfield(L
, -2, "mtu");
95 lua_pushinteger(L
, ifp
->mtu6
);
96 lua_setfield(L
, -2, "mtu6");
97 lua_pushinteger(L
, ifp
->bandwidth
);
98 lua_setfield(L
, -2, "bandwidth");
99 lua_pushinteger(L
, ifp
->link_ifindex
);
100 lua_setfield(L
, -2, "link_ifindex");
101 lua_pushinteger(L
, ifp
->ll_type
);
102 lua_setfield(L
, -2, "linklayer_type");
105 void lua_decode_interface(lua_State
*L
, int idx
, struct interface
*ifp
)
107 lua_getfield(L
, idx
, "name");
108 strlcpy(ifp
->name
, lua_tostring(L
, -1), sizeof(ifp
->name
));
110 lua_getfield(L
, idx
, "ifindex");
111 ifp
->ifindex
= lua_tointeger(L
, -1);
113 lua_getfield(L
, idx
, "status");
114 ifp
->status
= lua_tointeger(L
, -1);
116 lua_getfield(L
, idx
, "flags");
117 ifp
->flags
= lua_tointeger(L
, -1);
119 lua_getfield(L
, idx
, "metric");
120 ifp
->metric
= lua_tointeger(L
, -1);
122 lua_getfield(L
, idx
, "speed");
123 ifp
->speed
= lua_tointeger(L
, -1);
125 lua_getfield(L
, idx
, "mtu");
126 ifp
->mtu
= lua_tointeger(L
, -1);
128 lua_getfield(L
, idx
, "mtu6");
129 ifp
->mtu6
= lua_tointeger(L
, -1);
131 lua_getfield(L
, idx
, "bandwidth");
132 ifp
->bandwidth
= lua_tointeger(L
, -1);
134 lua_getfield(L
, idx
, "link_ifindex");
135 ifp
->link_ifindex
= lua_tointeger(L
, -1);
137 lua_getfield(L
, idx
, "linklayer_type");
138 ifp
->ll_type
= lua_tointeger(L
, -1);
143 void *lua_tointerface(lua_State
*L
, int idx
)
145 struct interface
*ifp
=
146 XCALLOC(MTYPE_SCRIPT_RES
, sizeof(struct interface
));
148 lua_decode_interface(L
, idx
, ifp
);
152 void lua_pushinaddr(lua_State
*L
, const struct in_addr
*addr
)
154 char buf
[INET_ADDRSTRLEN
];
156 inet_ntop(AF_INET
, addr
, buf
, sizeof(buf
));
159 lua_pushinteger(L
, addr
->s_addr
);
160 lua_setfield(L
, -2, "value");
161 lua_pushstring(L
, buf
);
162 lua_setfield(L
, -2, "string");
165 void lua_decode_inaddr(lua_State
*L
, int idx
, struct in_addr
*inaddr
)
167 lua_getfield(L
, idx
, "value");
168 inaddr
->s_addr
= lua_tointeger(L
, -1);
174 void *lua_toinaddr(lua_State
*L
, int idx
)
176 struct in_addr
*inaddr
=
177 XCALLOC(MTYPE_SCRIPT_RES
, sizeof(struct in_addr
));
178 lua_decode_inaddr(L
, idx
, inaddr
);
183 void lua_pushin6addr(lua_State
*L
, const struct in6_addr
*addr
)
185 char buf
[INET6_ADDRSTRLEN
];
187 inet_ntop(AF_INET6
, addr
, buf
, sizeof(buf
));
190 lua_pushlstring(L
, (const char *)addr
->s6_addr
, 16);
191 lua_setfield(L
, -2, "value");
192 lua_pushstring(L
, buf
);
193 lua_setfield(L
, -2, "string");
196 void lua_decode_in6addr(lua_State
*L
, int idx
, struct in6_addr
*in6addr
)
198 lua_getfield(L
, idx
, "string");
199 inet_pton(AF_INET6
, lua_tostring(L
, -1), in6addr
);
205 void *lua_toin6addr(lua_State
*L
, int idx
)
207 struct in6_addr
*in6addr
=
208 XCALLOC(MTYPE_SCRIPT_RES
, sizeof(struct in6_addr
));
209 lua_decode_in6addr(L
, idx
, in6addr
);
213 void lua_pushipaddr(lua_State
*L
, const struct ipaddr
*addr
)
215 if (IS_IPADDR_V4(addr
))
216 lua_pushinaddr(L
, &addr
->ipaddr_v4
);
218 lua_pushin6addr(L
, &addr
->ipaddr_v6
);
221 void lua_pushethaddr(lua_State
*L
, const struct ethaddr
*addr
)
224 lua_pushinteger(L
, *(addr
->octet
));
225 lua_setfield(L
, -2, "octet");
228 void lua_pushsockunion(lua_State
*L
, const union sockunion
*su
)
230 char buf
[SU_ADDRSTRLEN
];
232 sockunion2str(su
, buf
, sizeof(buf
));
235 lua_pushlstring(L
, (const char *)sockunion_get_addr(su
),
236 sockunion_get_addrlen(su
));
237 lua_setfield(L
, -2, "value");
238 lua_pushstring(L
, buf
);
239 lua_setfield(L
, -2, "string");
242 void lua_decode_sockunion(lua_State
*L
, int idx
, union sockunion
*su
)
244 lua_getfield(L
, idx
, "string");
245 if (str2sockunion(lua_tostring(L
, -1), su
) < 0)
246 zlog_err("Lua hook call: Failed to decode sockunion");
253 void *lua_tosockunion(lua_State
*L
, int idx
)
255 union sockunion
*su
=
256 XCALLOC(MTYPE_SCRIPT_RES
, sizeof(union sockunion
));
258 lua_decode_sockunion(L
, idx
, su
);
262 void lua_pushtimet(lua_State
*L
, const time_t *time
)
264 lua_pushinteger(L
, *time
);
267 void lua_decode_timet(lua_State
*L
, int idx
, time_t *t
)
269 *t
= lua_tointeger(L
, idx
);
273 void *lua_totimet(lua_State
*L
, int idx
)
275 time_t *t
= XCALLOC(MTYPE_SCRIPT_RES
, sizeof(time_t));
277 lua_decode_timet(L
, idx
, t
);
281 void lua_pushintegerp(lua_State
*L
, const long long *num
)
283 lua_pushinteger(L
, *num
);
286 void lua_decode_integerp(lua_State
*L
, int idx
, long long *num
)
289 *num
= lua_tonumberx(L
, idx
, &isnum
);
294 void *lua_tointegerp(lua_State
*L
, int idx
)
296 long long *num
= XCALLOC(MTYPE_SCRIPT_RES
, sizeof(long long));
298 lua_decode_integerp(L
, idx
, num
);
302 void lua_pushnexthop(lua_State
*L
, const struct nexthop
*nexthop
)
305 lua_pushinteger(L
, nexthop
->vrf_id
);
306 lua_setfield(L
, -2, "vrf_id");
307 lua_pushinteger(L
, nexthop
->ifindex
);
308 lua_setfield(L
, -2, "ifindex");
309 lua_pushinteger(L
, nexthop
->type
);
310 lua_setfield(L
, -2, "type");
311 lua_pushinteger(L
, nexthop
->flags
);
312 lua_setfield(L
, -2, "flags");
313 if (nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
) {
314 lua_pushinteger(L
, nexthop
->bh_type
);
315 lua_setfield(L
, -2, "bh_type");
316 } else if (nexthop
->type
== NEXTHOP_TYPE_IPV4
) {
317 lua_pushinaddr(L
, &nexthop
->gate
.ipv4
);
318 lua_setfield(L
, -2, "gate");
319 } else if (nexthop
->type
== NEXTHOP_TYPE_IPV6
) {
320 lua_pushin6addr(L
, &nexthop
->gate
.ipv6
);
321 lua_setfield(L
, -2, "gate");
323 lua_pushinteger(L
, nexthop
->nh_label_type
);
324 lua_setfield(L
, -2, "nh_label_type");
325 lua_pushinteger(L
, nexthop
->weight
);
326 lua_setfield(L
, -2, "weight");
327 lua_pushinteger(L
, nexthop
->backup_num
);
328 lua_setfield(L
, -2, "backup_num");
329 lua_pushinteger(L
, *(nexthop
->backup_idx
));
330 lua_setfield(L
, -2, "backup_idx");
331 if (nexthop
->nh_encap_type
== NET_VXLAN
) {
332 lua_pushinteger(L
, nexthop
->nh_encap
.vni
);
333 lua_setfield(L
, -2, "vni");
335 lua_pushinteger(L
, nexthop
->nh_encap_type
);
336 lua_setfield(L
, -2, "nh_encap_type");
337 lua_pushinteger(L
, nexthop
->srte_color
);
338 lua_setfield(L
, -2, "srte_color");
341 void lua_pushnexthop_group(lua_State
*L
, const struct nexthop_group
*ng
)
344 struct nexthop
*nexthop
;
347 for (ALL_NEXTHOPS_PTR(ng
, nexthop
)) {
348 lua_pushnexthop(L
, nexthop
);
354 void lua_decode_stringp(lua_State
*L
, int idx
, char *str
)
356 strlcpy(str
, lua_tostring(L
, idx
), strlen(str
) + 1);
360 void *lua_tostringp(lua_State
*L
, int idx
)
362 char *string
= XSTRDUP(MTYPE_SCRIPT_RES
, lua_tostring(L
, idx
));
368 * Decoder for const values, since we cannot modify them.
370 void lua_decode_noop(lua_State
*L
, int idx
, const void *ptr
)
376 * Noop decoder for int.
378 void lua_decode_integer_noop(lua_State
*L
, int idx
, int i
)
385 * Lua-compatible wrappers for FRR logging functions.
387 static const char *frrlua_log_thunk(lua_State
*L
)
391 nargs
= lua_gettop(L
);
394 return lua_tostring(L
, 1);
397 static int frrlua_log_debug(lua_State
*L
)
399 zlog_debug("%s", frrlua_log_thunk(L
));
403 static int frrlua_log_info(lua_State
*L
)
405 zlog_info("%s", frrlua_log_thunk(L
));
409 static int frrlua_log_notice(lua_State
*L
)
411 zlog_notice("%s", frrlua_log_thunk(L
));
415 static int frrlua_log_warn(lua_State
*L
)
417 zlog_warn("%s", frrlua_log_thunk(L
));
421 static int frrlua_log_error(lua_State
*L
)
423 zlog_err("%s", frrlua_log_thunk(L
));
427 static const luaL_Reg log_funcs
[] = {
428 {"debug", frrlua_log_debug
},
429 {"info", frrlua_log_info
},
430 {"notice", frrlua_log_notice
},
431 {"warn", frrlua_log_warn
},
432 {"error", frrlua_log_error
},
436 void frrlua_export_logging(lua_State
*L
)
439 luaL_setfuncs(L
, log_funcs
, 0);
440 lua_setglobal(L
, "log");
447 char *frrlua_stackdump(lua_State
*L
)
449 int top
= lua_gettop(L
);
452 struct buffer
*buf
= buffer_new(4098);
454 for (int i
= 1; i
<= top
; i
++) {
455 int t
= lua_type(L
, i
);
458 case LUA_TSTRING
: /* strings */
459 snprintf(tmpbuf
, sizeof(tmpbuf
), "\"%s\"\n",
461 buffer_putstr(buf
, tmpbuf
);
463 case LUA_TBOOLEAN
: /* booleans */
464 snprintf(tmpbuf
, sizeof(tmpbuf
), "%s\n",
465 lua_toboolean(L
, i
) ? "true" : "false");
466 buffer_putstr(buf
, tmpbuf
);
468 case LUA_TNUMBER
: /* numbers */
469 snprintf(tmpbuf
, sizeof(tmpbuf
), "%g\n",
471 buffer_putstr(buf
, tmpbuf
);
473 default: /* other values */
474 snprintf(tmpbuf
, sizeof(tmpbuf
), "%s\n",
476 buffer_putstr(buf
, tmpbuf
);
481 char *result
= XSTRDUP(MTYPE_TMP
, buffer_getstr(buf
));
488 #endif /* HAVE_SCRIPTING */