--- /dev/null
+#
+# Copyright (C) 20013-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=lua-bencode
+PKG_VERSION:=2.1.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_URL:=https://bitbucket.org/wilhelmy/lua-bencode
+PKG_SOURCE_PROTO:=hg
+PKG_SOURCE_VERSION:=500243383cb6acbddd3cf12aee6e4667aab53324
+PKG_LICENSE:=MIT
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/lua-bencode
+ SUBMENU:=Lua
+ SECTION:=lang
+ CATEGORY:=Languages
+ TITLE:=lua-bencode
+ URL:=https://bitbucket.org/wilhelmy/lua-bencode
+ MAINTAINER:=Lars Gierth <larsg@systemli.org>
+ DEPENDS:=+lua
+endef
+
+define Package/lua-bencode/description
+ This is a module for the lua programming language for decoding and encoding
+ bencoded data which can be used to read and write torrent files for bittorrent.
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+endef
+
+
+define Package/lua-bencode/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/bencode.lua $(1)/usr/lib/lua
+endef
+
+$(eval $(call BuildPackage,lua-bencode))
--- /dev/null
+#
+# Copyright (C) 20013-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=lua-sha2
+PKG_VERSION:=0.2.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_URL:=https://code.google.com/p/sha2/
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_VERSION:=02bd4bfdc806
+PKG_LICENSE:=MIT
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/lua-sha2
+ SUBMENU:=Lua
+ SECTION:=lang
+ CATEGORY:=Languages
+ TITLE:=Lua binding for Aaron Gifford's SHA-2 implementation
+ URL:=https://code.google.com/p/sha2/
+ MAINTAINER:=Lars Gierth <larsg@systemli.org>
+ DEPENDS:=+lua
+endef
+
+define Package/lua-sha2/description
+ Lua Binding for the SHA-2 (SHA-256/384/512) BSD-licensed C implementation by Aaron Gifford.
+ Also contains a HMAC implementation in Lua.
+endef
+
+TARGET_CFLAGS += -fPIC -DSHA2_USE_INTTYPES_H -DBYTE_ORDER -DLITTLE_ENDIAN
+TARGET_LDFLAGS += -fPIC -DSHA2_USE_INTTYPES_H -DBYTE_ORDER -DLITTLE_ENDIAN
+
+define Build/Configure
+endef
+
+define Package/lua-sha2/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua/hmac
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/sha2.so $(1)/usr/lib/lua
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/hmac.lua $(1)/usr/lib/lua
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/hmac/sha2.lua $(1)/usr/lib/lua/hmac
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/hmac/md5.lua $(1)/usr/lib/lua/hmac
+endef
+
+$(eval $(call BuildPackage,lua-sha2))
--- /dev/null
+From: Lars Gierth <larsg@systemli.org>
+Date: Tue, 2 Sep 2014 00:05:39 +0200
+
+ Add rump Makefile
+
+new file mode 100644
+index 0000000..f081d38
+--- /dev/null
++++ b/Makefile
+@@ -0,0 +1,4 @@
++all: sha2.o sha2lib.o
++ $(CC) -shared -o sha2.so sha2.o sha2lib.o
++
++.PHONY: all
--- /dev/null
+#
+# Copyright (C) 2009-2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=luasocket
+PKG_SOURCE_VERSION:=6d5e40c324c84d9c1453ae88e0ad5bdd0a631448
+PKG_VERSION:=3.0-rc1-20130909
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://github.com/diegonehab/luasocket.git
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/luasocket
+ SUBMENU:=Lua
+ SECTION:=lang
+ CATEGORY:=Languages
+ TITLE:=LuaSocket
+ URL:=http://luasocket.luaforge.net/
+ MAINTAINER:=W. Michael Petullo <mike@flyn.org>
+ DEPENDS:=+lua
+endef
+
+define Package/luasocket/description
+ LuaSocket is the most comprehensive networking support
+ library for the Lua language. It provides easy access to
+ TCP, UDP, DNS, SMTP, FTP, HTTP, MIME and much more.
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR)/ \
+ LIBDIR="$(TARGET_LDFLAGS)" \
+ CC="$(TARGET_CC) $(TARGET_CFLAGS) $(TARGET_CPPFLAGS) -std=gnu99" \
+ LD="$(TARGET_CROSS)ld -shared" \
+ all
+endef
+
+
+define Package/luasocket/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/src/{ltn12,mime,socket}.lua $(1)/usr/lib/lua
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/mime.so.1.0.3 $(1)/usr/lib/lua
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/socket.so.3.0-rc1 $(1)/usr/lib/lua
+ $(INSTALL_DIR) $(1)/usr/lib/lua/mime
+ ln -sf ../mime.so.1.0.3 $(1)/usr/lib/lua/mime/core.so
+ $(INSTALL_DIR) $(1)/usr/lib/lua/socket
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/src/{ftp,http,smtp,tp,url,headers}.lua $(1)/usr/lib/lua/socket
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/unix.so $(1)/usr/lib/lua/socket
+ ln -sf ../socket.so.3.0-rc1 $(1)/usr/lib/lua/socket/core.so
+endef
+
+$(eval $(call BuildPackage,luasocket))
--- /dev/null
+From 96fdf07acf78ecfc9be76a8b0591f38fe6f1a875 Mon Sep 17 00:00:00 2001
+From: Steven Barth <steven@midlink.org>
+Date: Sat, 9 Nov 2013 12:01:42 +0100
+Subject: [PATCH] Add interface resolving
+
+---
+ src/if.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/if.h | 27 ++++++++++++++
+ src/luasocket.c | 2 +
+ src/makefile | 2 +
+ src/options.c | 9 +++++
+ 5 files changed, 153 insertions(+)
+ create mode 100644 src/if.c
+ create mode 100644 src/if.h
+
+diff --git a/src/if.c b/src/if.c
+new file mode 100644
+index 0000000..db231aa
+--- /dev/null
++++ b/src/if.c
+@@ -0,0 +1,113 @@
++/*
++ * $Id: if.c $
++ *
++ * Author: Markus Stenberg <fingon@iki.fi>
++ *
++ * Copyright (c) 2012 cisco Systems, Inc.
++ *
++ * Created: Tue Dec 4 14:50:34 2012 mstenber
++ * Last modified: Wed Dec 5 18:51:08 2012 mstenber
++ * Edit time: 24 min
++ *
++ */
++
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <net/if.h>
++
++#include "if.h"
++
++#include "lauxlib.h"
++
++static int if_global_indextoname(lua_State *L);
++static int if_global_nametoindex(lua_State *L);
++static int if_global_nameindex(lua_State *L);
++
++static luaL_Reg func[] = {
++ { "indextoname", if_global_indextoname},
++ { "nametoindex", if_global_nametoindex},
++ { "nameindex", if_global_nameindex},
++ { NULL, NULL}
++};
++
++int if_open(lua_State *L)
++{
++ lua_pushstring(L, "iface");
++ lua_newtable(L);
++ luaL_openlib(L, NULL, func, 0);
++ lua_settable(L, -3);
++ return 0;
++}
++
++int if_global_indextoname(lua_State *L)
++{
++ unsigned int ifnumber;
++ const char *name;
++ char buf[IF_NAMESIZE+1];
++
++ if (!lua_isnumber(L, 1))
++ {
++ lua_pushnil(L);
++ lua_pushstring(L, "indextoname expects only number argument");
++ return 2;
++ }
++ ifnumber = lua_tonumber(L, 1);
++ if (!(name = if_indextoname(ifnumber, buf)))
++ {
++ lua_pushnil(L);
++ lua_pushstring(L, "nonexistent interface");
++ return 2;
++ }
++ lua_pushstring(L, name);
++ return 1;
++}
++
++int if_global_nametoindex(lua_State *L)
++{
++ unsigned int ifnumber;
++ if (!lua_isstring(L, 1))
++ {
++ lua_pushnil(L);
++ lua_pushstring(L, "nametoindex expects only string argument");
++ return 2;
++ }
++ if (!(ifnumber = if_nametoindex(lua_tostring(L, 1))))
++ {
++ lua_pushnil(L);
++ lua_pushstring(L, "nonexistent interface");
++ return 2;
++ }
++ lua_pushnumber(L, ifnumber);
++ return 1;
++}
++
++int if_global_nameindex(lua_State *L)
++{
++ struct if_nameindex *ni, *oni;
++ int i = 1;
++ oni = ni = if_nameindex();
++ lua_newtable(L);
++ while (ni && ni->if_index && *(ni->if_name))
++ {
++ /* at result[i], we store.. */
++ lua_pushnumber(L, i);
++
++ /* new table with two items - index, name*/
++ lua_newtable(L);
++ lua_pushstring(L, "index");
++ lua_pushnumber(L, ni->if_index);
++ lua_settable(L, -3);
++
++ lua_pushstring(L, "name");
++ lua_pushstring(L, ni->if_name);
++ lua_settable(L, -3);
++
++ /* Then, actually store it */
++ lua_settable(L, -3);
++
++ i++;
++ ni++;
++ }
++ if_freenameindex(oni);
++ return 1;
++}
+diff --git a/src/if.h b/src/if.h
+new file mode 100644
+index 0000000..dc7faf8
+--- /dev/null
++++ b/src/if.h
+@@ -0,0 +1,27 @@
++/*
++ * $Id: if.h $
++ *
++ * Author: Markus Stenberg <fingon@iki.fi>
++ *
++ * Copyright (c) 2012 cisco Systems, Inc.
++ *
++ * Created: Tue Dec 4 14:37:24 2012 mstenber
++ * Last modified: Tue Dec 4 14:51:43 2012 mstenber
++ * Edit time: 7 min
++ *
++ */
++
++/* This module provides Lua wrapping for the advanced socket API
++ * defined in RFC3542, or mainly, the access to the system's interface
++ * list. It is necessary for use of recvmsg/sendmsg.
++ *
++ * TODO - Do something clever with Windows?
++ */
++#ifndef IF_H
++#define IF_H
++
++#include "lua.h"
++
++int if_open(lua_State *L);
++
++#endif /* IF_H */
+diff --git a/src/luasocket.c b/src/luasocket.c
+index e6ee747..85d41a6 100644
+--- a/src/luasocket.c
++++ b/src/luasocket.c
+@@ -31,6 +31,7 @@
+ #include "tcp.h"
+ #include "udp.h"
+ #include "select.h"
++#include "if.h"
+
+ /*-------------------------------------------------------------------------*\
+ * Internal function prototypes
+@@ -51,6 +52,7 @@ static const luaL_Reg mod[] = {
+ {"tcp", tcp_open},
+ {"udp", udp_open},
+ {"select", select_open},
++ {"iface", if_open},
+ {NULL, NULL}
+ };
+
+diff --git a/src/makefile b/src/makefile
+index 8d3521e..09d4882 100644
+--- a/src/makefile
++++ b/src/makefile
+@@ -262,6 +262,7 @@ SOCKET_OBJS= \
+ auxiliar.$(O) \
+ options.$(O) \
+ inet.$(O) \
++ if.$(O) \
+ $(SOCKET) \
+ except.$(O) \
+ select.$(O) \
+@@ -387,6 +388,7 @@ auxiliar.$(O): auxiliar.c auxiliar.h
+ buffer.$(O): buffer.c buffer.h io.h timeout.h
+ except.$(O): except.c except.h
+ inet.$(O): inet.c inet.h socket.h io.h timeout.h usocket.h
++if.$(O): if.c if.h
+ io.$(O): io.c io.h timeout.h
+ luasocket.$(O): luasocket.c luasocket.h auxiliar.h except.h \
+ timeout.h buffer.h io.h inet.h socket.h usocket.h tcp.h \
+diff --git a/src/options.c b/src/options.c
+index 8ac2a14..1c73e6f 100644
+--- a/src/options.c
++++ b/src/options.c
+@@ -3,6 +3,9 @@
+ * LuaSocket toolkit
+ \*=========================================================================*/
+ #include <string.h>
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <net/if.h>
+
+ #include "lauxlib.h"
+
+@@ -285,6 +288,12 @@ static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name)
+ if (!lua_isnil(L, -1)) {
+ if (lua_isnumber(L, -1)) {
+ val.ipv6mr_interface = (unsigned int) lua_tonumber(L, -1);
++ } else if (lua_isstring(L, -1)) {
++ if (!(val.ipv6mr_interface = if_nametoindex(lua_tostring(L, -1)))) {
++ lua_pushnil(L);
++ lua_pushstring(L, "nonexistent interface");
++ return 2;
++ }
+ } else
+ luaL_argerror(L, -1, "number 'interface' field expected");
+ }
+--
+1.8.4.rc3
+
--- /dev/null
+#
+# Copyright (C) 2014,2015 Hyperboria.net
+#
+# You may redistribute this program and/or modify it under the terms of
+# the GNU General Public License as published by the Free Software Foundation,
+# either version 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=luci-app-cjdns
+PKG_VERSION:=1.3
+PKG_RELEASE:=5
+
+PKG_LICENSE:=GPL-3.0
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/luci-app-cjdns
+ SECTION:=luci
+ CATEGORY:=LuCI
+ SUBMENU:=3. Applications
+ TITLE:=Encrypted near-zero-conf mesh routing protocol
+ URL:=https://github.com/hyperboria/cjdns
+ MAINTAINER:=Lars Gierth <larsg@systemli.org>
+ DEPENDS:=+cjdns +luci-base
+endef
+
+define Package/luci-app-cjdns/description
+ This package allows you to configure and inspect cjdns networking using LuCI.
+
+ Cjdns implements an encrypted IPv6 network using public-key cryptography
+ for address allocation and a distributed hash table for routing.
+ This provides near-zero-configuration networking, and prevents many
+ of the security and scalability issues that plague existing networks.
+endef
+
+define Build/Compile
+endef
+
+define Package/luci-app-cjdns/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua/luci
+ $(CP) ./luasrc/* $(1)/usr/lib/lua/luci
+endef
+
+$(eval $(call BuildPackage,luci-app-cjdns))
--- /dev/null
+module("luci.controller.cjdns", package.seeall)
+
+cjdns = require "cjdns/init"
+dkjson = require "dkjson"
+
+function index()
+ if not nixio.fs.access("/etc/config/cjdns") then
+ return
+ end
+
+ entry({"admin", "services", "cjdns"},
+ cbi("cjdns/overview"), _("cjdns")).dependent = true
+
+ entry({"admin", "services", "cjdns", "overview"},
+ cbi("cjdns/overview"), _("Overview"), 1).leaf = false
+
+ entry({"admin", "services", "cjdns", "peering"},
+ cbi("cjdns/peering"), _("Peers"), 2).leaf = false
+
+ entry({"admin", "services", "cjdns", "iptunnel"},
+ cbi("cjdns/iptunnel"), _("IP Tunnel"), 3).leaf = false
+
+ entry({"admin", "services", "cjdns", "settings"},
+ cbi("cjdns/settings"), _("Settings"), 4).leaf = false
+
+ entry({"admin", "services", "cjdns", "cjdrouteconf"},
+ cbi("cjdns/cjdrouteconf"), _("cjdroute.conf"), 5).leaf = false
+
+ entry({"admin", "services", "cjdns", "peers"}, call("act_peers")).leaf = true
+ entry({"admin", "services", "cjdns", "ping"}, call("act_ping")).leaf = true
+end
+
+function act_peers()
+ require("cjdns/uci")
+ admin = cjdns.uci.makeInterface()
+
+ local page = 0
+ local peers = {}
+
+ while page do
+ local response, err = admin:auth({
+ q = "InterfaceController_peerStats",
+ page = page
+ })
+
+ if err or response.error then
+ luci.http.status(502, "Bad Gateway")
+ luci.http.prepare_content("application/json")
+ luci.http.write_json({ err = err, response = response })
+ return
+ end
+
+ for i,peer in pairs(response.peers) do
+ peer.ipv6 = publictoip6(peer.publicKey)
+ if peer.user == nil then
+ peer.user = ''
+ uci.cursor():foreach("cjdns", "udp_peer", function(udp_peer)
+ if peer.publicKey == udp_peer.public_key then
+ peer.user = udp_peer.user
+ end
+ end)
+ end
+ peers[#peers + 1] = peer
+ end
+
+ if response.more then
+ page = page + 1
+ else
+ page = nil
+ end
+ end
+
+ luci.http.status(200, "OK")
+ luci.http.prepare_content("application/json")
+ luci.http.write_json(peers)
+end
+
+function act_ping()
+ require("cjdns/uci")
+ admin = cjdns.uci.makeInterface()
+
+ local response, err = admin:auth({
+ q = "SwitchPinger_ping",
+ path = luci.http.formvalue("label"),
+ timeout = tonumber(luci.http.formvalue("timeout"))
+ })
+
+ if err or response.error then
+ luci.http.status(502, "Bad Gateway")
+ luci.http.prepare_content("application/json")
+ luci.http.write_json({ err = err, response = response })
+ return
+ end
+
+ luci.http.status(200, "OK")
+ luci.http.prepare_content("application/json")
+ luci.http.write_json(response)
+end
+
+function publictoip6(publicKey)
+ local process = io.popen("/usr/bin/publictoip6 " .. publicKey, "r")
+ local ipv6 = process:read()
+ process:close()
+ return ipv6
+end
--- /dev/null
+m = Map("cjdns", translate("cjdns"),
+ translate("Implements an encrypted IPv6 network using public-key \
+ cryptography for address allocation and a distributed hash table for \
+ routing. This provides near-zero-configuration networking, and prevents \
+ many of the security and scalability issues that plague existing \
+ networks."))
+
+dkjson = require("dkjson")
+cjdns = require("cjdns")
+require("cjdns/uci")
+
+local f = SimpleForm("cjdrouteconf", translate("Edit cjdroute.conf"),
+ translate("JSON interface to what's /etc/cjdroute.conf on other systems. \
+ Will be parsed and written to UCI by <code>cjdrouteconf set</code>."))
+
+local o = f:field(Value, "_cjdrouteconf")
+o.template = "cbi/tvalue"
+o.rows = 25
+
+function o.cfgvalue(self, section)
+ return dkjson.encode(cjdns.uci.get(), { indent = true })
+end
+
+function o.write(self, section, value)
+ local obj, pos, err = dkjson.decode(value, 1, nil)
+
+ if obj then
+ cjdns.uci.set(obj)
+ end
+end
+
+return f
--- /dev/null
+uci = require "luci.model.uci"
+cursor = uci:cursor_state()
+
+m = Map("cjdns", translate("cjdns"),
+ translate("Implements an encrypted IPv6 network using public-key \
+ cryptography for address allocation and a distributed hash table for \
+ routing. This provides near-zero-configuration networking, and prevents \
+ many of the security and scalability issues that plague existing \
+ networks."))
+
+m.on_after_commit = function(self)
+ os.execute("/etc/init.d/cjdns restart")
+end
+
+-- Outgoing
+outgoing = m:section(TypedSection, "iptunnel_outgoing", translate("Outgoing IP Tunnel Connections"),
+ translate("Enter the public keys of the nodes that will provide Internet access."))
+outgoing.anonymous = true
+outgoing.addremove = true
+outgoing.template = "cbi/tblsection"
+
+outgoing:option(Value, "public_key", translate("Public Key")).size = 55
+
+-- Allowed
+allowed = m:section(TypedSection, "iptunnel_allowed", translate("Allowed IP Tunnel Connections"),
+ translate("Enter the public key of the node you will provide Internet access to, along with the \
+ IPv4 and/or IPv6 address you will assign them."))
+allowed.anonymous = true
+allowed.addremove = true
+
+public_key = allowed:option(Value, "public_key", translate("Public Key"))
+public_key.template = "cjdns/value"
+public_key.size = 55
+
+ipv4 = allowed:option(Value, "ipv4", translate("IPv4"))
+ipv4.template = "cjdns/value"
+ipv4.datatype = 'ipaddr'
+ipv4.size = 55
+
+ipv6 = allowed:option(Value, "ipv6", translate("IPv6"),
+ translate("IPv6 addresses should be entered <em>without</em> brackets here, e.g. <code>2001:123:ab::10</code>."))
+ipv6.template = "cjdns/value"
+ipv6.datatype = 'ip6addr'
+ipv6.size = 55
+
+return m
--- /dev/null
+m = Map("cjdns", translate("cjdns"),
+ translate("Implements an encrypted IPv6 network using public-key \
+ cryptography for address allocation and a distributed hash table for \
+ routing. This provides near-zero-configuration networking, and prevents \
+ many of the security and scalability issues that plague existing \
+ networks."))
+
+m:section(SimpleSection).template = "cjdns/status"
+
+return m
--- /dev/null
+uci = require "luci.model.uci"
+cursor = uci:cursor_state()
+
+cjdns = require("cjdns")
+require("cjdns/uci")
+
+m = Map("cjdns", translate("cjdns"),
+ translate("Implements an encrypted IPv6 network using public-key \
+ cryptography for address allocation and a distributed hash table for \
+ routing. This provides near-zero-configuration networking, and prevents \
+ many of the security and scalability issues that plague existing \
+ networks."))
+
+m.on_after_commit = function(self)
+ os.execute("/etc/init.d/cjdns restart")
+end
+
+-- Authorized Passwords
+passwords = m:section(TypedSection, "password", translate("Authorized Passwords"),
+ translate("Anyone offering one of the these passwords will be allowed to peer with you on the existing UDP and Ethernet interfaces."))
+passwords.anonymous = true
+passwords.addremove = true
+passwords.template = "cbi/tblsection"
+
+passwords:option(Value, "user", translate("User/Name"),
+ translate("Must be unique.")
+).default = "user-" .. cjdns.uci.random_string(6)
+passwords:option(Value, "contact", translate("Contact"), translate("Optional, for out-of-band communication."))
+passwords:option(Value, "password", translate("Password"),
+ translate("Hand out to your peer, in accordance with the peering best practices of the network.")
+).default = cjdns.uci.random_string(32)
+
+-- UDP Peers
+udp_peers = m:section(TypedSection, "udp_peer", translate("Outgoing UDP Peers"),
+ translate("For peering via public IP networks, the peer handed you their Public Key and IP address/port along with a password. IPv6 addresses should be entered with square brackets, like so: <code>[2001::1]</code>."))
+udp_peers.anonymous = true
+udp_peers.addremove = true
+udp_peers.template = "cbi/tblsection"
+udp_peers:option(Value, "user", translate("User/Name")).datatype = "string"
+
+udp_interface = udp_peers:option(Value, "interface", translate("UDP interface"))
+local index = 1
+for i,section in pairs(cursor:get_all("cjdns")) do
+ if section[".type"] == "udp_interface" then
+ udp_interface:value(index, section.address .. ":" .. section.port)
+ end
+end
+udp_interface.default = 1
+udp_peers:option(Value, "address", translate("IP address"))
+udp_peers:option(Value, "port", translate("Port")).datatype = "portrange"
+udp_peers:option(Value, "public_key", translate("Public key"))
+udp_peers:option(Value, "password", translate("Password"))
+
+-- Ethernet Peers
+eth_peers = m:section(TypedSection, "eth_peer", translate("Outgoing Ethernet Peers"),
+ translate("For peering via local Ethernet networks, the peer handed you their Public Key and MAC address along with a password."))
+eth_peers.anonymous = true
+eth_peers.addremove = true
+eth_peers.template = "cbi/tblsection"
+
+eth_interface = eth_peers:option(Value, "interface", translate("Ethernet interface"))
+local index = 1
+for i,section in pairs(cursor:get_all("cjdns")) do
+ if section[".type"] == "eth_interface" then
+ eth_interface:value(index, section.bind)
+ end
+end
+eth_interface.default = 1
+eth_peers:option(Value, "address", translate("MAC address")).datatype = "macaddr"
+eth_peers:option(Value, "public_key", translate("Public key"))
+eth_peers:option(Value, "password", translate("Password"))
+
+return m
--- /dev/null
+m = Map("cjdns", translate("cjdns"),
+ translate("Implements an encrypted IPv6 network using public-key \
+ cryptography for address allocation and a distributed hash table for \
+ routing. This provides near-zero-configuration networking, and prevents \
+ many of the security and scalability issues that plague existing \
+ networks."))
+
+m.on_after_commit = function(self)
+ os.execute("/etc/init.d/cjdns restart")
+end
+
+s = m:section(NamedSection, "cjdns", nil, translate("Settings"))
+s.addremove = false
+
+-- Identity
+s:tab("identity", translate("Identity"))
+node6 = s:taboption("identity", Value, "ipv6", translate("IPv6 address"),
+ translate("This node's IPv6 address within the cjdns network."))
+node6.datatype = "ip6addr"
+pbkey = s:taboption("identity", Value, "public_key", translate("Public key"),
+ translate("Used for packet encryption and authentication."))
+pbkey.datatype = "string"
+prkey = s:taboption("identity", Value, "private_key", translate("Private key"),
+ translate("Keep this private. When compromised, generate a new keypair and IPv6."))
+prkey.datatype = "string"
+
+-- Admin Interface
+s:tab("admin", translate("Admin API"), translate("The Admin API can be used by other applications or services to configure and inspect cjdns' routing and peering.<br/><br/>Documentation: <a href=\"https://github.com/cjdelisle/cjdns/tree/master/admin#cjdns-admin-api\">admin/README.md</a>"))
+aip = s:taboption("admin", Value, "admin_address", translate("IP Address"),
+ translate("IPv6 addresses should be entered like so: <code>[2001::1]</code>."))
+apt = s:taboption("admin", Value, "admin_port", translate("Port"))
+apt.datatype = "port"
+apw = s:taboption("admin", Value, "admin_password", translate("Password"))
+apw.datatype = "string"
+
+-- Security
+s:tab("security", translate("Security"), translate("Functionality related to hardening the cjdroute process."))
+s:taboption("security", Flag, "seccomp", translate("SecComp sandboxing"))
+
+-- UDP Interfaces
+udp_interfaces = m:section(TypedSection, "udp_interface", translate("UDP Interfaces"),
+ translate("These interfaces allow peering via public IP networks, such as the Internet, or many community-operated wireless networks. IPv6 addresses should be entered with square brackets, like so: <code>[2001::1]</code>."))
+udp_interfaces.anonymous = true
+udp_interfaces.addremove = true
+udp_interfaces.template = "cbi/tblsection"
+
+udp_address = udp_interfaces:option(Value, "address", translate("IP Address"))
+udp_address.placeholder = "0.0.0.0"
+udp_interfaces:option(Value, "port", translate("Port")).datatype = "portrange"
+
+-- Ethernet Interfaces
+eth_interfaces = m:section(TypedSection, "eth_interface", translate("Ethernet Interfaces"),
+ translate("These interfaces allow peering via local Ethernet networks, such as home or office networks, or phone tethering. If an interface name is set to \"all\" each available device will be used."))
+eth_interfaces.anonymous = true
+eth_interfaces.addremove = true
+eth_interfaces.template = "cbi/tblsection"
+
+eth_bind = eth_interfaces:option(Value, "bind", translate("Network Interface"))
+eth_bind.placeholder = "br-lan"
+eth_beacon = eth_interfaces:option(Value, "beacon", translate("Beacon Mode"))
+eth_beacon:value(0, translate("0 -- Disabled"))
+eth_beacon:value(1, translate("1 -- Accept beacons"))
+eth_beacon:value(2, translate("2 -- Accept and send beacons"))
+eth_beacon.default = 2
+eth_beacon.datatype = "integer(range(0,2))"
+
+return m
--- /dev/null
+<%+cjdns/status%>
--- /dev/null
+<script type="text/javascript">//<![CDATA[
+
+ var peersURI = '<%=luci.dispatcher.build_url("admin", "services", "cjdns", "peers")%>';
+ var updatePeers = function(x, peers) {
+ var table = document.getElementById('cjdns-peerings');
+ while (table.rows.length > 1) {
+ table.deleteRow(1);
+ }
+
+ if ((peers) && ((peers.err) || (typeof peers.length === 'undefined'))) {
+ var errpeer = (peers.err)
+ ? 'Socket Error: unable to connect to Admin API'
+ : 'No active peers';
+ var row = table.insertRow(-1);
+ row.className = 'cbi-section-table-row';
+ var cell = row.insertCell(-1);
+ cell.colSpan = 7;
+ cell.textContent = errpeer;
+ return;
+ };
+
+ peers.forEach(function(peer, i) {
+ if (peer.user == null) {
+ var user = '';
+ } else if (peer.user == 'Local Peers') {
+ var user = 'beacon';
+ } else {
+ var user = peer.user;
+ }
+
+ if (peer.isIncoming === 0) {
+ var interface = 'outgoing';
+ } else {
+ var interface = 'incoming';
+ }
+
+ var status = interface + ', ' + peer.state.toLowerCase();
+
+ if (peer.version === 0) {
+ var version = '-';
+ } else {
+ var version = 'v' + peer.version;
+ }
+
+ var rxtx = lbbytes(peer.bytesIn) + ' / ' + lbbytes(peer.bytesOut);
+
+ var row = table.insertRow(-1);
+ row.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
+ row.insertCell(-1).textContent = user;
+ row.insertCell(-1).textContent = peer.ipv6;
+ row.insertCell(-1).textContent = status;
+ row.insertCell(-1).textContent = version;
+ row.insertCell(-1).textContent = rxtx;
+ var latencyCell = row.insertCell(-1);
+ latencyCell.textContent = 'waiting';
+
+ var pingURI = '<%=luci.dispatcher.build_url("admin", "services", "cjdns", "ping")%>';
+ var timeout = 2000;
+ XHR.get(pingURI, { label: peer.switchLabel, timeout: timeout }, function(x, pong) {
+ var pongrsp = ((pong.err == "ai:recv > timeout") || (pong == "undefined") || (pong.ms >= timeout))
+ ? '> ' + timeout + ' ms'
+ : pong.ms + ' ms';
+ latencyCell.textContent = pongrsp;
+ })
+ });
+
+ };
+
+ XHR.get(peersURI, null, updatePeers);
+ XHR.poll(5, peersURI, null, updatePeers);
+
+//]]></script>
+
+<script type="text/javascript">
+<%# Author: [GitHub/75lb] -%>
+//<![CDATA[
+function lbbytes (bytes){
+
+ var kilobyte = 1024,
+ megabyte = kilobyte * 1024,
+ gigabyte = megabyte * 1024,
+ terabyte = gigabyte * 1024;
+
+ if ((bytes >= 0) && (bytes < kilobyte)) {
+ return bytes + " B";
+ } else if ((bytes >= kilobyte) && (bytes < megabyte)) {
+ return (bytes / kilobyte).toFixed(2) + " KB";
+ } else if ((bytes >= megabyte) && (bytes < gigabyte)) {
+ return (bytes / megabyte).toFixed(2) + " MB";
+ } else if ((bytes >= gigabyte) && (bytes < terabyte)) {
+ return (bytes / gigabyte).toFixed(2) + " GB";
+ } else if (bytes >= terabyte) {
+ return (bytes / terabyte).toFixed(2) + " TB";
+ } else {
+ return bytes + " B";
+ }
+};
+//]]>
+</script>
+
+<fieldset class="cbi-section">
+ <legend>Active cjdns peers</legend>
+ <table class="cbi-section-table" id="cjdns-peerings">
+ <tr class="cbi-section-table-titles">
+ <th class="cbi-section-table-cell">User/Name</th>
+ <th class="cbi-section-table-cell">IPv6</th>
+ <th class="cbi-section-table-cell">Status</th>
+ <th class="cbi-section-table-cell">Version</th>
+ <th class="cbi-section-table-cell">Rx / Tx</th>
+ <th class="cbi-section-table-cell">Latency</th>
+ </tr>
+ <tr class="cbi-section-table-row">
+ <td colspan="7">Querying Admin API</td>
+ </tr>
+ </table>
+</fieldset>
--- /dev/null
+<%+cbi/valueheader%>
+ <input type="<%=self.password and 'password" class="cbi-input-password' or 'text" class="cbi-input-text' %>" onchange="cbi_d_update(this.id)"<%=
+ attr("name", cbid) .. attr("id", cbid) .. attr("value", self:cfgvalue(section) or self.default) ..
+ ifattr(self.size, "size") .. ifattr(self.placeholder, "placeholder")
+ %> style="width: auto" />
+ <% if self.password then %><img src="<%=resource%>/cbi/reload.gif" style="vertical-align:middle" title="<%:Reveal/hide password%>" onclick="var e = document.getElementById('<%=cbid%>'); e.type = (e.type=='password') ? 'text' : 'password';" /><% end %>
+ <% if #self.keylist > 0 or self.datatype then -%>
+ <script type="text/javascript">//<![CDATA[
+ <% if #self.keylist > 0 then -%>
+ cbi_combobox_init('<%=cbid%>', {
+ <%-
+ for i, k in ipairs(self.keylist) do
+ -%>
+ <%-=string.format("%q", k) .. ":" .. string.format("%q", self.vallist[i])-%>
+ <%-if i<#self.keylist then-%>,<%-end-%>
+ <%-
+ end
+ -%>
+ }, '<%- if not self.rmempty and not self.optional then -%>
+ <%-: -- Please choose -- -%>
+ <%- elseif self.placeholder then -%>
+ <%-= pcdata(self.placeholder) -%>
+ <%- end -%>', '
+ <%- if self.combobox_manual then -%>
+ <%-=self.combobox_manual-%>
+ <%- else -%>
+ <%-: -- custom -- -%>
+ <%- end -%>');
+ <%- end %>
+ <% if self.datatype then -%>
+ cbi_validate_field('<%=cbid%>', <%=tostring((self.optional or self.rmempty) == true)%>, '<%=self.datatype:gsub("'", "\\'")%>');
+ <%- end %>
+ //]]></script>
+ <% end -%>
+<%+cbi/valuefooter%>
module "luci.version"
-if pcall(dofile, "/etc/openwrt_release") and _G.DISTRIB_DESCRIPTION then
+if pcall(dofile, "/etc/librecmc_release") and _G.DISTRIB_DESCRIPTION then
distname = ""
distversion = _G.DISTRIB_DESCRIPTION
else