From 0ef46dc967b53f09254033027ffc9d6e129e4d4f Mon Sep 17 00:00:00 2001 From: Steven Barth Date: Mon, 30 Mar 2009 11:27:43 +0000 Subject: [PATCH] Import luanet library Relicensed with author's permission Thanks John --- contrib/package/luci/Makefile | 15 + libs/luanet/Makefile | 18 + libs/luanet/src/Makefile | 18 + libs/luanet/src/base64.c | 121 ++++++ libs/luanet/src/base64.h | 23 ++ libs/luanet/src/bridge.c | 171 +++++++++ libs/luanet/src/bridge.h | 27 ++ libs/luanet/src/df.c | 122 +++++++ libs/luanet/src/df.h | 23 ++ libs/luanet/src/helper.c | 73 ++++ libs/luanet/src/helper.h | 31 ++ libs/luanet/src/ifconfig.c | 250 +++++++++++++ libs/luanet/src/ifconfig.h | 30 ++ libs/luanet/src/iwconfig.c | 829 ++++++++++++++++++++++++++++++++++++++++++ libs/luanet/src/iwconfig.h | 28 ++ libs/luanet/src/main.c | 95 +++++ libs/luanet/src/route.c | 45 +++ libs/luanet/src/route.h | 21 ++ libs/luanet/src/test.lua | 132 +++++++ libs/luanet/src/vconfig.c | 93 +++++ libs/luanet/src/vconfig.h | 27 ++ 21 files changed, 2192 insertions(+) create mode 100644 libs/luanet/Makefile create mode 100644 libs/luanet/src/Makefile create mode 100644 libs/luanet/src/base64.c create mode 100644 libs/luanet/src/base64.h create mode 100644 libs/luanet/src/bridge.c create mode 100644 libs/luanet/src/bridge.h create mode 100644 libs/luanet/src/df.c create mode 100644 libs/luanet/src/df.h create mode 100644 libs/luanet/src/helper.c create mode 100644 libs/luanet/src/helper.h create mode 100644 libs/luanet/src/ifconfig.c create mode 100644 libs/luanet/src/ifconfig.h create mode 100644 libs/luanet/src/iwconfig.c create mode 100644 libs/luanet/src/iwconfig.h create mode 100644 libs/luanet/src/main.c create mode 100644 libs/luanet/src/route.c create mode 100644 libs/luanet/src/route.h create mode 100755 libs/luanet/src/test.lua create mode 100644 libs/luanet/src/vconfig.c create mode 100644 libs/luanet/src/vconfig.h diff --git a/contrib/package/luci/Makefile b/contrib/package/luci/Makefile index 45c3ecb59..044eca6ae 100644 --- a/contrib/package/luci/Makefile +++ b/contrib/package/luci/Makefile @@ -213,6 +213,17 @@ define Package/luci-json/install endef +define Package/luci-luanet + $(call Package/luci/libtemplate) + TITLE:=luanet + DEPENDS+=+libiw +endef + +define Package/luci-luanet/install + $(call Package/luci/install/template,$(1),libs/luanet) +endef + + NIXIO_TLS:=axtls @@ -821,6 +832,9 @@ endif ifneq ($(CONFIG_PACKAGE_luci-json),) PKG_SELECTED_MODULES+=libs/json endif +ifneq ($(CONFIG_PACKAGE_luci-luanet),) + PKG_SELECTED_MODULES+=libs/luanet +endif ifneq ($(CONFIG_PACKAGE_luci-nixio),) PKG_SELECTED_MODULES+=libs/nixio endif @@ -997,6 +1011,7 @@ $(eval $(call BuildPackage,luci-http)) $(eval $(call BuildPackage,luci-httpclient)) $(eval $(call BuildPackage,luci-ipkg)) $(eval $(call BuildPackage,luci-json)) +$(eval $(call BuildPackage,luci-luanet)) $(eval $(call BuildPackage,luci-nixio)) $(eval $(call BuildPackage,luci-uci)) $(eval $(call BuildPackage,luci-sys)) diff --git a/libs/luanet/Makefile b/libs/luanet/Makefile new file mode 100644 index 000000000..702f866b0 --- /dev/null +++ b/libs/luanet/Makefile @@ -0,0 +1,18 @@ +ifeq ($(CFLAGS),) + MYLDFLAGS ?= -L../../../contrib/uci/dist/usr/lib/ +endif + +include ../../build/module.mk +include ../../build/config.mk +include ../../build/gccconfig.mk + +compile: + make -Csrc \ + CFLAGS="$(CFLAGS) $(FPIC) $(LUA_CFLAGS) $(EXTRA_CFLAGS)" \ + LDFLAGS="$(LDFLAGS)" \ + MYLDFLAGS="$(MYLDFLAGS)" + mkdir -p dist/usr/lib/lua/ + cp src/luanet.so dist/usr/lib/lua + +clean: luaclean + make -Csrc clean diff --git a/libs/luanet/src/Makefile b/libs/luanet/src/Makefile new file mode 100644 index 000000000..852a7c4f4 --- /dev/null +++ b/libs/luanet/src/Makefile @@ -0,0 +1,18 @@ +PROGS=luanet.so +STRIP?=strip +CFLAGS?= +CFLAGS+=-pedantic -Werror -Wall -I/usr/include/lua5.1/ -std=gnu99 +LDFLAGS?= +LDFLAGS+= +OBJS=ifconfig.o bridge.o iwconfig.o helper.o route.o vconfig.o main.o df.o base64.o + +all: $(PROGS) + +$(PROGS): $(OBJS) + $(CC) $(CFLAGS) -shared -Wl,-soname,luanet -liw $(LDFLAGS) $^ -o $@ + +clean: + rm -f $(PROGS) *.o *.so + +%.o: %.c + $(CC) $(CFLAGS) -c $^ -o $@ diff --git a/libs/luanet/src/base64.c b/libs/luanet/src/base64.c new file mode 100644 index 000000000..f897cf7aa --- /dev/null +++ b/libs/luanet/src/base64.c @@ -0,0 +1,121 @@ +/* + * Base64.c + * Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com) + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include +#include + + +unsigned char map2[] = +{ + 0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, + 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33 +}; + +int b64_decode(lua_State *L) +{ + int i, v; + unsigned char out[512]; + unsigned char *dst = out; + char *in; + if(lua_gettop(L) != 1) + { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + return 0; + } + in = (char *)lua_tostring (L, 1); + v = 0; + for (i = 0; in[i] && in[i] != '='; i++) { + unsigned int index= in[i]-43; + if (index>=(sizeof(map2)/sizeof(map2[0])) || map2[index] == 0xff) + return -1; + v = (v << 6) + map2[index]; + if (i & 3) { + if (dst - out < 512) { + *dst++ = v >> (6 - 2 * (i & 3)); + } + } + } + if(!(dst - out)) + return 0; + lua_pushstring(L, (char*)out); + return 1; +} + +/***************************************************************************** +* b64_encode: stolen from VLC's http.c +* simplified by michael +* fixed edge cases and made it work from data (vs. strings) by ryan. +*****************************************************************************/ + +int b64_encode(lua_State *L) +{ + static const char b64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + char *ret, *dst, *src, tmp[1024]; + unsigned i_bits = 0; + int i_shift = 0; + int bytes_remaining, len; + if(lua_gettop(L) != 1) + { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + return 0; + } + src = (char *)lua_tostring (L, 1); + bytes_remaining = len = strlen(src); + if (len < 512) { + ret = dst = tmp; + } else + return 0; + + if (len) { // special edge case, what should we really do here? + while (bytes_remaining) { + i_bits = (i_bits << 8) + *src++; + bytes_remaining--; + i_shift += 8; + + do { + *dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f]; + i_shift -= 6; + } while (i_shift > 6 || (bytes_remaining == 0 && i_shift > 0)); + } + while ((dst - ret) & 3) + *dst++ = '='; + } + *dst = '\0'; + lua_pushstring(L, tmp); + return 1; +} diff --git a/libs/luanet/src/base64.h b/libs/luanet/src/base64.h new file mode 100644 index 000000000..e32365f8d --- /dev/null +++ b/libs/luanet/src/base64.h @@ -0,0 +1,23 @@ +/* + * Base64.c + * Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com) + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +int b64_decode(lua_State *L); +int b64_encode(lua_State *L); diff --git a/libs/luanet/src/bridge.c b/libs/luanet/src/bridge.c new file mode 100644 index 000000000..478f8b14f --- /dev/null +++ b/libs/luanet/src/bridge.c @@ -0,0 +1,171 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2008 John Crispin + * Copyright (C) 2008 Steven Barth + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static int sock_bridge = 0; +int bridge_startup() +{ + if(!sock_bridge) + sock_bridge = socket(AF_LOCAL, SOCK_STREAM, 0); + return sock_bridge; +} + +void bridge_shutdown(void) +{ + if(!sock_bridge) + return; + close(sock_bridge); + sock_bridge = 0; +} + +static inline int _bridge_new(lua_State *L, int i) +{ + char *ifname; + if(lua_gettop(L) != 1) + { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + return 0; + } + + ifname = (char *)lua_tostring (L, 1); + if(!ioctl(sock_bridge, i, ifname)) + lua_pushboolean(L, 1); + else + lua_pushboolean(L, 0); + return 1; +} + +int bridge_new(lua_State *L) +{ + return _bridge_new(L, SIOCBRADDBR); +} + +int bridge_del(lua_State *L) +{ + return _bridge_new(L, SIOCBRDELBR); +} + +static inline int _bridge_addif(lua_State *L, int i) +{ + struct ifreq ifr; + char *br, *ifname; + if(lua_gettop(L) != 2) + { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + return 0; + } + br = (char *)lua_tostring (L, 1); + ifname = (char *)lua_tostring (L, 2); + strncpy(ifr.ifr_name, br, IFNAMSIZ); + ifr.ifr_ifindex = if_nametoindex(ifname); + if(ifr.ifr_ifindex == 0) + { + lua_pushboolean(L, 0); + return 1; + } + if(!ioctl(sock_bridge, i, &ifr)) + lua_pushboolean(L, 1); + else + lua_pushboolean(L, 0); + return 1; +} + +int bridge_addif(lua_State *L) +{ + return _bridge_addif(L, SIOCBRADDIF); +} + +int bridge_delif(lua_State *L) +{ + return _bridge_addif(L, SIOCBRDELIF); +} + +#define SYSFS_PATH_MAX 512 +#define SYSFS_CLASS_NET "/sys/class/net/" +static int isbridge(const struct dirent *entry) +{ + char path[SYSFS_PATH_MAX]; + struct stat st; + + snprintf(path, SYSFS_PATH_MAX, SYSFS_CLASS_NET "%s/bridge", entry->d_name); + return stat(path, &st) == 0 && S_ISDIR(st.st_mode); +} + +static int isdev(const struct dirent *entry) +{ + if(*entry->d_name == '.') + return 0; + return 1; +} + +static inline void bridge_getifs(lua_State *L, const char *ifname) +{ + struct dirent **namelist; + int i, count = 0; + char path[SYSFS_PATH_MAX]; + snprintf(path, SYSFS_PATH_MAX, SYSFS_CLASS_NET "%s/brif", ifname); + count = scandir(path, &namelist, isdev, alphasort); + if(count < 0) + return; + + for(i = 0; i < count; i++) + { + lua_pushinteger(L, i + 1); + lua_pushstring(L, namelist[i]->d_name); + lua_settable(L, -3); + free(namelist[i]); + } + free(namelist); + return; +} + +int bridge_getall(lua_State *L) +{ + struct dirent **namelist; + int i, count = 0; + count = scandir(SYSFS_CLASS_NET, &namelist, isbridge, alphasort); + if (count < 0) + return 0; + + lua_newtable(L); + for (i = 0; i < count; i++) + { + lua_pushstring(L, namelist[i]->d_name); + lua_newtable(L); + bridge_getifs(L, namelist[i]->d_name); + free(namelist[i]); + lua_settable(L, -3); + } + free(namelist); + return 1; +} diff --git a/libs/luanet/src/bridge.h b/libs/luanet/src/bridge.h new file mode 100644 index 000000000..87202f64f --- /dev/null +++ b/libs/luanet/src/bridge.h @@ -0,0 +1,27 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2008 John Crispin + * Copyright (C) 2008 Steven Barth + */ + +#ifndef _BRIDGE_H__ +#define _BRIDGE_H__ +int bridge_startup(void); +void bridge_shutdown(void); +int bridge_new(lua_State *L); +int bridge_del(lua_State *L); +int bridge_addif(lua_State *L); +int bridge_delif(lua_State *L); +int bridge_getall(lua_State *L); +#endif diff --git a/libs/luanet/src/df.c b/libs/luanet/src/df.c new file mode 100644 index 000000000..be582f6ef --- /dev/null +++ b/libs/luanet/src/df.c @@ -0,0 +1,122 @@ +/* based on busybox code */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "helper.h" + +struct mntent *find_mount_point(const char *name, const char *table) +{ + struct stat s; + dev_t mountDevice; + FILE *mountTable; + struct mntent *mountEntry; + + if (stat(name, &s) != 0) + return 0; + + if ((s.st_mode & S_IFMT) == S_IFBLK) + mountDevice = s.st_rdev; + else + mountDevice = s.st_dev; + + + mountTable = setmntent(table ? table : "/etc/mtab", "r"); + if (!mountTable) + return 0; + + while ((mountEntry = getmntent(mountTable)) != 0) { + if (strcmp(name, mountEntry->mnt_dir) == 0 + || strcmp(name, mountEntry->mnt_fsname) == 0 + ) { /* String match. */ + break; + } + if (stat(mountEntry->mnt_fsname, &s) == 0 && s.st_rdev == mountDevice) /* Match the device. */ + break; + if (stat(mountEntry->mnt_dir, &s) == 0 && s.st_dev == mountDevice) /* Match the directory's mount point. */ + break; + } + endmntent(mountTable); + return mountEntry; +} + +static unsigned long kscale(unsigned long b, unsigned long bs) +{ + return (b * (unsigned long long) bs + 1024/2) / 1024; +} + +int df(lua_State *L) +{ + unsigned long blocks_used; + unsigned blocks_percent_used; + FILE *mount_table; + struct mntent *mount_entry = 0; + struct statfs s; + /* default display is kilobytes */ + const char *disp_units_hdr = "1k-blocks"; + int cnt = 0; + printf("Filesystem %-15sUsed Available Use%% Mounted on\n", + disp_units_hdr); + + mount_table = NULL; + mount_table = setmntent("/etc/mtab", "r"); + lua_newtable(L); + while (1) { + const char *device; + const char *mount_point; + + if (mount_table) { + mount_entry = getmntent(mount_table); + if (!mount_entry) { + endmntent(mount_table); + break; + } + } + + device = mount_entry->mnt_fsname; + mount_point = mount_entry->mnt_dir; + + if (statfs(mount_point, &s) != 0) { + perror(mount_point); + continue; + } + + if ((s.f_blocks > 0) || !mount_table) + { + blocks_used = s.f_blocks - s.f_bfree; + blocks_percent_used = 0; + if (blocks_used + s.f_bavail) + { + blocks_percent_used = (blocks_used * 100ULL + (blocks_used + s.f_bavail) / 2 ) + / (blocks_used + s.f_bavail); + } + lua_pushinteger(L, ++cnt); + lua_newtable(L); + + add_table_entry_int(L, "blocks", kscale(s.f_blocks, s.f_bsize)); + add_table_entry_int(L, "used", kscale(s.f_blocks-s.f_bfree, s.f_bsize)); + add_table_entry_int(L, "avail", kscale(s.f_bavail, s.f_bsize)); + add_table_entry_int(L, "percent", blocks_percent_used); + add_table_entry(L, "device", device); + add_table_entry(L, "mountpoint", mount_point); + add_table_entry_int(L, "blocksize", s.f_bsize); + lua_settable(L, -3); + + /*printf("\n%-20s" + 1, device) + printf(" %9lu %9lu %9lu %3u%% %s\n", + kscale(s.f_blocks, s.f_bsize), + kscale(s.f_blocks-s.f_bfree, s.f_bsize), + kscale(s.f_bavail, s.f_bsize), + blocks_percent_used, mount_point);*/ + } + } + return 1; +} diff --git a/libs/luanet/src/df.h b/libs/luanet/src/df.h new file mode 100644 index 000000000..7fe3f6e43 --- /dev/null +++ b/libs/luanet/src/df.h @@ -0,0 +1,23 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2008 John Crispin + * Copyright (C) 2008 Steven Barth + */ + +#ifndef _DF_H__ +#define _DF_H__ + +int df(lua_State *L); + +#endif diff --git a/libs/luanet/src/helper.c b/libs/luanet/src/helper.c new file mode 100644 index 000000000..57679925b --- /dev/null +++ b/libs/luanet/src/helper.c @@ -0,0 +1,73 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2008 John Crispin + * Copyright (C) 2008 Steven Barth + */ + +#include +#include +#include + +#include +#include +#include + +int char2ipv4(char *c, char *ip) +{ + int i; + char *tmp = strdup(c); + char *t = tmp; + char *e = NULL; + int ret = -1; + for(i = 0; i < 4; i++) + { + int j = strtol(t, &e, 10); + if((j < 0) || (j > 255)) + goto error; + if(i != 3) + if(*e != '.') + goto error; + *ip++ = j; + t = e + 1; + } + ret = 0; +error: + free(tmp); + return ret; +} + +void ipv42char(char *b, char *ip) +{ + sprintf(ip, "%d.%d.%d.%d", b[0] & 0xff, b[1] & 0xff, b[2] & 0xff, b[3] & 0xff); +} + +void mac2char(char *b, char *mac) +{ + sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", + b[0] & 0xff, b[1] & 0xff, b[2] & 0xff, b[3] & 0xff, b[4] & 0xff, b[5] & 0xff); +} + +void add_table_entry(lua_State *L, const char *k, const char *v) +{ + lua_pushstring(L, k); + lua_pushstring(L, v); + lua_settable(L, -3); +} + +void add_table_entry_int(lua_State *L, const char *k, int v) +{ + lua_pushstring(L, k); + lua_pushinteger(L, v); + lua_settable(L, -3); +} diff --git a/libs/luanet/src/helper.h b/libs/luanet/src/helper.h new file mode 100644 index 000000000..dec55529b --- /dev/null +++ b/libs/luanet/src/helper.h @@ -0,0 +1,31 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2008 John Crispin + * Copyright (C) 2008 Steven Barth + */ + +#ifndef _HELPER_H__ +#define _HELPER_H__ + +#include +#include +#include + +int char2ipv4(char *c, char *ip); +void ipv42char(char *b, char *ip); +void mac2char(char *b, char *mac); +void add_table_entry(lua_State *L, const char *k, const char *v); +void add_table_entry_int(lua_State *L, const char *k, int v); + +#endif diff --git a/libs/luanet/src/ifconfig.c b/libs/luanet/src/ifconfig.c new file mode 100644 index 000000000..58ce45e90 --- /dev/null +++ b/libs/luanet/src/ifconfig.c @@ -0,0 +1,250 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2008 John Crispin + * Copyright (C) 2008 Steven Barth + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "helper.h" + +int sock_ifconfig = 0; + +int ifc_startup(void) +{ + if(!sock_ifconfig) + sock_ifconfig = socket(AF_INET, SOCK_DGRAM, 0); + return sock_ifconfig; +} + +void ifc_shutdown(void) +{ + if(!sock_ifconfig) + return; + close(sock_ifconfig); + sock_ifconfig = 0; +} + +static int isdev(const struct dirent *entry) +{ + if(*entry->d_name == '.') + return 0; + return 1; +} + +static void ifc_addif(lua_State *L, char *ifname) +{ + char *ip = malloc(32); + struct ifreq ifr; + lua_pushstring(L, ifname); + lua_newtable(L); + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + + if(!ioctl(sock_ifconfig, SIOCGIFADDR, &ifr)) + { + ipv42char(&ifr.ifr_addr.sa_data[2], ip); + add_table_entry(L, "ip", ip); + } + + if(!ioctl(sock_ifconfig, SIOCGIFNETMASK, &ifr)) + { + ipv42char(&ifr.ifr_netmask.sa_data[2], ip); + add_table_entry(L, "netmask", ip); + } + + if(!ioctl(sock_ifconfig, SIOCGIFBRDADDR, &ifr)) + { + ipv42char(&ifr.ifr_broadaddr.sa_data[2], ip); + add_table_entry(L, "broadaddr", ip); + } + + if(!ioctl(sock_ifconfig, SIOCGIFHWADDR, &ifr)) + { + mac2char(ifr.ifr_hwaddr.sa_data, ip); + add_table_entry(L, "mac", ip); + } + + if(!ioctl(sock_ifconfig, SIOCGIFFLAGS, &ifr)) + { + if(ifr.ifr_flags & IFF_UP) + add_table_entry(L, "up", "1"); + else + add_table_entry(L, "up", "0"); + } + + ioctl(sock_ifconfig, SIOCGIFMTU, &ifr); + lua_pushstring(L, "mtu"); + lua_pushinteger(L, ifr.ifr_mtu); + lua_settable(L, -3); + free(ip); + lua_settable(L, -3); +} + +#define SYSFS_CLASS_NET "/sys/class/net/" +int ifc_getall(lua_State *L) +{ + int numreqs = 50; + struct dirent **namelist; + int i, count = 0; + struct ifconf ifc; + struct ifreq *ifr; + ifc.ifc_buf = NULL; + count = scandir(SYSFS_CLASS_NET, &namelist, isdev, alphasort); + if (count < 0) + { + return 0; + } + lua_newtable(L); + for (i = 0; i < count; i++) + { + ifc_addif(L, namelist[i]->d_name); + free(namelist[i]); + } + free(namelist); + + ifc.ifc_len = sizeof(struct ifreq) * numreqs; + ifc.ifc_buf = malloc(ifc.ifc_len); + if(ioctl(sock_ifconfig, SIOCGIFCONF, &ifc) < 0) + goto out; + ifr = ifc.ifc_req; + for(i = 0; i < ifc.ifc_len; i += sizeof(struct ifreq)) + { + if(strchr(ifr->ifr_name, ':')) + ifc_addif(L, ifr->ifr_name); + ifr++; + } +out: + free(ifc.ifc_buf); + return 1; +} + +static inline int _ifc_setip(lua_State *L, int i) +{ + struct ifreq ifr; + char *ifname, *ip; + if(lua_gettop(L) != 2) + { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + return 0; + } + ifname = (char *)lua_tostring (L, 1); + ip = (char *)lua_tostring (L, 2); + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + ifr.ifr_addr.sa_family = AF_INET; + if(char2ipv4(ip, &ifr.ifr_addr.sa_data[2])) + { + lua_pushstring(L, "invalid ip"); + lua_error(L); + return 0; + } + if(!ioctl(sock_ifconfig, i, &ifr)) + lua_pushboolean(L, 1); + else + lua_pushboolean(L, 0); + return 1; +} + +int ifc_setip(lua_State *L) +{ + return _ifc_setip(L, SIOCSIFADDR); +} + +int ifc_setnetmask(lua_State *L) +{ + return _ifc_setip(L, SIOCGIFNETMASK); +} + +int ifc_setbroadcast(lua_State *L) +{ + return _ifc_setip(L, SIOCSIFBRDADDR); +} + +int ifc_setmtu(lua_State *L) +{ + struct ifreq ifr; + char *ifname; + int mtu; + if(lua_gettop(L) != 2) + { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + return 0; + } + ifname = (char *)lua_tostring (L, 1); + mtu = (int)lua_tointeger (L, 2); + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + ifr.ifr_mtu = mtu; + if(!ioctl(sock_ifconfig, SIOCSIFMTU, &ifr)) + lua_pushboolean(L, 1); + else + lua_pushboolean(L, 0); + return 1; +} + +static int _ifc_up(lua_State *L, int up) +{ + struct ifreq ifr; + char *ifname; + if(lua_gettop(L) != 1) + { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + return 0; + } + + ifname = (char *)lua_tostring (L, 1); + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + + if(ioctl(sock_ifconfig, SIOCGIFFLAGS, &ifr) < 0) + { + lua_pushboolean(L, 0); + return 1; + } + if(up) + ifr.ifr_flags |= IFF_UP | IFF_RUNNING; + else + ifr.ifr_flags &= ~IFF_UP; + if(!ioctl(sock_ifconfig, SIOCSIFFLAGS, &ifr)) + lua_pushboolean(L, 1); + else + lua_pushboolean(L, 0); + return 1; +} + +int ifc_up(lua_State *L) +{ + return _ifc_up(L, 1); +} + +int ifc_down(lua_State *L) +{ + return _ifc_up(L, 0); +} + diff --git a/libs/luanet/src/ifconfig.h b/libs/luanet/src/ifconfig.h new file mode 100644 index 000000000..dffffd583 --- /dev/null +++ b/libs/luanet/src/ifconfig.h @@ -0,0 +1,30 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2008 John Crispin + * Copyright (C) 2008 Steven Barth + */ + +#ifndef _IFCONFIG_H__ +#define _IFCONFIG_H__ +int ifc_startup(void); +void ifc_shutdown(void); + +int ifc_getall(lua_State *L); +int ifc_setip(lua_State *L); +int ifc_setnetmask(lua_State *L); +int ifc_setbroadcast(lua_State *L); +int ifc_setmtu(lua_State *L); +int ifc_up(lua_State *L); +int ifc_down(lua_State *L); +#endif diff --git a/libs/luanet/src/iwconfig.c b/libs/luanet/src/iwconfig.c new file mode 100644 index 000000000..5fc65b607 --- /dev/null +++ b/libs/luanet/src/iwconfig.c @@ -0,0 +1,829 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2008 John Crispin + * Copyright (C) 2008 Steven Barth + */ + +#include +#include +#include +#include +#include +#include +#include +#include "iwlib.h" + +#include +#include +#include + +#include "helper.h" + +static int sock_iwconfig = 0; + +typedef struct iwscan_state +{ + /* State */ + int ap_num; /* Access Point number 1->N */ + int val_index; /* Value in table 0->(N-1) */ +} iwscan_state; + +int iwc_startup(void) +{ + if(!sock_iwconfig) + sock_iwconfig = iw_sockets_open(); + return sock_iwconfig; +} + +void iwc_shutdown(void) +{ + if(!sock_iwconfig) + return; + iw_sockets_close(sock_iwconfig); + sock_iwconfig = 0; +} + +/* taken from wireless tools */ +static int +get_info(char * ifname, struct wireless_info * info) +{ + struct iwreq wrq; + + memset((char*) info, 0, sizeof(struct wireless_info)); + + /* Get basic information */ + if(iw_get_basic_config(sock_iwconfig, ifname, &(info->b)) < 0) + { + /* If no wireless name : no wireless extensions */ + /* But let's check if the interface exists at all */ + struct ifreq ifr; + + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + if(ioctl(sock_iwconfig, SIOCGIFFLAGS, &ifr) < 0) + return(-ENODEV); + else + return(-ENOTSUP); + } + + /* Get ranges */ + if(iw_get_range_info(sock_iwconfig, ifname, &(info->range)) >= 0) + info->has_range = 1; + + /* Get AP address */ + if(iw_get_ext(sock_iwconfig, ifname, SIOCGIWAP, &wrq) >= 0) + { + info->has_ap_addr = 1; + memcpy(&(info->ap_addr), &(wrq.u.ap_addr), sizeof (sockaddr)); + } + + /* Get bit rate */ + if(iw_get_ext(sock_iwconfig, ifname, SIOCGIWRATE, &wrq) >= 0) + { + info->has_bitrate = 1; + memcpy(&(info->bitrate), &(wrq.u.bitrate), sizeof(iwparam)); + } + + /* Get Power Management settings */ + wrq.u.power.flags = 0; + if(iw_get_ext(sock_iwconfig, ifname, SIOCGIWPOWER, &wrq) >= 0) + { + info->has_power = 1; + memcpy(&(info->power), &(wrq.u.power), sizeof(iwparam)); + } + + /* Get stats */ + if(iw_get_stats(sock_iwconfig, ifname, &(info->stats), + &info->range, info->has_range) >= 0) + { + info->has_stats = 1; + } + + /* Get NickName */ + wrq.u.essid.pointer = (caddr_t) info->nickname; + wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1; + wrq.u.essid.flags = 0; + if(iw_get_ext(sock_iwconfig, ifname, SIOCGIWNICKN, &wrq) >= 0) + if(wrq.u.data.length > 1) + info->has_nickname = 1; + + if((info->has_range) && (info->range.we_version_compiled > 9)) + { + /* Get Transmit Power */ + if(iw_get_ext(sock_iwconfig, ifname, SIOCGIWTXPOW, &wrq) >= 0) + { + info->has_txpower = 1; + memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam)); + } + } + + /* Get sensitivity */ + if(iw_get_ext(sock_iwconfig, ifname, SIOCGIWSENS, &wrq) >= 0) + { + info->has_sens = 1; + memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam)); + } + + if((info->has_range) && (info->range.we_version_compiled > 10)) + { + /* Get retry limit/lifetime */ + if(iw_get_ext(sock_iwconfig, ifname, SIOCGIWRETRY, &wrq) >= 0) + { + info->has_retry = 1; + memcpy(&(info->retry), &(wrq.u.retry), sizeof(iwparam)); + } + } + + /* Get RTS threshold */ + if(iw_get_ext(sock_iwconfig, ifname, SIOCGIWRTS, &wrq) >= 0) + { + info->has_rts = 1; + memcpy(&(info->rts), &(wrq.u.rts), sizeof(iwparam)); + } + + /* Get fragmentation threshold */ + if(iw_get_ext(sock_iwconfig, ifname, SIOCGIWFRAG, &wrq) >= 0) + { + info->has_frag = 1; + memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam)); + } + + return(0); +} + +void iwc_get(lua_State *L, char *ifname) +{ + struct wireless_info info; + int rc = get_info(ifname, &info); + char buffer[128]; + if(rc) + return; + + lua_pushstring(L, ifname); + lua_newtable(L); + + if(info.b.has_essid) + { + if(info.b.essid_on) + add_table_entry(L, "essid", info.b.essid); + else + add_table_entry(L, "essid", "off"); + } + + if(info.b.has_mode) + add_table_entry(L, "mode", iw_operation_mode[info.b.mode]); + + if(info.b.has_freq) + { + double freq = info.b.freq; /* Frequency/channel */ + int channel = -1; /* Converted to channel */ + char tmp[4]; + if(info.has_range && (freq < KILO)) + channel = iw_channel_to_freq((int) freq, &freq, &info.range); + iw_print_freq(buffer, sizeof(buffer), freq, -1, info.b.freq_flags); + snprintf(tmp, 4, "%d", channel); + add_table_entry(L, "channel", tmp); + add_table_entry(L, "freq", buffer); + } + + if(info.has_ap_addr) + add_table_entry(L, "macap", iw_sawap_ntop(&info.ap_addr, buffer)); + + if(info.has_bitrate) + { + iw_print_bitrate(buffer, sizeof(buffer), info.bitrate.value); + add_table_entry(L, "bitrate", buffer); + } + + if(info.has_txpower) + { + iw_print_txpower(buffer, sizeof(buffer), &info.txpower); + add_table_entry(L, "txpower", buffer); + } + lua_settable(L, -3); +} + +int iwc_getall(lua_State *L) +{ + FILE *fp; + char buffer[128]; + char *b = buffer; + fp = fopen("/proc/net/wireless", "r"); + if(!fp) + return -1; + fgets(buffer, 128, fp); + fgets(buffer, 128, fp); + lua_newtable(L); + while(fgets(buffer, 128, fp)) + { + char *t; + b = buffer; + while(*b == ' ') + b++; + t = strstr(b, ":"); + if(t) + *t = '\0'; + iwc_get(L, b); + } + return 1; +} + +/* taken from wireless tools */ +int iwc_set_essid(lua_State *L) +{ + struct iwreq wrq; + int i = 1; + char essid[IW_ESSID_MAX_SIZE + 1]; + int we_kernel_version; + char *ifname, *e; + if(lua_gettop(L) != 2) + { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + return 0; + } + ifname = (char *)lua_tostring (L, 1); + e = (char *)lua_tostring (L, 2); + + if((!strcasecmp(e, "off")) | (!strcasecmp(e, "any"))) + { + wrq.u.essid.flags = 0; + essid[0] = '\0'; + } else if(!strcasecmp(e, "on")) + { + /* Get old essid */ + memset(essid, '\0', sizeof(essid)); + wrq.u.essid.pointer = (caddr_t) essid; + wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1; + wrq.u.essid.flags = 0; + if(iw_get_ext(sock_iwconfig, ifname, SIOCGIWESSID, &wrq) < 0) + return 0; + wrq.u.essid.flags = 1; + } else { + wrq.u.essid.flags = 1; + strcpy(essid, e); /* Size checked, all clear */ + i++; + } + + /* Get version from kernel, device may not have range... */ + we_kernel_version = iw_get_kernel_we_version(); + + /* Finally set the ESSID value */ + wrq.u.essid.pointer = (caddr_t) essid; + wrq.u.essid.length = strlen(essid); + if(we_kernel_version < 21) + wrq.u.essid.length++; + + if(!iw_set_ext(sock_iwconfig, ifname, SIOCSIWESSID, &wrq)) + lua_pushboolean(L, 1); + else + lua_pushboolean(L, 0); + return 1; +} + +/* taken from wireless tools */ +int iwc_set_mode(lua_State *L) +{ + struct iwreq wrq; + unsigned int k; /* Must be unsigned */ + char *ifname, *mode; + + if(lua_gettop(L) != 2) + { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + return 0; + } + ifname = (char *)lua_tostring (L, 1); + mode = (char *)lua_tostring (L, 2); + + /* Check if it is a uint, otherwise get is as a string */ + if(sscanf(mode, "%ui", &k) != 1) + { + k = 0; + while((k < IW_NUM_OPER_MODE) && strncasecmp(mode, iw_operation_mode[k], 3)) + k++; + } + if(k >= IW_NUM_OPER_MODE) + return 0; + + wrq.u.mode = k; + if(!iw_set_ext(sock_iwconfig, ifname, SIOCSIWMODE, &wrq)) + lua_pushboolean(L, 1); + else + lua_pushboolean(L, 0); + return 1; +} + +int iwc_set_channel(lua_State *L) +{ + struct iwreq wrq; + char *ifname; + int channel; + if(lua_gettop(L) != 2) + { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + return 0; + } + ifname = (char *)lua_tostring (L, 1); + channel = (int)lua_tointeger(L, 2); + + if(channel == -1) + { + wrq.u.freq.m = -1; + wrq.u.freq.e = 0; + wrq.u.freq.flags = 0; + } else { + iw_float2freq(channel, &wrq.u.freq); + wrq.u.freq.flags = IW_FREQ_FIXED; + } + if(!iw_set_ext(sock_iwconfig, ifname, SIOCSIWFREQ, &wrq)) + lua_pushboolean(L, 1); + else + lua_pushboolean(L, 0); + return 1; +} + +static const char * iw_ie_cypher_name[] = { + "none", + "WEP-40", + "TKIP", + "WRAP", + "CCMP", + "WEP-104", +}; +#define IW_ARRAY_LEN(x) (sizeof(x)/sizeof((x)[0])) +#define IW_IE_CYPHER_NUM IW_ARRAY_LEN(iw_ie_cypher_name) + +static const char * iw_ie_key_mgmt_name[] = { + "none", + "802.1x", + "PSK", +}; +#define IW_IE_KEY_MGMT_NUM IW_ARRAY_LEN(iw_ie_key_mgmt_name) + +static inline void iw_print_ie_wpa(lua_State *L, unsigned char * iebuf, int buflen) +{ + int ielen = iebuf[1] + 2; + int offset = 2; /* Skip the IE id, and the length. */ + unsigned char wpa1_oui[3] = {0x00, 0x50, 0xf2}; + unsigned char wpa2_oui[3] = {0x00, 0x0f, 0xac}; + unsigned char *wpa_oui; + int i; + uint16_t ver = 0; + uint16_t cnt = 0; + int wpa1 = 0, wpa2 = 0; + char buf[256]; + if(ielen > buflen) + ielen = buflen; + + switch(iebuf[0]) + { + case 0x30: /* WPA2 */ + /* Check if we have enough data */ + if(ielen < 4) + return; + wpa_oui = wpa2_oui; + break; + + case 0xdd: /* WPA or else */ + wpa_oui = wpa1_oui; + /* Not all IEs that start with 0xdd are WPA. + * * So check that the OUI is valid. */ + if((ielen < 8) + || ((memcmp(&iebuf[offset], wpa_oui, 3) != 0) + && (iebuf[offset+3] == 0x01))) + { + return; + } + + offset += 4; + break; + + default: + return; + } + + /* Pick version number (little endian) */ + ver = iebuf[offset] | (iebuf[offset + 1] << 8); + offset += 2; + + if(iebuf[0] == 0xdd) + wpa1 = 1; + if(iebuf[0] == 0x30) + wpa2 = 1; + + if(ielen < (offset + 4)) + { + if(wpa1) + { + add_table_entry(L, "wpa1gcipher", "TKIP"); + add_table_entry(L, "wpa1pcipher", "TKIP"); + } else { + add_table_entry(L, "wpa2gcipher", "TKIP"); + add_table_entry(L, "wpa2pcipher", "TKIP"); + } + return; + } + + if(memcmp(&iebuf[offset], wpa_oui, 3) != 0) + { + if(wpa1) + add_table_entry(L, "wpa1gcipher", "Proprietary"); + else + add_table_entry(L, "wpa2gcipher", "Proprietary"); + } else { + if(wpa1) + add_table_entry(L, "wpa1gcipher", iebuf[offset+3][iw_ie_cypher_name]); + else + add_table_entry(L, "wpa2gcipher", iebuf[offset+3][iw_ie_cypher_name]); + } + offset += 4; + + if(ielen < (offset + 2)) + { + if(wpa1) + add_table_entry(L, "wpa1pcipher", "TKIP"); + else + add_table_entry(L, "wpa2pcipher", "TKIP"); + return; + } + /* Otherwise, we have some number of pairwise ciphers. */ + cnt = iebuf[offset] | (iebuf[offset + 1] << 8); + offset += 2; + if(ielen < (offset + 4*cnt)) + return; + *buf = '\0'; + for(i = 0; i < cnt; i++) + { + if(i > 0) + strncat(buf, " ", 256); + if(memcmp(&iebuf[offset], wpa_oui, 3) != 0) + { + strncat(buf, "Proprietary", 256); + } else { + if(iebuf[offset+3] <= IW_IE_CYPHER_NUM) + strncat(buf, iw_ie_cypher_name[iebuf[offset+3]], 256); + else + strncat(buf, "unknown", 256); + } + offset+=4; + } + if(wpa1) + add_table_entry(L, "wpa1pcipher", buf); + else + add_table_entry(L, "wpa2pcipher", buf); + + /* Check if we are done */ + if(ielen < (offset + 2)) + return; + + /* Now, we have authentication suites. */ + cnt = iebuf[offset] | (iebuf[offset + 1] << 8); + offset += 2; + *buf = '\0'; + if(ielen < (offset + 4*cnt)) + return; + + for(i = 0; i < cnt; i++) + { + if(i != 0) + strncat(buf, " ", 256); + if(memcmp(&iebuf[offset], wpa_oui, 3) != 0) + { + strncat(buf, "Proprietary", 256); + } else { + if(iebuf[offset+3] <= IW_IE_KEY_MGMT_NUM) + strncat(buf, iw_ie_key_mgmt_name[iebuf[offset+3]], 256); + else + strncat(buf, "unknown", 256); + } + offset+=4; + } + if(wpa1) + add_table_entry(L, "wpa1auth", buf); + else + add_table_entry(L, "wpa2auth", buf); + /* Check if we are done */ + if(ielen < (offset + 1)) + return; +} + +static inline void print_scanning_token(lua_State *L, struct stream_descr *stream, + struct iw_event *event, struct iwscan_state *state, struct iw_range *iw_range, int has_range) +{ + char buffer[128]; /* Temporary buffer */ + + /* Now, let's decode the event */ + switch(event->cmd) + { + case SIOCGIWAP: + add_table_entry(L, "addr", iw_saether_ntop(&event->u.ap_addr, buffer)); + state->ap_num++; + break; + case SIOCGIWFREQ: + { + double freq; /* Frequency/channel */ + int channel = -1; /* Converted to channel */ + freq = iw_freq2float(&(event->u.freq)); + /* Convert to channel if possible */ + if(has_range) + channel = iw_freq_to_channel(freq, iw_range); + snprintf(buffer, 128, "%1.3f", freq); + add_table_entry(L, "frequency", buffer); + snprintf(buffer, 128, "%d", channel); + add_table_entry(L, "channel", buffer); + //iw_print_freq(buffer, sizeof(buffer), freq, channel, event->u.freq.flags); + //printf(" %s\n", buffer); + } + break; + case SIOCGIWMODE: + /* Note : event->u.mode is unsigned, no need to check <= 0 */ + if(event->u.mode >= IW_NUM_OPER_MODE) + event->u.mode = IW_NUM_OPER_MODE; + add_table_entry(L, "mode", iw_operation_mode[event->u.mode]); + break; + case SIOCGIWESSID: + { + char essid[IW_ESSID_MAX_SIZE+1]; + memset(essid, '\0', sizeof(essid)); + if((event->u.essid.pointer) && (event->u.essid.length)) + memcpy(essid, event->u.essid.pointer, event->u.essid.length); + if(event->u.essid.flags) + add_table_entry(L, "essid", essid); + else + add_table_entry(L, "essid", "off/any/hidden"); + } + break; + case SIOCGIWENCODE: + { + unsigned char key[IW_ENCODING_TOKEN_MAX]; + if(event->u.data.pointer) + memcpy(key, event->u.data.pointer, event->u.data.length); + else + event->u.data.flags |= IW_ENCODE_NOKEY; + if(event->u.data.flags & IW_ENCODE_DISABLED) + { + add_table_entry(L, "key", "off"); + } else { + iw_print_key(buffer, sizeof(buffer), key, event->u.data.length, + event->u.data.flags); + add_table_entry(L, "key", buffer); + } + } + break; + case SIOCGIWRATE: + if(state->val_index == 0) + { + lua_pushstring(L, "bitrates"); + lua_newtable(L); + } + //iw_print_bitrate(buffer, sizeof(buffer), event->u.bitrate.value); + snprintf(buffer, sizeof(buffer), "%d", event->u.bitrate.value); + lua_pushinteger(L, state->val_index + 1); + lua_pushstring(L, buffer); + lua_settable(L, -3); + + /* Check for termination */ + if(stream->value == NULL) + { + lua_settable(L, -3); + state->val_index = 0; + } else + state->val_index++; + break; + case IWEVGENIE: + { + int offset = 0; + unsigned char *buffer = event->u.data.pointer; + int buflen = event->u.data.length; + while(offset <= (buflen - 2)) + { + switch(buffer[offset]) + { + case 0xdd: /* WPA1 (and other) */ + case 0x30: /* WPA2 */ + iw_print_ie_wpa(L, buffer + offset, buflen); + break; + default: + break; + } + offset += buffer[offset+1] + 2; + } + } + break; + default: + break; + } /* switch(event->cmd) */ +} + +int iwc_scan(lua_State *L) +{ + struct iwreq wrq; + struct iw_scan_req scanopt; /* Options for 'set' */ + int scanflags = 0; /* Flags for scan */ + unsigned char *buffer = NULL; /* Results */ + int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */ + struct iw_range range; + int has_range; + struct timeval tv; /* Select timeout */ + int timeout = 15000000; /* 15s */ + char *ifname; + if(lua_gettop(L) != 1) + { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + return 0; + } + ifname = (char *)lua_tostring (L, 1); + + /* Debugging stuff */ + if((IW_EV_LCP_PK2_LEN != IW_EV_LCP_PK_LEN) || (IW_EV_POINT_PK2_LEN != IW_EV_POINT_PK_LEN)) + { + fprintf(stderr, "*** Please report to jt@hpl.hp.com your platform details\n"); + fprintf(stderr, "*** and the following line :\n"); + fprintf(stderr, "*** IW_EV_LCP_PK2_LEN = %zu ; IW_EV_POINT_PK2_LEN = %zu\n\n", + IW_EV_LCP_PK2_LEN, IW_EV_POINT_PK2_LEN); + } + + /* Get range stuff */ + has_range = (iw_get_range_info(sock_iwconfig, ifname, &range) >= 0); + + /* Check if the interface could support scanning. */ + if((!has_range) || (range.we_version_compiled < 14)) + { + lua_pushstring(L, "interface does not support scanning"); + lua_error(L); + return 0; + } + + /* Init timeout value -> 250ms between set and first get */ + tv.tv_sec = 0; + tv.tv_usec = 250000; + + /* Clean up set args */ + memset(&scanopt, 0, sizeof(scanopt)); + + wrq.u.data.pointer = NULL; + wrq.u.data.flags = 0; + wrq.u.data.length = 0; + + /* Initiate Scanning */ + if(iw_set_ext(sock_iwconfig, ifname, SIOCSIWSCAN, &wrq) < 0) + { + if((errno != EPERM) || (scanflags != 0)) + { + lua_pushstring(L, "interface does not support scanning"); + lua_error(L); + return 0; + } + /* If we don't have the permission to initiate the scan, we may + * * still have permission to read left-over results. + * * But, don't wait !!! */ + #if 0 + /* Not cool, it display for non wireless interfaces... */ + fprintf(stderr, "%-8.16s (Could not trigger scanning, just reading left-over results)\n", ifname); + #endif + tv.tv_usec = 0; + } + timeout -= tv.tv_usec; + + /* Forever */ + while(1) + { + fd_set rfds; /* File descriptors for select */ + int last_fd; /* Last fd */ + int ret; + + /* Guess what ? We must re-generate rfds each time */ + FD_ZERO(&rfds); + last_fd = -1; + /* In here, add the rtnetlink fd in the list */ + + /* Wait until something happens */ + ret = select(last_fd + 1, &rfds, NULL, NULL, &tv); + + /* Check if there was an error */ + if(ret < 0) + { + if(errno == EAGAIN || errno == EINTR) + continue; + lua_pushstring(L, "unhandled signal"); + lua_error(L); + return 0; + } + + /* Check if there was a timeout */ + if(ret == 0) + { + unsigned char * newbuf; + +realloc: + /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */ + newbuf = realloc(buffer, buflen); + if(newbuf == NULL) + { + if(buffer) + free(buffer); + fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__); + return 0; + } + buffer = newbuf; + + /* Try to read the results */ + wrq.u.data.pointer = buffer; + wrq.u.data.flags = 0; + wrq.u.data.length = buflen; + if(iw_get_ext(sock_iwconfig, ifname, SIOCGIWSCAN, &wrq) < 0) + { + /* Check if buffer was too small (WE-17 only) */ + if((errno == E2BIG) && (range.we_version_compiled > 16)) + { + /* Some driver may return very large scan results, either + * because there are many cells, or because they have many + * large elements in cells (like IWEVCUSTOM). Most will + * only need the regular sized buffer. We now use a dynamic + * allocation of the buffer to satisfy everybody. Of course, + * as we don't know in advance the size of the array, we try + * various increasing sizes. Jean II */ + + /* Check if the driver gave us any hints. */ + if(wrq.u.data.length > buflen) + buflen = wrq.u.data.length; + else + buflen *= 2; + + /* Try again */ + goto realloc; + } + + /* Check if results not available yet */ + if(errno == EAGAIN) + { + /* Restart timer for only 100ms*/ + tv.tv_sec = 0; + tv.tv_usec = 100000; + timeout -= tv.tv_usec; + if(timeout > 0) + continue; /* Try again later */ + } + + /* Bad error */ + free(buffer); + fprintf(stderr, "%-8.16s Failed to read scan data : %s\n\n", + ifname, strerror(errno)); + return 0; + } else + /* We have the results, go to process them */ + break; + } + + /* In here, check if event and event type + * * if scan event, read results. All errors bad & no reset timeout */ + } + + if(wrq.u.data.length) + { + struct iw_event iwe; + struct stream_descr stream; + struct iwscan_state state = { .ap_num = 1, .val_index = 0 }; + int ret; + int table = 0; + iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length); + lua_newtable(L); + do + { + /* Extract an event and print it */ + ret = iw_extract_event_stream(&stream, &iwe, + range.we_version_compiled); + if(ret > 0) + { + if(iwe.cmd == SIOCGIWAP) + { + if(table) + lua_settable(L, -3); + table = 1; + lua_pushinteger(L, state.ap_num); + lua_newtable(L); + } + print_scanning_token(L, &stream, &iwe, &state, &range, has_range); + } + } while(ret > 0); + lua_settable(L, -3); + free(buffer); + return 1; + } + free(buffer); + return 0; +} diff --git a/libs/luanet/src/iwconfig.h b/libs/luanet/src/iwconfig.h new file mode 100644 index 000000000..59240d570 --- /dev/null +++ b/libs/luanet/src/iwconfig.h @@ -0,0 +1,28 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2008 John Crispin + * Copyright (C) 2008 Steven Barth + */ + +#ifndef _IWCONFIG_H__ +#define _IWCONFIG_H__ +int iwc_startup(void); +void iwc_shutdown(void); +int iwc_get(lua_State *L); +int iwc_getall(lua_State *L); +int iwc_set_essid(lua_State *L); +int iwc_set_mode(lua_State *L); +int iwc_set_channel(lua_State *L); +int iwc_scan(lua_State *L); +#endif diff --git a/libs/luanet/src/main.c b/libs/luanet/src/main.c new file mode 100644 index 000000000..0a42276cb --- /dev/null +++ b/libs/luanet/src/main.c @@ -0,0 +1,95 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2008 John Crispin + * Copyright (C) 2008 Steven Barth + */ + +#include +#include + +#include +#include +#include + +#include "route.h" +#include "bridge.h" +#include "ifconfig.h" +#include "iwconfig.h" +#include "vconfig.h" +#include "df.h" +#include "base64.h" + +int psleep(lua_State *L) +{ + int s; + if(lua_gettop(L) != 1) + { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + return 0; + } + + s = (int)lua_tointeger (L, 1); + sleep(s); + return 0; +} + +static luaL_reg func[] = { + {"ifc_getall", ifc_getall}, + {"ifc_setip", ifc_setip}, + {"ifc_setnetmask", ifc_setnetmask}, + {"ifc_setbroadcast", ifc_setbroadcast}, + {"ifc_setmtu", ifc_setmtu}, + {"ifc_up", ifc_up}, + {"ifc_down", ifc_down}, + {"bridge_getall", bridge_getall}, + {"bridge_new", bridge_new}, + {"bridge_del", bridge_del}, + {"bridge_addif", bridge_addif}, + {"bridge_delif", bridge_delif}, + {"iwc_getall", iwc_getall}, + {"iwc_set_essid", iwc_set_essid}, + {"iwc_set_mode", iwc_set_mode}, + {"iwc_set_channel", iwc_set_channel}, + {"iwc_scan", iwc_scan}, + {"vlan_getall", vlan_getall}, + {"vlan_add", vlan_add}, + {"vlan_del", vlan_del}, + {"df", df}, + {"b64_encode", b64_encode}, + {"b64_decode", b64_decode}, + {"sleep", psleep}, + {NULL, NULL} +}; + +int luaopen_luanet(lua_State *L) +{ + ifc_startup(); + bridge_startup(); + iwc_startup(); + luaL_openlib(L, "luanet", func, 0); + lua_pushstring(L, "_VERSION"); + lua_pushstring(L, "1.0"); + lua_rawset(L, -3); + return 1; +} + +int luaclose_luanet(lua_State *L) +{ + ifc_shutdown(); + bridge_shutdown(); + iwc_shutdown(); + lua_pushstring(L, "Called"); + return 1; +} diff --git a/libs/luanet/src/route.c b/libs/luanet/src/route.c new file mode 100644 index 000000000..1690b74b7 --- /dev/null +++ b/libs/luanet/src/route.c @@ -0,0 +1,45 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2008 John Crispin + * Copyright (C) 2008 Steven Barth + */ + +#include +#include +#include + +#include "helper.h" + +extern int sock_ifconfig; + +int route_add(char *dev, int flag_gateway, int flag_host, char *dst, char *gateway, char *mask) +{ + struct rtentry r; + char ip[4]; + r.rt_flags = RTF_UP; + if(flag_gateway) + r.rt_flags |= RTF_GATEWAY; + if(flag_host) + r.rt_flags |= RTF_HOST; + r.rt_dst.sa_family = AF_INET; + r.rt_gateway.sa_family = AF_INET; + r.rt_genmask.sa_family = AF_INET; + char2ipv4(dst, ip); + ((struct sockaddr_in *) &r.rt_dst)->sin_addr.s_addr = (unsigned int)ip; + char2ipv4(gateway, ip); + ((struct sockaddr_in *) &r.rt_gateway)->sin_addr.s_addr = (unsigned int)ip; + char2ipv4(mask, ip); + ((struct sockaddr_in *) &r.rt_genmask)->sin_addr.s_addr = (unsigned int)ip; + return ioctl(sock_ifconfig, SIOCADDRT, (void *) &r); +} diff --git a/libs/luanet/src/route.h b/libs/luanet/src/route.h new file mode 100644 index 000000000..53f6e98b9 --- /dev/null +++ b/libs/luanet/src/route.h @@ -0,0 +1,21 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2008 John Crispin + * Copyright (C) 2008 Steven Barth + */ + +#ifndef _ROUTE_H__ +#define _ROUTE_H__ +int route_add(char *dev, int flag_gateway, int flag_host, char *dst, char *gateway, char *mask); +#endif diff --git a/libs/luanet/src/test.lua b/libs/luanet/src/test.lua new file mode 100755 index 000000000..713836b55 --- /dev/null +++ b/libs/luanet/src/test.lua @@ -0,0 +1,132 @@ +#!/usr/bin/lua + +print("luanet test") +local luanet = require("luanet") + +print("sleeping 4 secs") +luanet.sleep(4) + +print("---ifconfig---\n") +print("set ip wlan0 -> 192.168.1.2") +print(luanet.ifc_setip("wlan0", "192.168.1.2")) +print("set ip wlan0:1 -> 192.168.2.2") +print(luanet.ifc_setip("wlan0:1", "192.168.2.2")) +print("set mtu wlan0 -> 1400") +print(luanet.ifc_setmtu("wlan0", "1400")) +--print("set down wlan0 ->") +--print(luanet.ifc_down("wlan0")) +--print("set up wlan0 ->") +--print(luanet.ifc_up("wlan0")) +local devs = luanet.ifc_getall() +for i,v in pairs(devs) do + print("\ndev -> "..i) + print(devs[i].ip) + print(devs[i].netmask) + print(devs[i].broadaddr) + print(devs[i].mac) + print(devs[i].mtu) + print(devs[i].up) +end + + +print("\n\n---bridge---\n") +print("add bridge br-test ->") +print(luanet.bridge_new("br-test")) + +print("add wlan0 to br-test ->") +print(luanet.bridge_addif("br-test", "wlan0")) + +print("listing bridges") +local brs = luanet.bridge_getall() +if brs then + for i,v in pairs(brs) do + print(i) + for j,k in pairs(v) do + print(j.."->"..k) + end + end +end +print("del wlan0 from br-test ->") +print(luanet.bridge_delif("br-test", "wlan0")) + +print("del bridge br-test ->") +print(luanet.bridge_del("br-test")) + + +print("\n\n---wifi---\n") +print("set wlan0 essid test123") +print(luanet.iwc_set_essid("wlan0", "test123")) +print("set wifi channel to 3") +print(luanet.iwc_set_channel("wlan0", 3)) +print("set wifi to managed") +print(luanet.iwc_set_mode("wlan0", "managed")) +print("\nget all wifi devices") +local wifidevs = luanet.iwc_getall() +if wifidevs then + for i,v in pairs(wifidevs) do + print(i) + for j,k in pairs(v) do + print(" "..j.."->"..k) + end + end +end +local scan = luanet.iwc_scan("wlan0") +print("\nscanning wifi on wlan0") +if scan then + for i,v in pairs(scan) do + print("\n"..i) + print(" mac -> "..v.addr) + print(" frequency -> "..v.frequency) + print(" channel -> "..v.channel) + print(" mode -> "..v.mode) + print(" essid -> "..v.essid) + print(" key -> "..v.key) + print(" wpa1gcipher -> "..(v.wpa1gcipher or "")) + print(" wpa1pcipher -> "..(v.wpa1pcipher or "")) + print(" wpa1auth -> "..(v.wpa1auth or "")) + print(" wpa2gcipher -> "..(v.wpa2gcipher or "")) + print(" wpa2pcipher -> "..(v.wpa2pcipher or "")) + print(" wpa2auth -> "..(v.wpa2auth or "")) + print(" bitrates") + for j,k in ipairs(v.bitrates) do + --print(j.."->"..k) + end + end +end + + +print("\n\n---vlan---\n") +print("add wlan0 to vlan0") +print(luanet.vlan_add("wlan0", 0)); +print("add wlan0 to vlan1") +print(luanet.vlan_add("wlan0", 1)); +print("del wlan0 from all vlans") +print(luanet.vlan_del("wlan0.0")); +print("add wlan0 to vlan6") +print(luanet.vlan_add("wlan0", 6)); +local vlans = luanet.vlan_getall() +if vlans then + for i,v in ipairs(vlans) do + print(i.."->"..v) + end +end + + +print("\n\n---df---\n") + +print("getting disc usage") +local discs = luanet.df() +if discs then + for i,v in ipairs(discs) do + print(i.."->") + for k,l in pairs(v) do + print(" "..k.."->"..l) + end + end +end + + +print("\n\n---b64---\n") +print("test2 -->"..(luanet.b64_encode("test2") or "fail")) +print("dGVzdDI= -->"..(luanet.b64_decode("dGVzdDI=") or "fail")) + diff --git a/libs/luanet/src/vconfig.c b/libs/luanet/src/vconfig.c new file mode 100644 index 000000000..7adccc9a9 --- /dev/null +++ b/libs/luanet/src/vconfig.c @@ -0,0 +1,93 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2008 John Crispin + * Copyright (C) 2008 Steven Barth + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +extern int sock_ifconfig; + + +static inline int _vlan_add(lua_State *L, int i) +{ + struct vlan_ioctl_args ifr; + int a = (i == ADD_VLAN_CMD)?(2):(1); + char *ifname; + if(lua_gettop(L) != a) + { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + return 0; + } + ifname = (char *)lua_tostring (L, 1); + ifr.cmd = i; + if(i == ADD_VLAN_CMD) + ifr.u.VID = (int)lua_tointeger (L, 2); + strncpy(ifr.device1, ifname, IFNAMSIZ); + if(!ioctl(sock_ifconfig, SIOCSIFVLAN, &ifr)) + lua_pushboolean(L, 1); + else + lua_pushboolean(L, 0); + return 1; +} + +int vlan_add(lua_State *L) +{ + return _vlan_add(L, ADD_VLAN_CMD); +} + +int vlan_del(lua_State *L) +{ + return _vlan_add(L, DEL_VLAN_CMD); +} + +int vlan_getall(lua_State *L) +{ + struct dirent **namelist; + int n = 0, i, count = 0; + count = scandir("/proc/net/vlan/", &namelist, NULL, alphasort); + if (count < 0) + return 0; + lua_newtable(L); + for (i = 0; i < count; i++) + { + if(strcmp(namelist[i]->d_name, "config") && (*namelist[i]->d_name != '.')) + { + n++; + lua_pushinteger(L, n); + lua_pushstring(L, namelist[i]->d_name); + lua_settable(L, -3); + } + free(namelist[i]); + } + free(namelist); + return 1; +} diff --git a/libs/luanet/src/vconfig.h b/libs/luanet/src/vconfig.h new file mode 100644 index 000000000..25bb6161d --- /dev/null +++ b/libs/luanet/src/vconfig.h @@ -0,0 +1,27 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2008 John Crispin + * Copyright (C) 2008 Steven Barth + */ + +#ifndef _VCONFIG_H__ +#define _VCONFIG_H__ + +int vlan_add(lua_State *L); +int vlan_del(lua_State *L); +int vlan_getall(lua_State *L); + +#endif -- 2.11.0