Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145802521
D25447.id73621.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
35 KB
Referenced Files
None
Subscribers
None
D25447.id73621.diff
View Options
Index: libexec/flua/Makefile
===================================================================
--- libexec/flua/Makefile
+++ libexec/flua/Makefile
@@ -24,6 +24,10 @@
CFLAGS+= -I${SRCTOP}/lib/liblua -I${.CURDIR}/modules -I${LUASRC}
CFLAGS+= -DLUA_PROGNAME="\"${PROG}\""
+SRCS+= lua_ifconfig.c
+CFLAGS+= -I${SRCTOP}/lib/libifconfig
+LIBADD+= ifconfig sysdecode
+
# readline bits; these aren't needed if we're building a bootstrap flua, as we
# don't expect that one to see any REPL usage.
.if !defined(BOOTSTRAPPING)
Index: libexec/flua/linit_flua.c
===================================================================
--- libexec/flua/linit_flua.c
+++ libexec/flua/linit_flua.c
@@ -36,6 +36,7 @@
#include "lauxlib.h"
#include "lfs.h"
#include "lposix.h"
+#include "lua_ifconfig.h"
#include "lua_ucl.h"
/*
@@ -57,6 +58,7 @@
{LUA_BITLIBNAME, luaopen_bit32},
#endif
/* FreeBSD Extensions */
+ {"ifconfig", luaopen_ifconfig},
{"lfs", luaopen_lfs},
{"posix.sys.stat", luaopen_posix_sys_stat},
{"posix.unistd", luaopen_posix_unistd},
Index: libexec/flua/modules/lua_ifconfig.h
===================================================================
--- libexec/flua/modules/lua_ifconfig.h
+++ libexec/flua/modules/lua_ifconfig.h
@@ -0,0 +1,10 @@
+/*-
+ * This file is in the public domain.
+ */
+/* $FreeBSD$ */
+
+#pragma once
+
+#include <lua.h>
+
+int luaopen_ifconfig(lua_State *L);
Index: libexec/flua/modules/lua_ifconfig.c
===================================================================
--- libexec/flua/modules/lua_ifconfig.c
+++ libexec/flua/modules/lua_ifconfig.c
@@ -0,0 +1,1462 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2020, Ryan Moeller <freqlabs@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $FreeBSD$ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <arpa/inet.h>
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/ieee8023ad_lacp.h>
+#include <net/if_lagg.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <netinet/in.h>
+#include <netinet/ip_carp.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/nd6.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <ifaddrs.h>
+#include <netdb.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysdecode.h>
+#include <sysexits.h>
+
+#include <libifconfig.h>
+
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+
+#define IFCONFIG_HANDLE_META "ifconfig_handle_t"
+#define STRUCT_IFADDRS_META "struct ifaddrs *"
+
+#define IFFBITS \
+ "\020" \
+ "\001UP" \
+ "\002BROADCAST" \
+ "\003DEBUG" \
+ "\004LOOPBACK" \
+ "\005POINTOPOINT" \
+ "\007RUNNING" \
+ "\010NOARP" \
+ "\011PROMISC" \
+ "\012ALLMULTI" \
+ "\013OACTIVE" \
+ "\014SIMPLEX" \
+ "\015LINK0" \
+ "\016LINK1" \
+ "\017LINK2" \
+ "\020MULTICAST" \
+ "\022PPROMISC" \
+ "\023MONITOR" \
+ "\024STATICARP"
+
+#define IFCAPBITS \
+ "\020" \
+ "\001RXCSUM" \
+ "\002TXCSUM" \
+ "\003NETCONS" \
+ "\004VLAN_MTU" \
+ "\005VLAN_HWTAGGING" \
+ "\006JUMBO_MTU" \
+ "\007POLLING" \
+ "\010VLAN_HWCSUM" \
+ "\011TSO4" \
+ "\012TSO6" \
+ "\013LRO" \
+ "\014WOL_UCAST" \
+ "\015WOL_MCAST" \
+ "\016WOL_MAGIC" \
+ "\017TOE4" \
+ "\020TOE6" \
+ "\021VLAN_HWFILTER" \
+ "\023VLAN_HWTSO" \
+ "\024LINKSTATE" \
+ "\025NETMAP" \
+ "\026RXCSUM_IPV6" \
+ "\027TXCSUM_IPV6" \
+ "\031TXRTLMT" \
+ "\032HWRXTSTMP" \
+ "\033NOMAP" \
+ "\034TXTLS4" \
+ "\035TXTLS6"
+
+#define IN6BITS \
+ "\020" \
+ "\001anycast" \
+ "\002tenative" \
+ "\003duplicated" \
+ "\004detached" \
+ "\005deprecated" \
+ "\007nodad" \
+ "\010autoconf" \
+ "\011temporary" \
+ "\012prefer_source"
+
+#define ND6BITS \
+ "\020" \
+ "\001nud" \
+ "\002accept_rtadv" \
+ "\003prefer_source" \
+ "\004ifdisabled" \
+ "\005dont_set_ifroute" \
+ "\006auto_linklocal" \
+ "\007no_radr" \
+ "\010no_prefer_iface" \
+ "\011no_dad" \
+ "\012ipv6_only" \
+ "\013ipv6_only"
+
+#define LAGGHASHBITS \
+ "\020" \
+ "\001l2" \
+ "\002l3" \
+ "\003l4"
+
+static const char *carp_states[] = { CARP_STATES };
+static const struct lagg_protos lagg_protos[] = LAGG_PROTOS;
+
+/*
+ * Create an array of the set flags in v, using the kernel %b format bits.
+ */
+static void
+push_flags_array(lua_State *L, unsigned v, const char *bits)
+{
+ int i, len;
+
+ lua_newtable(L);
+
+ /* Skip numeric format. */
+ ++bits;
+
+ while ((i = *bits++) != '\0') {
+ if ((v & (1 << (i - 1))) != 0) {
+ for (len = 0; bits[len] > 32; ++len);
+ lua_pushlstring(L, bits, len);
+ lua_rawseti(L, -2, i);
+ bits += len;
+ } else {
+ for (; *bits > 32; ++bits);
+ }
+ }
+}
+
+/*
+ * Decode an array of the flags to set and return as an int.
+ */
+static int
+pop_flags_array(lua_State *L, int index, const char *bits)
+{
+ int v = 0;
+
+ /* Skip numeric format. */
+ ++bits;
+
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, index) != 0) {
+ const char *flag, *flags = bits;
+ int i, len;
+
+ luaL_checkstring(L, index + 2);
+
+ flag = lua_tostring(L, index + 2);
+ lua_pop(L, 1);
+ while ((i = *flags++) != '\0') {
+ for (len = 0; flags[len] > 32; ++len);
+ if (strncmp(flag, flags, len) == 0) {
+ v |= 1 << (i - 1);
+ break;
+ }
+ flags += len;
+ }
+ }
+
+ return (v);
+}
+
+/*
+ * Push a table describing media information.
+ */
+static void
+push_media_info(lua_State *L, int ifmw)
+{
+ char opts[80];
+ int index;
+
+ lua_newtable(L);
+ index = lua_gettop(L);
+
+ lua_pushstring(L, ifconfig_media_get_type(ifmw));
+ lua_setfield(L, index, "type");
+
+ lua_pushstring(L, ifconfig_media_get_subtype(ifmw));
+ lua_setfield(L, index, "subtype");
+
+ ifconfig_media_get_options_string(ifmw, opts, sizeof opts);
+ lua_pushstring(L, opts);
+ lua_setfield(L, index, "options");
+}
+
+/*
+ * Push a table describing an AF_INET address or nil if error.
+ */
+static void
+push_inet4_addrinfo(lua_State *L, ifconfig_handle_t *h, struct ifaddrs *ifa)
+{
+ char addr_buf[NI_MAXHOST];
+ struct ifconfig_inet_addr addr;
+ int index;
+
+ if (ifconfig_inet_get_addrinfo(h, ifa->ifa_name, ifa, &addr) != 0) {
+ lua_pushnil(L);
+ return;
+ }
+
+ lua_newtable(L);
+ index = lua_gettop(L);
+
+ /* TODO: can this just be inet_ntoa? */
+ inet_ntop(AF_INET, &addr.sin->sin_addr, addr_buf, sizeof addr_buf);
+ lua_pushstring(L, addr_buf);
+ lua_setfield(L, index, "inet");
+
+ if (addr.dst != NULL) {
+ lua_pushstring(L, inet_ntoa_r(addr.dst->sin_addr, addr_buf,
+ sizeof addr_buf));
+ lua_setfield(L, index, "destination");
+ }
+
+ lua_pushstring(L, inet_ntoa_r(addr.netmask->sin_addr, addr_buf,
+ sizeof addr_buf));
+ lua_setfield(L, index, "netmask");
+
+ if (addr.broadcast != NULL) {
+ lua_pushstring(L, inet_ntoa_r(addr.broadcast->sin_addr,
+ addr_buf, sizeof addr_buf));
+ lua_setfield(L, index, "broadcast");
+ }
+
+ if (addr.vhid != 0) {
+ lua_pushinteger(L, addr.vhid);
+ lua_setfield(L, index, "vhid");
+ }
+}
+
+/*
+ * Push a table describing an AF_INET6 address or nil if error.
+ */
+static void
+push_inet6_addrinfo(lua_State *L, ifconfig_handle_t *h, struct ifaddrs *ifa)
+{
+ char addr_buf[NI_MAXHOST];
+ struct ifconfig_inet6_addr addr;
+ struct timespec now;
+ int index;
+
+ if (ifconfig_inet6_get_addrinfo(h, ifa->ifa_name, ifa, &addr) != 0) {
+ lua_pushnil(L);
+ return;
+ }
+
+ lua_newtable(L);
+ index = lua_gettop(L);
+
+ if (getnameinfo((struct sockaddr *)addr.sin6, addr.sin6->sin6_len,
+ addr_buf, sizeof addr_buf, NULL, 0, NI_NUMERICHOST) != 0)
+ /* TODO: can this just be inet_ntoa? */
+ inet_ntop(AF_INET6, &addr.sin6->sin6_addr, addr_buf,
+ sizeof addr_buf);
+ lua_pushstring(L, addr_buf);
+ lua_setfield(L, index, "inet6");
+
+ if (addr.dstin6 != NULL) {
+ inet_ntop(AF_INET6, addr.dstin6, addr_buf, sizeof addr_buf);
+ lua_pushstring(L, addr_buf);
+ lua_setfield(L, index, "destination");
+ }
+
+ lua_pushinteger(L, addr.prefixlen);
+ lua_setfield(L, index, "prefixlen");
+
+ if (addr.sin6->sin6_scope_id != 0) {
+ lua_pushinteger(L, addr.sin6->sin6_scope_id);
+ lua_setfield(L, index, "scopeid");
+ }
+
+ push_flags_array(L, addr.flags, IN6BITS);
+ lua_setfield(L, index, "flags");
+
+ clock_gettime(CLOCK_MONOTONIC_FAST, &now);
+ if (addr.lifetime.ia6t_preferred || addr.lifetime.ia6t_expire) {
+ lua_pushinteger(L, MAX(0l,
+ addr.lifetime.ia6t_preferred - now.tv_sec));
+ lua_setfield(L, index, "preferred_lifetime");
+
+ lua_pushinteger(L, MAX(0l,
+ addr.lifetime.ia6t_expire - now.tv_sec));
+ lua_setfield(L, index, "valid_lifetime");
+ }
+
+ if (addr.vhid != 0) {
+ lua_pushinteger(L, addr.vhid);
+ lua_setfield(L, index, "vhid");
+ }
+}
+
+/*
+ * Push a table describing an AF_LINK address or nil if error.
+ */
+static void
+push_link_addrinfo(lua_State *L, ifconfig_handle_t *h, struct ifaddrs *ifa)
+{
+ char addr_buf[NI_MAXHOST];
+ struct sockaddr_dl *sdl;
+ int index, n;
+
+ sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+ if (sdl == NULL || sdl->sdl_alen <= 0) {
+ lua_pushnil(L);
+ return;
+ }
+
+ lua_newtable(L);
+ index = lua_gettop(L);
+
+ switch (sdl->sdl_type) {
+ case IFT_ETHER:
+ case IFT_L2VLAN:
+ case IFT_BRIDGE:
+ if (sdl->sdl_alen != ETHER_ADDR_LEN)
+ break;
+ ether_ntoa_r((struct ether_addr *)LLADDR(sdl), addr_buf);
+ lua_pushstring(L, addr_buf);
+ lua_setfield(L, index, "ether");
+ break;
+ default:
+ n = sdl->sdl_nlen > 0 ? sdl->sdl_nlen + 1 : 0;
+ lua_pushstring(L, link_ntoa(sdl) + n); /* FIXME: link_ntoa_r */
+ lua_setfield(L, index, "lladdr");
+ break;
+ }
+}
+
+/*
+ * Push a table describing an AF_LOCAL address.
+ */
+static void
+push_local_addrinfo(lua_State *L, ifconfig_handle_t *h, struct ifaddrs *ifa)
+{
+ struct sockaddr_un *sun;
+ int index;
+
+ lua_newtable(L);
+ index = lua_gettop(L);
+
+ if (strlen(sun->sun_path) == 0)
+ lua_pushstring(L, "-");
+ else
+ lua_pushstring(L, sun->sun_path);
+ lua_setfield(L, index, "path");
+}
+
+/*
+ * Check the stack for an ifconfig handle userdata at the given index.
+ */
+static ifconfig_handle_t *
+l_ifconfig_checkhandle(lua_State *L, int index)
+{
+ ifconfig_handle_t *h, **hp;
+
+ hp = luaL_checkudata(L, index, IFCONFIG_HANDLE_META);
+ assert(hp != NULL);
+ h = *hp;
+ luaL_argcheck(L, h != NULL, index, "invalid ifconfig handle");
+ return (h);
+}
+
+/*
+ * Check the stack for an ifaddrs userdata at the given index.
+ */
+static struct ifaddrs *
+l_ifconfig_checkifaddrs(lua_State *L, int index)
+{
+ struct ifaddrs *ifa, **ifap;
+
+ ifap = luaL_checkudata(L, index, STRUCT_IFADDRS_META);
+ assert(ifap != NULL);
+ ifa = *ifap;
+ luaL_argcheck(L, ifa != NULL, index, "invalid ifaddr");
+ return (ifa);
+}
+
+/*
+ * Invoke a callback function on the stack with the handle and accumulator
+ * from the stack and the given ifaddrs, leaving the handle, callback, and
+ * accumulator result on the stack after the call.
+ *
+ * This is used by the ifconfig_foreach_* functions to invoke a lua callback.
+ */
+static void
+foreach_cb(ifconfig_handle_t *h, struct ifaddrs *ifa, void *udata)
+{
+ lua_State *L = udata;
+ struct ifaddrs **ifap;
+
+ /* Stack: h,cb,acc */
+
+ /* Make copies of the callback and handle positioned for the call. */
+ lua_pushvalue(L, 1); /* -> h,cb,acc,h */
+ lua_pushvalue(L, 2); /* -> h,cb,acc,h,cb */
+ lua_insert(L, 3); /* -> h,cb,cb,acc,h */
+ lua_insert(L, 4); /* -> h,cb,cb,h,acc */
+
+ /* Push the ifa userdata. */
+ ifap = lua_newuserdata(L, sizeof ifa); /* -> h,cb,cb,h,acc,ifa */
+ assert(ifap != NULL);
+ *ifap = ifa;
+ luaL_getmetatable(L, STRUCT_IFADDRS_META);
+ lua_setmetatable(L, -2);
+
+ /* Reposition the accumulator to be last so it can be optional. */
+ lua_insert(L, 5); /* -> h,cb,cb,h,ifa,acc */
+
+ /* Invoke the callback. */
+ lua_call(L, 3, 1); /* -> h,cb,acc */
+}
+
+/** Explicit close method
+ */
+static int
+l_ifconfig_handle_close(lua_State *L)
+{
+ ifconfig_handle_t *h, **hp;
+
+ hp = luaL_checkudata(L, 1, IFCONFIG_HANDLE_META);
+ assert(hp != NULL);
+ h = *hp;
+ if (h != NULL) {
+ ifconfig_close(h);
+ *hp = NULL;
+ }
+ return (0);
+}
+
+/** Get error info
+ * @return errtype, errno, ioctlname?
+ */
+static int
+l_ifconfig_handle_error(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ ifconfig_errtype errtype;
+
+ h = l_ifconfig_checkhandle(L, 1);
+
+ errtype = ifconfig_err_errtype(h);
+ switch (errtype) {
+ case OK:
+ lua_pushnil(L);
+ return (1);
+ case OTHER:
+ lua_pushstring(L, "OTHER");
+ break;
+ case IOCTL:
+ lua_pushstring(L, "IOCTL");
+ break;
+ case SOCKET:
+ lua_pushstring(L, "SOCKET");
+ break;
+ default:
+ lua_pushstring(L, "<unknown>");
+ break;
+ }
+
+ lua_pushinteger(L, ifconfig_err_errno(h));
+
+ if (errtype == IOCTL) {
+ unsigned long req = ifconfig_err_ioctlreq(h);
+ lua_pushstring(L, sysdecode_ioctlname(req));
+ return (3);
+ }
+
+ return (2);
+}
+
+/** Higher-order fold iterator over interfaces
+ * @param cb A callback function (handle, iface, udata) -> udata
+ * @param udata An initial accumulator value (may be nil)
+ * @return The final accumulator value returned by cb
+ */
+static int
+l_ifconfig_foreach_iface(lua_State *L)
+{
+ const int MAXARGS = 3;
+ ifconfig_handle_t *h;
+ int n;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+
+ /* Ensure the correct number of args. Extras are discarded. */
+ n = lua_gettop(L);
+ if (n == (MAXARGS - 1))
+ lua_pushnil(L);
+ else if (n > MAXARGS)
+ lua_pop(L, n - MAXARGS);
+
+ if (ifconfig_foreach_iface(h, foreach_cb, L) != 0)
+ return luaL_error(L, "iteration failed");
+
+ return (1);
+}
+
+/** Higher-order fold iterator over interface addresses
+ * @param ifa A STRUCT_IFADDRS_META userdata value from foreach_iface
+ * @param cb A callback function (handle, iface, udata) -> udata
+ * @param udata An initial accumulator value (may be nil)
+ * @return The final accumulator value returned by cb
+ */
+static int
+l_ifconfig_foreach_ifaddr(lua_State *L)
+{
+ const int MAXARGS = 4;
+ ifconfig_handle_t *h;
+ struct ifaddrs *ifa;
+ int n;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ ifa = l_ifconfig_checkifaddrs(L, 2);
+ luaL_checktype(L, 3, LUA_TFUNCTION);
+
+ /* Ensure the correct number of args. Extras are discarded. */
+ n = lua_gettop(L);
+ if (n == (MAXARGS - 1))
+ lua_pushnil(L);
+ else if (n > MAXARGS)
+ lua_pop(L, n - MAXARGS);
+ lua_remove(L, 2);
+
+ ifconfig_foreach_ifaddr(h, ifa, foreach_cb, L);
+
+ return (1);
+}
+
+/** Get interface description
+ * @param name The name of an interface
+ * @return Description string if set, otherwise nil
+ */
+static int
+l_ifconfig_get_description(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name;
+ char *desc;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+
+ name = lua_tostring(L, 2);
+ if (ifconfig_get_description(h, name, &desc) != 0)
+ lua_pushnil(L);
+ else
+ lua_pushstring(L, desc);
+
+ return (1);
+}
+
+/** Set interface description
+ * @param name The name of an interface
+ * @param desc Description string to set
+ * @return true if success, false if error
+ */
+static int
+l_ifconfig_set_description(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name, *desc;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+ luaL_checkstring(L, 3);
+
+ name = lua_tostring(L, 2);
+ desc = lua_tostring(L, 3);
+ if (ifconfig_set_description(h, name, desc) != 0)
+ lua_pushboolean(L, false);
+ else
+ lua_pushboolean(L, true);
+
+ return (1);
+}
+
+/** Unset interface description
+ * @param name The name of an interface
+ * @return true if success, false if error
+ */
+static int
+l_ifconfig_unset_description(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+
+ name = lua_tostring(L, 2);
+ if (ifconfig_unset_description(h, name) != 0)
+ lua_pushboolean(L, false);
+ else
+ lua_pushboolean(L, true);
+
+ return (1);
+}
+
+/** Set interface name
+ * @param name The name of an interface
+ * @param newname A new name for the interface
+ * @return true if success, false if error
+ */
+static int
+l_ifconfig_set_name(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name, *newname;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+ luaL_checkstring(L, 3);
+
+ name = lua_tostring(L, 2);
+ newname = lua_tostring(L, 3);
+ if (ifconfig_set_name(h, name, newname) != 0)
+ lua_pushboolean(L, false);
+ else
+ lua_pushboolean(L, true);
+
+ return (1);
+}
+
+/** Get original interface name
+ * @param name The name of an interface
+ * @return Original interface name or nil if error
+ */
+static int
+l_ifconfig_get_orig_name(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name;
+ char *orig_name;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+
+ name = lua_tostring(L, 2);
+ if (ifconfig_get_orig_name(h, name, &orig_name) != 0)
+ lua_pushnil(L);
+ else
+ lua_pushstring(L, orig_name);
+
+ return (1);
+}
+
+#if 0 /* setfib not implemented in libifconfig? */
+/** Set interface fib
+ * @param name The name of an interface
+ * @param fib A fib number to use
+ * @return true if success, false if error
+ */
+static int
+l_ifconfig_set_fib(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name;
+ ptrdiff_t fib;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+ luaL_checkinteger(L, 3);
+
+ name = lua_tostring(L, 2);
+ fib = lua_tointeger(L, 3);
+ luaL_argcheck(L, INT_MAX < fib || fib < INT_MIN, 3, "fib out of range");
+ if (ifconfig_set_fib(h, name, fib) != 0)
+ lua_pushboolean(L, false);
+ else
+ lua_pushboolean(L, true);
+
+ return (1);
+}
+#endif
+
+/** Get interface fib
+ * @param name The name of an interface
+ * @return fib of the interface or nil if error
+ */
+static int
+l_ifconfig_get_fib(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name;
+ int fib;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+
+ name = lua_tostring(L, 2);
+ if (ifconfig_get_fib(h, name, &fib) != 0)
+ lua_pushnil(L);
+ else
+ lua_pushinteger(L, fib);
+
+ return (1);
+}
+
+/** Set interface mtu
+ * @param name The name of an interface
+ * @param mtu A mtu to use
+ * @return true if success, false if error
+ */
+static int
+l_ifconfig_set_mtu(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name;
+ ptrdiff_t mtu;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+ luaL_checkinteger(L, 3);
+
+ name = lua_tostring(L, 2);
+ mtu = lua_tointeger(L, 3);
+ luaL_argcheck(L, INT_MIN <= mtu && mtu <= INT_MAX, 3, "mtu out of range");
+ if (ifconfig_set_mtu(h, name, mtu) != 0)
+ lua_pushboolean(L, false);
+ else
+ lua_pushboolean(L, true);
+
+ return (1);
+}
+
+/** Get interface mtu
+ * @param name The name of an interface
+ * @return mtu of the interface or nil if error
+ */
+static int
+l_ifconfig_get_mtu(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name;
+ int mtu;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+
+ name = lua_tostring(L, 2);
+ if (ifconfig_get_mtu(h, name, &mtu) != 0)
+ lua_pushnil(L);
+ else
+ lua_pushinteger(L, mtu);
+
+ return (1);
+}
+
+/** Get interface nd6 info
+ * @param name The name of an interface
+ * @return An list of the enabled nd6 options or nil if error
+ */
+static int
+l_ifconfig_get_nd6(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name;
+ struct in6_ndireq nd;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+
+ name = lua_tostring(L, 2);
+ if (ifconfig_get_nd6(h, name, &nd) != 0)
+ lua_pushnil(L);
+ else
+ push_flags_array(L, nd.ndi.flags, ND6BITS);
+
+ return (1);
+}
+
+/** Set interface metric
+ * @param name The name of an interface
+ * @param metric A metric to use
+ * @return true if success, false if error
+ */
+static int
+l_ifconfig_set_metric(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name;
+ ptrdiff_t metric;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+ luaL_checkinteger(L, 3);
+
+ name = lua_tostring(L, 2);
+ metric = lua_tointeger(L, 3);
+ luaL_argcheck(L, INT_MAX < metric || metric < INT_MIN, 3,
+ "metric out of range");
+ if (ifconfig_set_metric(h, name, metric) != 0)
+ lua_pushboolean(L, false);
+ else
+ lua_pushboolean(L, true);
+
+ return (1);
+}
+
+/** Get interface metric
+ * @param name The name of an interface
+ * @return metric of the interface or nil if error
+ */
+static int
+l_ifconfig_get_metric(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name;
+ int metric;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+
+ name = lua_tostring(L, 2);
+ if (ifconfig_get_metric(h, name, &metric) != 0)
+ lua_pushnil(L);
+ else
+ lua_pushinteger(L, metric);
+
+ return (1);
+}
+
+/** Set interface capabilities
+ * @param name The name of an interface
+ * @param caps An array of the capabilities to be enabled on the interface
+ * (capabilities not listed will be disabled)
+ * @return true if success, false if error
+ */
+static int
+l_ifconfig_set_capability(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name;
+ int capability;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+ luaL_checktype(L, 3, LUA_TTABLE);
+
+ name = lua_tostring(L, 2);
+ capability = pop_flags_array(L, 3, IFCAPBITS);
+ if (ifconfig_set_capability(h, name, capability) != 0)
+ lua_pushboolean(L, false);
+ else
+ lua_pushboolean(L, true);
+
+ return (1);
+}
+
+/** Get interface capabilities
+ * @param name The name of an interface
+ * @return A table of the enabled/supported capabilites or nil if error
+ */
+static int
+l_ifconfig_get_capability(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name;
+ struct ifconfig_capabilities capability;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+
+ name = lua_tostring(L, 2);
+ if (ifconfig_get_capability(h, name, &capability) != 0) {
+ lua_pushnil(L);
+ return (1);
+ }
+
+ lua_newtable(L);
+
+ lua_pushstring(L, "options");
+ push_flags_array(L, capability.curcap, IFCAPBITS);
+ lua_rawset(L, 3);
+
+ lua_pushstring(L, "capabilities");
+ push_flags_array(L, capability.reqcap, IFCAPBITS);
+ lua_rawset(L, 3);
+
+ return (1);
+}
+
+/** Get interface groups list
+ * @param name The name of an interface
+ * @return A table of the groups containing the interface or nil if error
+ */
+static int
+l_ifconfig_get_groups(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name;
+ struct ifgroupreq ifgr;
+ struct ifg_req *ifg;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+
+ name = lua_tostring(L, 2);
+ if (ifconfig_get_groups(h, name, &ifgr) != 0) {
+ lua_pushnil(L);
+ return (1);
+ }
+
+ lua_newtable(L);
+
+ for (ifg = ifgr.ifgr_groups;
+ ifg != NULL && ifgr.ifgr_len >= sizeof *ifg;
+ ++ifg, ifgr.ifgr_len -= sizeof *ifg) {
+ if (strcmp(ifg->ifgrq_group, "all") == 0)
+ continue;
+ lua_pushstring(L, ifg->ifgrq_group);
+ lua_rawseti(L, 3, lua_rawlen(L, 3) + 1);
+ }
+
+ return (1);
+}
+
+/** Get interface status
+ * @param name The name of an interface
+ * @return Interface status as a string or nil if error
+ */
+static int
+l_ifconfig_get_status(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name;
+ struct ifstat status;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+
+ name = lua_tostring(L, 2);
+ if (ifconfig_get_ifstatus(h, name, &status) != 0)
+ lua_pushnil(L);
+ else
+ lua_pushstring(L, status.ascii);
+
+ return (1);
+}
+
+/** Get interface media info
+ * @param name The name of an interface
+ * @return A table describing the interface media or nil if error
+ */
+static int
+l_ifconfig_get_media(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name;
+ struct ifmediareq *ifmr;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+
+ name = lua_tostring(L, 2);
+ if (ifconfig_media_get_mediareq(h, name, &ifmr) != 0) {
+ lua_pushnil(L);
+ return (1);
+ }
+
+ lua_newtable(L);
+
+ push_media_info(L, ifmr->ifm_current);
+ lua_setfield(L, 3, "current");
+
+ push_media_info(L, ifmr->ifm_active);
+ lua_setfield(L, 3, "active");
+
+ lua_newtable(L);
+ for (size_t i = 0; i < ifmr->ifm_count; ++i) {
+ push_media_info(L, ifmr->ifm_ulist[i]);
+ lua_rawseti(L, 4, lua_rawlen(L, 4) + 1);
+ }
+ lua_setfield(L, 3, "supported");
+
+ lua_pushstring(L, ifconfig_media_get_status(ifmr));
+ lua_setfield(L, 3, "status");
+
+ free(ifmr);
+
+ return (1);
+}
+
+/** Get interface carp info
+ * @param name
+ * @return A table describing the interface carp vhids or nil if error
+ */
+static int
+l_ifconfig_get_carp(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name;
+ struct carpreq carpr[CARP_MAXVHID];
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+
+ name = lua_tostring(L, 2);
+ if (ifconfig_carp_get_info(h, name, carpr, nitems(carpr)) != 0) {
+ lua_pushnil(L);
+ return (1);
+ }
+
+ lua_newtable(L);
+
+ for (size_t i = 0; i < carpr[0].carpr_count; ++i) {
+ lua_newtable(L);
+
+ lua_pushstring(L, carp_states[carpr[i].carpr_state]);
+ lua_setfield(L, 4, "state");
+
+ lua_pushinteger(L, carpr[i].carpr_vhid);
+ lua_setfield(L, 4, "vhid");
+
+ lua_pushinteger(L, carpr[i].carpr_advbase);
+ lua_setfield(L, 4, "advbase");
+
+ lua_pushinteger(L, carpr[i].carpr_advskew);
+ lua_setfield(L, 4, "advskew");
+
+ lua_rawseti(L, 3, lua_rawlen(L, 3) + 1);
+ }
+
+ return (1);
+}
+
+/** Get address info
+ * @param addr An ifaddrs userdata object
+ * @return Table describing the address or nil if error
+ */
+static int
+l_ifconfig_addr_info(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ struct ifaddrs *ifa;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ ifa = l_ifconfig_checkifaddrs(L, 2);
+
+ switch (ifa->ifa_addr->sa_family) {
+ case AF_INET:
+ push_inet4_addrinfo(L, h, ifa);
+ break;
+ case AF_INET6:
+ push_inet6_addrinfo(L, h, ifa);
+ break;
+ case AF_LINK:
+ push_link_addrinfo(L, h, ifa);
+ break;
+ case AF_LOCAL:
+ push_local_addrinfo(L, h, ifa);
+ break;
+ case AF_UNSPEC:
+ default:
+ lua_pushnil(L);
+ break;
+ }
+
+ return (1);
+}
+
+/** Get lagg interface status
+ * @param name The name of a lagg interface
+ * @return Table describing the status of the lagg or nil if error
+ */
+static int
+l_ifconfig_get_lagg_status(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name;
+ struct ifconfig_lagg_status *lagg_status;
+ const char *protoname = "<unknown>";
+ int index;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+
+ name = lua_tostring(L, 2);
+ if (ifconfig_lagg_get_lagg_status(h, name, &lagg_status) != 0) {
+ lua_pushnil(L);
+ return (1);
+ }
+
+ lua_newtable(L);
+ index = lua_gettop(L);
+
+ for (size_t i = 0; i < nitems(lagg_protos); ++i) {
+ if (lagg_status->ra->ra_proto == lagg_protos[i].lpr_proto) {
+ protoname = lagg_protos[i].lpr_name;
+ break;
+ }
+ }
+ lua_pushstring(L, protoname);
+ lua_setfield(L, index, "laggproto");
+
+ push_flags_array(L, lagg_status->rf->rf_flags & LAGG_F_HASHMASK,
+ LAGGHASHBITS);
+ lua_setfield(L, index, "lagghash");
+
+ lua_newtable(L);
+ ++index;
+
+ push_flags_array(L, lagg_status->ro->ro_opts, LAGG_OPT_BITS);
+ lua_setfield(L, index, "flags");
+
+ lua_pushinteger(L, lagg_status->ro->ro_flowid_shift);
+ lua_setfield(L, index, "flowid_shift");
+
+ if (lagg_status->ra->ra_proto == LAGG_PROTO_ROUNDROBIN) {
+ lua_pushinteger(L, lagg_status->ro->ro_bkt);
+ lua_setfield(L, index, "rr_limit");
+ }
+
+ --index;
+ lua_setfield(L, index, "options");
+
+ lua_newtable(L);
+ ++index;
+
+ lua_pushinteger(L, lagg_status->ro->ro_active);
+ lua_setfield(L, index, "active");
+
+ lua_pushinteger(L, lagg_status->ro->ro_flapping);
+ lua_setfield(L, index, "flapping");
+
+ --index;
+ lua_setfield(L, index, "stats");
+
+ lua_newtable(L);
+ ++index;
+
+ for (size_t i = 0; i < lagg_status->ra->ra_ports; ++i) {
+ struct lagg_reqport *lagg_port = &lagg_status->ra->ra_port[i];
+
+ lua_newtable(L);
+ ++index;
+
+ lua_pushstring(L, lagg_port->rp_portname);
+ lua_setfield(L, index, "laggport");
+
+ push_flags_array(L, lagg_port->rp_flags, LAGG_PORT_BITS);
+ lua_setfield(L, index, "flags");
+
+ if (lagg_status->ra->ra_proto == LAGG_PROTO_LACP) {
+ struct lacp_opreq *lacp_port = (struct lacp_opreq *)
+ &lagg_port->rp_lacpreq;
+
+ push_flags_array(L, lacp_port->actor_state,
+ LACP_STATE_BITS);
+ lua_setfield(L, index, "lacp_state");
+ }
+
+ --index;
+ lua_rawseti(L, index, lua_rawlen(L, index) + 1);
+ }
+
+ --index;
+ lua_setfield(L, index, "ports");
+
+ ifconfig_lagg_free_lagg_status(lagg_status);
+
+ return (1);
+}
+
+/** Get the parent laggdev of a laggport interface
+ * @param name The name of a laggport interface
+ * @return Parent laggdev name or nil if error
+ */
+static int
+l_ifconfig_get_laggport_laggdev(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name;
+ struct lagg_reqport lagg_port;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+
+ name = lua_tostring(L, 2);
+ if (ifconfig_lagg_get_laggport_status(h, name, &lagg_port) != 0)
+ lua_pushnil(L);
+ else
+ lua_pushstring(L, lagg_port.rp_ifname);
+
+ return (1);
+}
+
+/** Destroy an interface
+ * @param name The name of an interface
+ * @return true if success, false if error
+ */
+static int
+l_ifconfig_destroy(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+
+ name = lua_tostring(L, 2);
+ if (ifconfig_destroy_interface(h, name) != 0)
+ lua_pushboolean(L, false);
+ else
+ lua_pushboolean(L, true);
+
+ return (1);
+}
+
+/** Create an interface
+ * @param name The name of an interface
+ * @return Created interface name or nil if error
+ */
+static int
+l_ifconfig_create(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name;
+ char *ifname;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+
+ name = lua_tostring(L, 2);
+ if (ifconfig_create_interface(h, name, &ifname) != 0)
+ lua_pushnil(L);
+ else
+ lua_pushstring(L, ifname);
+
+ return (1);
+}
+
+/** Create a vlan interface
+ * @param name The name of a vlan interface to create
+ * @param vlandev The name of an interface to attach to
+ * @param vlantag A vlan number to use
+ * @return The name of the created interface or nil if error
+ */
+static int
+l_ifconfig_create_vlan(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name, *vlandev;
+ char *ifname;
+ ptrdiff_t vlantag;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+ luaL_checkstring(L, 3);
+ luaL_checkinteger(L, 4);
+
+ name = lua_tostring(L, 2);
+ vlandev = lua_tostring(L, 3);
+ vlantag = lua_tointeger(L, 4);
+ luaL_argcheck(L, 0 <= vlantag && vlantag <= UINT16_MAX, 4,
+ "vlantag out of range");
+ if (ifconfig_create_interface_vlan(h, name, &ifname, vlandev, vlantag) != 0)
+ lua_pushnil(L);
+ else
+ lua_pushstring(L, ifname);
+
+ return (1);
+}
+
+/** Set vlandev and vlantag for a vlan interface
+ * @param name The name of a vlan interface
+ * @param vlandev The name of the interface to attach to
+ * @param vlantag A vlan number to use
+ * @return true if success, false if error
+ */
+static int
+l_ifconfig_set_vlantag(lua_State *L)
+{
+ ifconfig_handle_t *h;
+ const char *name, *vlandev;
+ ptrdiff_t vlantag;
+
+ h = l_ifconfig_checkhandle(L, 1);
+ luaL_checkstring(L, 2);
+ luaL_checkstring(L, 3);
+ luaL_checkinteger(L, 4);
+
+ name = lua_tostring(L, 2);
+ vlandev = lua_tostring(L, 3);
+ vlantag = lua_tointeger(L, 4);
+ luaL_argcheck(L, 0 <= vlantag && vlantag <= UINT16_MAX, 4,
+ "vlantag out of range");
+ if (ifconfig_set_vlantag(h, name, vlandev, vlantag) != 0)
+ lua_pushboolean(L, false);
+ else
+ lua_pushboolean(L, true);
+
+ return (1);
+}
+
+static const struct luaL_Reg l_ifconfig_handle[] = {
+ {"close", l_ifconfig_handle_close},
+ {"error", l_ifconfig_handle_error},
+ {"foreach_iface", l_ifconfig_foreach_iface},
+ {"foreach_ifaddr", l_ifconfig_foreach_ifaddr},
+ {"get_description", l_ifconfig_get_description},
+ {"set_description", l_ifconfig_set_description},
+ {"unset_description", l_ifconfig_unset_description},
+ {"set_name", l_ifconfig_set_name},
+ {"get_orig_name", l_ifconfig_get_orig_name},
+#if 0 /* setfib not implemented in libifconfig? */
+ {"set_fib", l_ifconfig_set_fib},
+#endif
+ {"get_fib", l_ifconfig_get_fib},
+ {"set_mtu", l_ifconfig_set_mtu},
+ {"get_mtu", l_ifconfig_get_mtu},
+ {"get_nd6", l_ifconfig_get_nd6},
+ {"set_metric", l_ifconfig_set_metric},
+ {"get_metric", l_ifconfig_get_metric},
+ {"set_capability", l_ifconfig_set_capability},
+ {"get_capability", l_ifconfig_get_capability},
+ {"get_groups", l_ifconfig_get_groups},
+ {"get_status", l_ifconfig_get_status},
+ {"get_media", l_ifconfig_get_media},
+ {"get_carp", l_ifconfig_get_carp},
+ {"addr_info", l_ifconfig_addr_info},
+ {"get_lagg_status", l_ifconfig_get_lagg_status},
+ {"get_laggport_laggdev", l_ifconfig_get_laggport_laggdev},
+ {"destroy", l_ifconfig_destroy},
+ {"create", l_ifconfig_create},
+ {"create_vlan", l_ifconfig_create_vlan},
+ {"set_vlantag", l_ifconfig_set_vlantag},
+ {NULL, NULL}
+};
+
+static void
+l_ifconfig_handle_meta(lua_State *L)
+{
+ luaL_newmetatable(L, IFCONFIG_HANDLE_META);
+
+ /* metatable.__index = metatable */
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -2, "__index");
+
+ /* Automatically close handle when garbage collected. */
+ lua_pushcfunction(L, l_ifconfig_handle_close);
+ lua_setfield(L, -2, "__gc");
+
+ luaL_setfuncs(L, l_ifconfig_handle, 0);
+
+ lua_pop(L, 1);
+}
+
+/** Get interface name
+ * @return Name of the interface as a string
+ */
+static int
+l_struct_ifaddrs_name(lua_State *L)
+{
+ struct ifaddrs *ifa;
+
+ ifa = l_ifconfig_checkifaddrs(L, 1);
+
+ lua_pushstring(L, ifa->ifa_name);
+ return (1);
+}
+
+static const struct luaL_Reg l_struct_ifaddrs[] = {
+ {"name", l_struct_ifaddrs_name},
+ {NULL, NULL}
+};
+
+static void
+l_struct_ifaddrs_meta(lua_State *L)
+{
+ luaL_newmetatable(L, STRUCT_IFADDRS_META);
+
+ /* metatable.__index = metatable */
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -2, "__index");
+
+ luaL_setfuncs(L, l_struct_ifaddrs, 0);
+
+ lua_pop(L, 1);
+}
+
+static int
+l_ifconfig_open(lua_State *L)
+{
+ ifconfig_handle_t *h, **hp;
+
+ if ((h = ifconfig_open()) == NULL) {
+ lua_pushnil(L);
+ return (1);
+ }
+
+ hp = lua_newuserdata(L, sizeof h);
+ assert(hp != NULL);
+ *hp = h;
+ luaL_getmetatable(L, IFCONFIG_HANDLE_META);
+ lua_setmetatable(L, -2);
+ return (1);
+}
+
+static const struct luaL_Reg l_ifconfig[] = {
+ {"open", l_ifconfig_open},
+ {NULL, NULL}
+};
+
+int
+luaopen_ifconfig(lua_State *L)
+{
+ l_ifconfig_handle_meta(L);
+ l_struct_ifaddrs_meta(L);
+
+ lua_newtable(L);
+ luaL_setfuncs(L, l_ifconfig, 0);
+ return (1);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Feb 25, 4:33 PM (11 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28991836
Default Alt Text
D25447.id73621.diff (35 KB)
Attached To
Mode
D25447: lib/flua: Add bindings for libifconfig
Attached
Detach File
Event Timeline
Log In to Comment