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