Merge pull request #89 from SeattleMeshnet/master
cjdns: import package from github.com:SeattleMeshnet/meshbox
This commit is contained in:
commit
94ee37fe6c
10 changed files with 806 additions and 0 deletions
100
cjdns/Makefile
Normal file
100
cjdns/Makefile
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
PKG_NAME:=cjdns
|
||||||
|
PKG_VERSION:=0.16
|
||||||
|
PKG_RELEASE:=9
|
||||||
|
|
||||||
|
PKG_SOURCE_URL:=https://github.com/cjdelisle/cjdns.git
|
||||||
|
PKG_SOURCE_PROTO:=git
|
||||||
|
PKG_SOURCE_VERSION:=2138a1f6a94fc009958cde7b002c077a1eee929a
|
||||||
|
PKG_LICENSE:=GPL-3.0
|
||||||
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_VERSION).tar.bz2
|
||||||
|
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_SOURCE_VERSION)
|
||||||
|
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_SOURCE_VERSION)
|
||||||
|
|
||||||
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
|
||||||
|
|
||||||
|
define Package/cjdns
|
||||||
|
SECTION:=net
|
||||||
|
CATEGORY:=Network
|
||||||
|
SUBMENU:=Routing and Redirection
|
||||||
|
TITLE:=Encrypted near-zero-conf mesh routing protocol
|
||||||
|
URL:=https://github.com/hyperboria/cjdns
|
||||||
|
MAINTAINER:=Lars Gierth <larsg@systemli.org>
|
||||||
|
DEPENDS:=+kmod-tun +kmod-ipv6 +libnl-tiny +libpthread +librt \
|
||||||
|
+libuci-lua +lua-bencode +dkjson +luasocket +lua-sha2
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/cjdns/description
|
||||||
|
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/Configure
|
||||||
|
endef
|
||||||
|
|
||||||
|
ifneq ($(CONFIG_KERNEL_SECCOMP_FILTER),y)
|
||||||
|
PKG_DO_VARS:=Seccomp_NO=1
|
||||||
|
endif
|
||||||
|
|
||||||
|
define Build/Compile
|
||||||
|
CROSS="true" \
|
||||||
|
CC="$(TARGET_CC)" \
|
||||||
|
CFLAGS="$(TARGET_CFLAGS)" \
|
||||||
|
LDFLAGS="$(TARGET_LDFLAGS)" \
|
||||||
|
SYSTEM="linux" \
|
||||||
|
TARGET_ARCH="$(CONFIG_ARCH)" \
|
||||||
|
UCLIBC=1 \
|
||||||
|
SSP_SUPPORT="$(CONFIG_SSP_SUPPORT)" \
|
||||||
|
$(PKG_DO_VARS) \
|
||||||
|
$(PKG_BUILD_DIR)/do
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/cjdns/install
|
||||||
|
$(INSTALL_DIR) \
|
||||||
|
$(1)/usr/sbin \
|
||||||
|
$(1)/usr/bin \
|
||||||
|
$(1)/etc/config \
|
||||||
|
$(1)/etc/init.d \
|
||||||
|
$(1)/etc/uci-defaults \
|
||||||
|
$(1)/usr/lib/lua/cjdns
|
||||||
|
|
||||||
|
$(INSTALL_BIN) \
|
||||||
|
./files/cjdrouteconf \
|
||||||
|
$(1)/usr/bin
|
||||||
|
|
||||||
|
$(INSTALL_BIN) \
|
||||||
|
$(PKG_BUILD_DIR)/cjdroute \
|
||||||
|
$(1)/usr/sbin
|
||||||
|
|
||||||
|
$(INSTALL_BIN) \
|
||||||
|
$(PKG_BUILD_DIR)/publictoip6 \
|
||||||
|
$(1)/usr/bin
|
||||||
|
|
||||||
|
$(INSTALL_BIN) \
|
||||||
|
./files/cjdns.init \
|
||||||
|
$(1)/etc/init.d/cjdns
|
||||||
|
|
||||||
|
$(INSTALL_BIN) \
|
||||||
|
./files/cjdns.defaults \
|
||||||
|
$(1)/etc/uci-defaults/cjdns
|
||||||
|
|
||||||
|
$(CP) \
|
||||||
|
./lua/cjdns/* \
|
||||||
|
$(1)/usr/lib/lua/cjdns
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/cjdns/postinst
|
||||||
|
#!/bin/sh
|
||||||
|
if [ -z $${IPKG_INSTROOT} ] ; then
|
||||||
|
( . /etc/uci-defaults/cjdns ) && rm -f /etc/uci-defaults/cjdns
|
||||||
|
# TODO: we should have an 'Enable' button instead
|
||||||
|
/etc/init.d/cjdns enabled || /etc/init.d/cjdns enable
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call BuildPackage,cjdns))
|
125
cjdns/files/cjdns.defaults
Normal file
125
cjdns/files/cjdns.defaults
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# if there is an existing config, our work is already done
|
||||||
|
uci get cjdns.cjdns.ipv6 >/dev/null 2>&1
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
|
||||||
|
# register commit handler
|
||||||
|
uci -q batch <<-EOF >/dev/null
|
||||||
|
delete ucitrack.@cjdns[-1]
|
||||||
|
add ucitrack cjdns
|
||||||
|
set ucitrack.@cjdns[-1].init=cjdns
|
||||||
|
commit ucitrack
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# generate configuration
|
||||||
|
touch /etc/config/cjdns
|
||||||
|
cjdroute --genconf | cjdroute --cleanconf | cjdrouteconf set
|
||||||
|
|
||||||
|
# make sure config is present (might fail for any reason)
|
||||||
|
uci get cjdns.cjdns.ipv6 >/dev/null 2>&1
|
||||||
|
if [ $? -ne 0]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# enable auto-peering on ethernet
|
||||||
|
uci show network.lan | grep type=bridge >/dev/null 2>&1
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
# most routers will set up an ethernet bridge for the lan
|
||||||
|
ifname="br-lan"
|
||||||
|
else
|
||||||
|
# docker containers don't have permission to create bridges by default,
|
||||||
|
# so we bind to the underlying interface instead (likely eth0)
|
||||||
|
ifname=`uci get network.lan.ifname`
|
||||||
|
fi
|
||||||
|
uci -q batch <<-EOF >/dev/null
|
||||||
|
add cjdns eth_interface
|
||||||
|
set cjdns.@eth_interface[-1].beacon=2
|
||||||
|
set cjdns.@eth_interface[-1].bind=$ifname
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# set the tun interface name
|
||||||
|
uci set cjdns.cjdns.tun_device=tuncjdns
|
||||||
|
|
||||||
|
# create the network interface
|
||||||
|
uci -q batch <<-EOF >/dev/null
|
||||||
|
set network.cjdns=interface
|
||||||
|
set network.cjdns.ifname=tuncjdns
|
||||||
|
set network.cjdns.proto=none
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# firewall rules by @dangowrt -- thanks <3
|
||||||
|
|
||||||
|
# create the firewall zone
|
||||||
|
uci -q batch <<-EOF >/dev/null
|
||||||
|
add firewall zone
|
||||||
|
set firewall.@zone[-1].name=cjdns
|
||||||
|
add_list firewall.@zone[-1].network=cjdns
|
||||||
|
set firewall.@zone[-1].input=REJECT
|
||||||
|
set firewall.@zone[-1].output=ACCEPT
|
||||||
|
set firewall.@zone[-1].forward=REJECT
|
||||||
|
set firewall.@zone[-1].conntrack=1
|
||||||
|
set firewall.@zone[-1].family=ipv6
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# allow ICMP from cjdns zone, e.g. ping6
|
||||||
|
uci -q batch <<-EOF >/dev/null
|
||||||
|
add firewall rule
|
||||||
|
set firewall.@rule[-1].name='Allow-ICMPv6-cjdns'
|
||||||
|
set firewall.@rule[-1].src=cjdns
|
||||||
|
set firewall.@rule[-1].proto=icmp
|
||||||
|
add_list firewall.@rule[-1].icmp_type=echo-request
|
||||||
|
add_list firewall.@rule[-1].icmp_type=echo-reply
|
||||||
|
add_list firewall.@rule[-1].icmp_type=destination-unreachable
|
||||||
|
add_list firewall.@rule[-1].icmp_type=packet-too-big
|
||||||
|
add_list firewall.@rule[-1].icmp_type=time-exceeded
|
||||||
|
add_list firewall.@rule[-1].icmp_type=bad-header
|
||||||
|
add_list firewall.@rule[-1].icmp_type=unknown-header-type
|
||||||
|
set firewall.@rule[-1].limit='1000/sec'
|
||||||
|
set firewall.@rule[-1].family=ipv6
|
||||||
|
set firewall.@rule[-1].target=ACCEPT
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# allow SSH from cjdns zone, needs to be explicitly enabled
|
||||||
|
uci -q batch <<-EOF >/dev/null
|
||||||
|
add firewall rule
|
||||||
|
set firewall.@rule[-1].enabled=0
|
||||||
|
set firewall.@rule[-1].name='Allow-SSH-cjdns'
|
||||||
|
set firewall.@rule[-1].src=cjdns
|
||||||
|
set firewall.@rule[-1].proto=tcp
|
||||||
|
set firewall.@rule[-1].dest_port=22
|
||||||
|
set firewall.@rule[-1].target=ACCEPT
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# allow LuCI access from cjdns zone, needs to be explicitly enabled
|
||||||
|
uci -q batch <<-EOF >/dev/null
|
||||||
|
add firewall rule
|
||||||
|
set firewall.@rule[-1].enabled=0
|
||||||
|
set firewall.@rule[-1].name='Allow-HTTP-cjdns'
|
||||||
|
set firewall.@rule[-1].src=cjdns
|
||||||
|
set firewall.@rule[-1].proto=tcp
|
||||||
|
set firewall.@rule[-1].dest_port=80
|
||||||
|
set firewall.@rule[-1].target=ACCEPT
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# allow UDP peering from wan zone, if it exists
|
||||||
|
uci show network.wan >/dev/null 2>&1
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
peeringPort=`uci get cjdns.@udp_interface[0].port`
|
||||||
|
uci -q batch <<-EOF >/dev/null
|
||||||
|
add firewall rule
|
||||||
|
set firewall.@rule[-1].name='Allow-cjdns-wan'
|
||||||
|
set firewall.@rule[-1].src=wan
|
||||||
|
set firewall.@rule[-1].proto=udp
|
||||||
|
set firewall.@rule[-1].dest_port=$peeringPort
|
||||||
|
set firewall.@rule[-1].target=ACCEPT
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
uci commit cjdns
|
||||||
|
uci commit firewall
|
||||||
|
uci commit network
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
32
cjdns/files/cjdns.init
Executable file
32
cjdns/files/cjdns.init
Executable file
|
@ -0,0 +1,32 @@
|
||||||
|
#!/bin/sh /etc/rc.common
|
||||||
|
|
||||||
|
START=90
|
||||||
|
STOP=85
|
||||||
|
|
||||||
|
USE_PROCD=1
|
||||||
|
|
||||||
|
start_service()
|
||||||
|
{
|
||||||
|
[ -f /etc/uci-defaults/cjdns ] && ( . /etc/uci-defaults/cjdns )
|
||||||
|
|
||||||
|
procd_open_instance
|
||||||
|
procd_set_param respawn
|
||||||
|
procd_set_param command /bin/ash -c "cjdrouteconf get | tee /tmp/etc/cjdroute.conf | cjdroute --nobg | logger -t cjdns"
|
||||||
|
procd_close_instance
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_service()
|
||||||
|
{
|
||||||
|
killall cjdroute
|
||||||
|
}
|
||||||
|
|
||||||
|
reload_service()
|
||||||
|
{
|
||||||
|
# cat /tmp/etc/cjdroute.conf | cjdrouteconf reload
|
||||||
|
restart
|
||||||
|
}
|
||||||
|
|
||||||
|
service_triggers()
|
||||||
|
{
|
||||||
|
procd_add_reload_trigger cjdns
|
||||||
|
}
|
30
cjdns/files/cjdrouteconf
Executable file
30
cjdns/files/cjdrouteconf
Executable file
|
@ -0,0 +1,30 @@
|
||||||
|
#!/usr/bin/env lua
|
||||||
|
|
||||||
|
dkjson = require("dkjson")
|
||||||
|
cjdns = require("cjdns")
|
||||||
|
require("cjdns/uci")
|
||||||
|
|
||||||
|
function help()
|
||||||
|
print("JSON interface to /etc/config/cjdns\n\nExamples: \
|
||||||
|
cjdrouteconf get > /tmp/etc/cjdroute.conf \
|
||||||
|
cat /tmp/etc/cjdroute.conf | cjdrouteconf set \
|
||||||
|
uci changes \
|
||||||
|
cjdrouteconf get | cjdroute")
|
||||||
|
end
|
||||||
|
|
||||||
|
if arg[1] == "get" then
|
||||||
|
local json = dkjson.encode(cjdns.uci.get(), { indent = true })
|
||||||
|
print(json)
|
||||||
|
elseif arg[1] == "set" then
|
||||||
|
local json = io.stdin:read("*a")
|
||||||
|
local obj, pos, err = dkjson.decode(json, 1, nil)
|
||||||
|
|
||||||
|
if obj then
|
||||||
|
cjdns.uci.set(obj)
|
||||||
|
else
|
||||||
|
print("dkjson: " .. err .. " (try cjdroute --cleanconf)")
|
||||||
|
os.exit(1)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
help()
|
||||||
|
end
|
105
cjdns/lua/cjdns/admin.lua
Normal file
105
cjdns/lua/cjdns/admin.lua
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
-- Cjdns admin module for Lua
|
||||||
|
-- Written by Philip Horger
|
||||||
|
|
||||||
|
common = require 'cjdns/common'
|
||||||
|
|
||||||
|
AdminInterface = {}
|
||||||
|
AdminInterface.__index = AdminInterface
|
||||||
|
common.AdminInterface = AdminInterface
|
||||||
|
|
||||||
|
function AdminInterface.new(properties)
|
||||||
|
properties = properties or {}
|
||||||
|
|
||||||
|
properties.host = properties.host or "127.0.0.1"
|
||||||
|
properties.port = properties.port or 11234
|
||||||
|
properties.password = properties.password or nil
|
||||||
|
properties.config = properties.config or common.ConfigFile.new("/etc/cjdroute.conf", false)
|
||||||
|
properties.timeout = properties.timeout or 2
|
||||||
|
|
||||||
|
properties.udp = common.UDPInterface.new(properties)
|
||||||
|
|
||||||
|
return setmetatable(properties, AdminInterface)
|
||||||
|
end
|
||||||
|
|
||||||
|
function AdminInterface:send(object)
|
||||||
|
local bencoded, err = bencode.encode(object)
|
||||||
|
if err then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
|
||||||
|
local sock_obj = assert(socket.udp())
|
||||||
|
sock_obj:settimeout(self.timeout)
|
||||||
|
|
||||||
|
local _, err = sock_obj:sendto(bencoded, self.host, self.port)
|
||||||
|
if err then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
|
||||||
|
return sock_obj
|
||||||
|
end
|
||||||
|
|
||||||
|
function AdminInterface:recv(sock_obj)
|
||||||
|
local retrieved, err = sock_obj:receive()
|
||||||
|
if not retrieved then
|
||||||
|
return nil, "ai:recv > " .. err
|
||||||
|
end
|
||||||
|
local bencoded, err = bencode.decode(retrieved)
|
||||||
|
if bencoded then
|
||||||
|
return bencoded
|
||||||
|
else
|
||||||
|
return nil, "ai:recv > " .. err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function AdminInterface:call(request)
|
||||||
|
local sock_obj, err = self:send(request)
|
||||||
|
if err then
|
||||||
|
return nil, "ai:call > " .. err
|
||||||
|
end
|
||||||
|
|
||||||
|
return self:recv(sock_obj)
|
||||||
|
end
|
||||||
|
|
||||||
|
function AdminInterface:getCookie()
|
||||||
|
local cookie_response, err = self:call({ q = "cookie" })
|
||||||
|
if not cookie_response then
|
||||||
|
return nil, "ai:getCookie > " .. err
|
||||||
|
end
|
||||||
|
return cookie_response.cookie
|
||||||
|
end
|
||||||
|
|
||||||
|
function AdminInterface:auth(request)
|
||||||
|
local funcname = request.q
|
||||||
|
local args = {}
|
||||||
|
for k, v in pairs(request) do
|
||||||
|
args[k] = v
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Step 1: Get cookie
|
||||||
|
local cookie, err = self:getCookie()
|
||||||
|
if err then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Step 2: Calculate hash1 (password + cookie)
|
||||||
|
local plaintext1 = self.password .. cookie
|
||||||
|
local hash1 = sha2.sha256hex(plaintext1)
|
||||||
|
|
||||||
|
-- Step 3: Calculate hash2 (intermediate stage request)
|
||||||
|
local request = {
|
||||||
|
q = "auth",
|
||||||
|
aq = funcname,
|
||||||
|
args = args,
|
||||||
|
hash = hash1,
|
||||||
|
cookie = cookie
|
||||||
|
}
|
||||||
|
local plaintext2, err = bencode.encode(request)
|
||||||
|
if err then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
local hash2 = sha2.sha256hex(plaintext2)
|
||||||
|
|
||||||
|
-- Step 4: Update hash in request, then ship it out
|
||||||
|
request.hash = hash2
|
||||||
|
return self:call(request)
|
||||||
|
end
|
7
cjdns/lua/cjdns/common.lua
Normal file
7
cjdns/lua/cjdns/common.lua
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
-- Cjdns admin module for Lua
|
||||||
|
-- Written by Philip Horger
|
||||||
|
|
||||||
|
-- This table is preserved over multiple imports, and collects
|
||||||
|
-- submodules import-by-import via init.lua.
|
||||||
|
|
||||||
|
return {}
|
12
cjdns/lua/cjdns/init.lua
Normal file
12
cjdns/lua/cjdns/init.lua
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
-- Cjdns admin module for Lua
|
||||||
|
-- Written by Philip Horger
|
||||||
|
|
||||||
|
bencode = require "bencode" -- https://bitbucket.org/wilhelmy/lua-bencode/
|
||||||
|
dkjson = require "dkjson" -- http://dkolf.de/src/dkjson-lua.fsl/home
|
||||||
|
socket = require "socket" -- http://w3.impa.br/~diego/software/luasocket/
|
||||||
|
sha2 = require "sha2" -- https://code.google.com/p/sha2/
|
||||||
|
|
||||||
|
require "cjdns/admin"
|
||||||
|
require "cjdns/udp"
|
||||||
|
|
||||||
|
return require "cjdns/common"
|
264
cjdns/lua/cjdns/uci.lua
Normal file
264
cjdns/lua/cjdns/uci.lua
Normal file
|
@ -0,0 +1,264 @@
|
||||||
|
common = require("cjdns/common")
|
||||||
|
uci = require("uci")
|
||||||
|
|
||||||
|
UCI = {}
|
||||||
|
common.uci = UCI
|
||||||
|
|
||||||
|
--- Return the configuration defaults as a table suitable for JSON output
|
||||||
|
--
|
||||||
|
-- Mostly taken from cjdroute --genconf
|
||||||
|
-- @return table with configuration defaults
|
||||||
|
function UCI.defaults()
|
||||||
|
return {
|
||||||
|
security = { { exemptAngel = 1, setuser = "nobody" } },
|
||||||
|
router = {
|
||||||
|
ipTunnel = { outgoingConnections = {}, allowedConnections = {} },
|
||||||
|
interface = { type = "TUNInterface" }
|
||||||
|
},
|
||||||
|
interfaces = { UDPInterface = {}, ETHInterface = {} },
|
||||||
|
authorizedPasswords = {},
|
||||||
|
logging = { logTo = "stdout" }
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Return the cjdns configuration as a table suitable for JSON output
|
||||||
|
--
|
||||||
|
-- Iterates over cjdns, eth_interface, udp_interface, eth_peer, udp_peer,
|
||||||
|
-- and password sections. Doesn't include IPTunnel related options yet.
|
||||||
|
-- @return table with cjdns configuration
|
||||||
|
function UCI.get()
|
||||||
|
local obj = UCI.defaults()
|
||||||
|
|
||||||
|
local cursor = uci.cursor()
|
||||||
|
|
||||||
|
local config = cursor:get_all("cjdns", "cjdns")
|
||||||
|
if not config then return obj end
|
||||||
|
|
||||||
|
obj.ipv6 = config.ipv6
|
||||||
|
obj.publicKey = config.public_key
|
||||||
|
obj.privateKey = config.private_key
|
||||||
|
obj.admin = {
|
||||||
|
bind = config.admin_address .. ":" .. config.admin_port,
|
||||||
|
password = config.admin_password }
|
||||||
|
|
||||||
|
if config.tun_device and string.len(config.tun_device) > 0 then
|
||||||
|
obj.router.interface.tunDevice = config.tun_device
|
||||||
|
end
|
||||||
|
|
||||||
|
cursor:foreach("cjdns", "iptunnel_outgoing", function(outgoing)
|
||||||
|
table.insert(obj.router.ipTunnel.outgoingConnections, outgoing.public_key)
|
||||||
|
end)
|
||||||
|
|
||||||
|
cursor:foreach("cjdns", "iptunnel_allowed", function(allowed)
|
||||||
|
entry = { publicKey = allowed.public_key }
|
||||||
|
if allowed.ipv4 then
|
||||||
|
entry["ip4Address"] = allowed.ipv4
|
||||||
|
end
|
||||||
|
if allowed.ipv6 then
|
||||||
|
entry["ip6Address"] = allowed.ipv6
|
||||||
|
end
|
||||||
|
table.insert(obj.router.ipTunnel.allowedConnections, entry)
|
||||||
|
end)
|
||||||
|
|
||||||
|
cursor:foreach("cjdns", "eth_interface", function(eth_interface)
|
||||||
|
table.insert(obj.interfaces.ETHInterface, {
|
||||||
|
bind = eth_interface.bind,
|
||||||
|
beacon = tonumber(eth_interface.beacon),
|
||||||
|
connectTo = {}
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
|
||||||
|
cursor:foreach("cjdns", "udp_interface", function(udp_interface)
|
||||||
|
table.insert(obj.interfaces.UDPInterface, {
|
||||||
|
bind = udp_interface.address .. ":" .. udp_interface.port,
|
||||||
|
connectTo = {}
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
|
||||||
|
cursor:foreach("cjdns", "eth_peer", function(eth_peer)
|
||||||
|
if not eth_peer.address == "" then
|
||||||
|
local i = tonumber(eth_peer.interface)
|
||||||
|
obj.interfaces.ETHInterface[i].connectTo[eth_peer.address] = {
|
||||||
|
publicKey = eth_peer.public_key,
|
||||||
|
password = eth_peer.password
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
cursor:foreach("cjdns", "udp_peer", function(udp_peer)
|
||||||
|
local bind = udp_peer.address .. ":" .. udp_peer.port
|
||||||
|
local i = tonumber(udp_peer.interface)
|
||||||
|
obj.interfaces.UDPInterface[i].connectTo[bind] = {
|
||||||
|
user = udp_peer.user,
|
||||||
|
publicKey = udp_peer.public_key,
|
||||||
|
password = udp_peer.password
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
|
cursor:foreach("cjdns", "password", function(password)
|
||||||
|
table.insert(obj.authorizedPasswords, {
|
||||||
|
password = password.password,
|
||||||
|
user = password.user,
|
||||||
|
contact = password.contact
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
|
||||||
|
return obj
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Parse and save updated configuration from JSON input
|
||||||
|
--
|
||||||
|
-- Transforms general settings, ETHInterface, UDPInterface, connectTo, and
|
||||||
|
-- authorizedPasswords fields into UCI sections, and replaces the UCI config's
|
||||||
|
-- contents with them.
|
||||||
|
-- @param table JSON input
|
||||||
|
-- @return Boolean whether saving succeeded
|
||||||
|
function UCI.set(obj)
|
||||||
|
local cursor = uci.cursor()
|
||||||
|
|
||||||
|
for i, section in pairs(cursor:get_all("cjdns")) do
|
||||||
|
cursor:delete("cjdns", section[".name"])
|
||||||
|
end
|
||||||
|
|
||||||
|
local admin_address, admin_port = string.match(obj.admin.bind, "^(.*):(.*)$")
|
||||||
|
UCI.cursor_section(cursor, "cjdns", "cjdns", "cjdns", {
|
||||||
|
ipv6 = obj.ipv6,
|
||||||
|
public_key = obj.publicKey,
|
||||||
|
private_key = obj.privateKey,
|
||||||
|
admin_password = obj.admin.password,
|
||||||
|
admin_address = admin_address,
|
||||||
|
admin_port = admin_port,
|
||||||
|
})
|
||||||
|
|
||||||
|
if obj.router.interface.tunDevice then
|
||||||
|
UCI.cursor_section(cursor, "cjdns", "cjdns", "cjdns", {
|
||||||
|
tun_device = tostring(obj.router.interface.tunDevice)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
if obj.router.ipTunnel.outgoingConnections then
|
||||||
|
for i,public_key in pairs(obj.router.ipTunnel.outgoingConnections) do
|
||||||
|
UCI.cursor_section(cursor, "cjdns", "iptunnel_outgoing", nil, {
|
||||||
|
public_key = public_key
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if obj.router.ipTunnel.allowedConnections then
|
||||||
|
for i,allowed in pairs(obj.router.ipTunnel.allowedConnections) do
|
||||||
|
entry = { public_key = allowed.publicKey }
|
||||||
|
if allowed.ip4Address then
|
||||||
|
entry["ipv4"] = allowed.ip4Address
|
||||||
|
end
|
||||||
|
if allowed.ip6Address then
|
||||||
|
entry["ipv6"] = allowed.ip6Address
|
||||||
|
end
|
||||||
|
|
||||||
|
UCI.cursor_section(cursor, "cjdns", "iptunnel_allowed", nil, entry)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if obj.interfaces.ETHInterface then
|
||||||
|
for i,interface in pairs(obj.interfaces.ETHInterface) do
|
||||||
|
UCI.cursor_section(cursor, "cjdns", "eth_interface", nil, {
|
||||||
|
bind = interface.bind,
|
||||||
|
beacon = tostring(interface.beacon)
|
||||||
|
})
|
||||||
|
|
||||||
|
if interface.connectTo then
|
||||||
|
for peer_address,peer in pairs(interface.connectTo) do
|
||||||
|
UCI.cursor_section(cursor, "cjdns", "eth_peer", nil, {
|
||||||
|
interface = i,
|
||||||
|
address = peer_address,
|
||||||
|
public_key = peer.publicKey,
|
||||||
|
password = peer.password
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if obj.interfaces.UDPInterface then
|
||||||
|
for i,interface in pairs(obj.interfaces.UDPInterface) do
|
||||||
|
local address, port = string.match(interface.bind, "^(.*):(.*)$")
|
||||||
|
UCI.cursor_section(cursor, "cjdns", "udp_interface", nil, {
|
||||||
|
address = address,
|
||||||
|
port = port
|
||||||
|
})
|
||||||
|
|
||||||
|
if interface.connectTo then
|
||||||
|
for peer_bind,peer in pairs(interface.connectTo) do
|
||||||
|
local peer_address, peer_port = string.match(peer_bind, "^(.*):(.*)$")
|
||||||
|
UCI.cursor_section(cursor, "cjdns", "udp_peer", nil, {
|
||||||
|
interface = i,
|
||||||
|
address = peer_address,
|
||||||
|
port = peer_port,
|
||||||
|
user = peer.user,
|
||||||
|
public_key = peer.publicKey,
|
||||||
|
password = peer.password
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if obj.authorizedPasswords then
|
||||||
|
for i,password in pairs(obj.authorizedPasswords) do
|
||||||
|
local user = password.user
|
||||||
|
if not user or string.len(user) == 0 then
|
||||||
|
user = "user-" .. UCI.random_string(6)
|
||||||
|
end
|
||||||
|
|
||||||
|
UCI.cursor_section(cursor, "cjdns", "password", nil, {
|
||||||
|
password = password.password,
|
||||||
|
user = user,
|
||||||
|
contact = password.contact
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return cursor:save("cjdns")
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Simple backport of Cursor:section from luci.model.uci
|
||||||
|
--
|
||||||
|
-- Backport reason: we don't wanna depend on LuCI.
|
||||||
|
-- @param Cursor the UCI cursor to operate on
|
||||||
|
-- @param string name of the config
|
||||||
|
-- @param string type of the section
|
||||||
|
-- @param string name of the section (optional)
|
||||||
|
-- @param table config values
|
||||||
|
function UCI.cursor_section(cursor, config, type, section, values)
|
||||||
|
if section then
|
||||||
|
cursor:set(config, section, type)
|
||||||
|
else
|
||||||
|
section = cursor:add("cjdns", type)
|
||||||
|
end
|
||||||
|
|
||||||
|
for k,v in pairs(values) do
|
||||||
|
cursor:set(config, section, k, v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function UCI.makeInterface()
|
||||||
|
local cursor = uci.cursor()
|
||||||
|
|
||||||
|
local config = cursor:get_all("cjdns", "cjdns")
|
||||||
|
if not config then return nil end
|
||||||
|
|
||||||
|
return common.AdminInterface.new({
|
||||||
|
host = config.admin_address,
|
||||||
|
port = config.admin_port,
|
||||||
|
password = config.admin_password,
|
||||||
|
config = UCI.get(),
|
||||||
|
timeout = 2
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
function UCI.random_string(length)
|
||||||
|
-- tr -cd 'A-Za-z0-9' < /dev/urandom
|
||||||
|
local urandom = io.popen("tr -cd 'A-Za-z0-9' 2> /dev/null < /dev/urandom", "r")
|
||||||
|
local string = urandom:read(length)
|
||||||
|
urandom:close()
|
||||||
|
return string
|
||||||
|
end
|
102
cjdns/lua/cjdns/udp.lua
Normal file
102
cjdns/lua/cjdns/udp.lua
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
-- Cjdns admin module for Lua
|
||||||
|
-- Written by Philip Horger
|
||||||
|
|
||||||
|
common = require 'cjdns/common'
|
||||||
|
|
||||||
|
UDPInterface = {}
|
||||||
|
UDPInterface.__index = UDPInterface
|
||||||
|
common.UDPInterface = UDPInterface
|
||||||
|
|
||||||
|
function UDPInterface.new(ai, config, ptype)
|
||||||
|
properties = {
|
||||||
|
ai = ai,
|
||||||
|
config = config or ai.config,
|
||||||
|
ptype = ptype or "ai"
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(properties, UDPInterface)
|
||||||
|
end
|
||||||
|
|
||||||
|
function UDPInterface:call(name, args)
|
||||||
|
local func = self[name .. "_" .. self.ptype]
|
||||||
|
return func(self, unpack(args))
|
||||||
|
end
|
||||||
|
|
||||||
|
function UDPInterface:newBind(...)
|
||||||
|
return self:call("newBind", arg)
|
||||||
|
end
|
||||||
|
|
||||||
|
function UDPInterface:beginConnection(...)
|
||||||
|
return self:call("beginConnection", arg)
|
||||||
|
end
|
||||||
|
|
||||||
|
function UDPInterface:newBind_ai(address)
|
||||||
|
local response, err = self.ai:auth({
|
||||||
|
q = "UDPInterface_new",
|
||||||
|
bindAddress = address
|
||||||
|
})
|
||||||
|
if not response then
|
||||||
|
return nil, err
|
||||||
|
elseif response.error ~= "none" then
|
||||||
|
return nil, response.error
|
||||||
|
elseif response.interfaceNumber then
|
||||||
|
return response.interfaceNumber
|
||||||
|
else
|
||||||
|
return nil, "bad response format"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function UDPInterface:newBind_config(address)
|
||||||
|
local udpif = self.config.contents.interfaces.UDPInterface
|
||||||
|
local new_interface = {
|
||||||
|
bind = address,
|
||||||
|
connectTo = {}
|
||||||
|
}
|
||||||
|
table.insert(udpif, new_interface)
|
||||||
|
return (#udpif - 1), new_interface
|
||||||
|
end
|
||||||
|
|
||||||
|
function UDPInterface:newBind_perm(...)
|
||||||
|
return
|
||||||
|
self:newBind_config(unpack(arg)),
|
||||||
|
self:newBind_ai(unpack(arg))
|
||||||
|
end
|
||||||
|
|
||||||
|
function UDPInterface:beginConnection_ai(pubkey, addr, password, interface)
|
||||||
|
local request = {
|
||||||
|
q = "UDPInterface_beginConnection",
|
||||||
|
publicKey = pubkey,
|
||||||
|
address = addr,
|
||||||
|
password = password
|
||||||
|
}
|
||||||
|
if interface then
|
||||||
|
request.interfaceNumber = interface
|
||||||
|
end
|
||||||
|
|
||||||
|
local response, err = self.ai:auth(request)
|
||||||
|
if not response then
|
||||||
|
return nil, err
|
||||||
|
elseif response.error == "none" then
|
||||||
|
-- Unfortunately, no real success indicator either.
|
||||||
|
return "No error"
|
||||||
|
else
|
||||||
|
return nil, response.error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function UDPInterface:beginConnection_config(pubkey, addr, password, interface)
|
||||||
|
local udpif = self.config.contents.interfaces.UDPInterface
|
||||||
|
local connections = udpif[(interface or 0) + 1].connectTo
|
||||||
|
local this_conn = {
|
||||||
|
password = password,
|
||||||
|
publicKey = pubkey
|
||||||
|
}
|
||||||
|
connections[addr] = this_conn
|
||||||
|
return this_conn -- allows adding metadata fields afterwards
|
||||||
|
end
|
||||||
|
|
||||||
|
function UDPInterface:beginConnection_perm(...)
|
||||||
|
return
|
||||||
|
self:beginConnection_config(unpack(arg)),
|
||||||
|
self:beginConnection_ai(unpack(arg))
|
||||||
|
end
|
29
cjdns/patches/010-fix-musl-build.patch
Normal file
29
cjdns/patches/010-fix-musl-build.patch
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
Index: cjdns-649e26c7d61ccc66c20e87e1e3d381f9ef0cfcb0/crypto/random/seed/LinuxRandomUuidSysctlRandomSeed.c
|
||||||
|
===================================================================
|
||||||
|
--- cjdns-649e26c7d61ccc66c20e87e1e3d381f9ef0cfcb0.orig/crypto/random/seed/LinuxRandomUuidSysctlRandomSeed.c
|
||||||
|
+++ cjdns-649e26c7d61ccc66c20e87e1e3d381f9ef0cfcb0/crypto/random/seed/LinuxRandomUuidSysctlRandomSeed.c
|
||||||
|
@@ -18,6 +18,8 @@
|
||||||
|
#include "util/Hex.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
+
|
||||||
|
+#ifdef __GLIBC__
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
|
||||||
|
static int getUUID(uint64_t output[2])
|
||||||
|
@@ -42,6 +44,15 @@ static int get(struct RandomSeed* random
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#else
|
||||||
|
+
|
||||||
|
+static int get(struct RandomSeed* randomSeed, uint64_t output[8])
|
||||||
|
+{
|
||||||
|
+ return -1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
struct RandomSeed* LinuxRandomUuidSysctlRandomSeed_new(struct Allocator* alloc)
|
||||||
|
{
|
||||||
|
return Allocator_clone(alloc, (&(struct RandomSeed) {
|
Loading…
Reference in a new issue