aboutsummaryrefslogtreecommitdiff
path: root/net/yggdrasil/files/ygguci
blob: cdeb3c1a9924c760aa663e460e03035626c146c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#!/usr/bin/env lua

dkjson = require("dkjson")
uci	= require("uci")

UCI = {}

--- Return the configuration defaults as a table suitable for JSON output
--
-- Mostly taken from yggdrasil -genconf -json
-- @return table with configuration defaults
function UCI.defaults()
	return { 
		AdminListen = "unix:///var/run/yggdrasil.sock", IfName = "ygg0", 
		NodeInfoPrivacy = false,
		IfMTU = 65535,

		Peers = { }, Listen = { }, MulticastInterfaces = { }, AllowedPublicKeys = { },
		InterfacePeers = setmetatable({ }, {__jsontype = "object"}),
		NodeInfo = setmetatable({ }, {__jsontype = "object"})
	}
end

--- Return the yggdrasil configuration as a table suitable for JSON output
--
-- @return table with yggdrasil configuration
function UCI.get()
	local obj = UCI.defaults()

	local cursor = uci.cursor()
	local config = cursor:get_all("yggdrasil", "yggdrasil")
	if not config then return obj end

	obj.PublicKey = config.PublicKey
	obj.PrivateKey = config.PrivateKey
	obj.AdminListen = config.AdminListen or obj.AdminListen
	obj.IfName = config.IfName or obj.IfName
	obj.NodeInfo = dkjson.decode(config.NodeInfo) or obj.NodeInfo
	for _, v in pairs({ "NodeInfoPrivacy" }) do
		if config[v] ~= nil then obj[v] = to_bool(config[v]) end
	end
	if config["IfMTU"] ~= nil then obj["IfMTU"] = tonumber(config["IfMTU"]) end

	cursor:foreach("yggdrasil", "peer", function (s) 
		table.insert(obj.Peers, s.uri)
	end)
	cursor:foreach("yggdrasil", "listen_address", function (s) 
		table.insert(obj.Listen, s.uri)
	end)
	cursor:foreach("yggdrasil", "multicast_interface", function (s) 
		table.insert(obj.MulticastInterfaces, {
			Beacon = to_bool(s.beacon), Listen = to_bool(s.listen),
			Port = tonumber(s.port), Regex = s.regex
		})
	end)
	cursor:foreach("yggdrasil", "allowed_public_key", function (s) 
		table.insert(obj.AllowedPublicKeys, s.key)
	end)

	cursor:foreach("yggdrasil", "interface_peer", function (s) 
		if obj.InterfacePeers[s.interface] == nil then
			obj.InterfacePeers[s.interface] = {}
		end
		table.insert(obj.InterfacePeers[s["interface"]], s.uri)
	end)

	return obj
end

--- Parse and save updated configuration from JSON input
--
-- Transforms general settings 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("yggdrasil")) do
		cursor:delete("yggdrasil", section[".name"])
	end


	cursor:set("yggdrasil", "yggdrasil", "yggdrasil")
	cursor:set("yggdrasil", "yggdrasil", "PublicKey", obj.PublicKey) 
	cursor:set("yggdrasil", "yggdrasil", "PrivateKey", obj.PrivateKey) 
	cursor:set("yggdrasil", "yggdrasil", "AdminListen", obj.AdminListen) 
	cursor:set("yggdrasil", "yggdrasil", "IfName", obj.IfName) 
	cursor:set("yggdrasil", "yggdrasil", "NodeInfoPrivacy", to_int(obj.NodeInfoPrivacy)) 
	cursor:set("yggdrasil", "yggdrasil", "NodeInfo", dkjson.encode(obj.NodeInfo)) 
	cursor:set("yggdrasil", "yggdrasil", "IfMTU", obj.IfMTU)

	set_values(cursor, "peer", "uri", obj.Peers)
	set_values(cursor, "listen_address", "uri", obj.Listen)

	for _, interface in pairs(obj.MulticastInterfaces) do
		local name = cursor:add("yggdrasil", "multicast_interface")
		cursor:set("yggdrasil", name, "beacon", to_int(interface.Beacon))
		cursor:set("yggdrasil", name, "listen", to_int(interface.Listen))
		cursor:set("yggdrasil", name, "port", interface.Port)
		cursor:set("yggdrasil", name, "regex", interface.Regex)
	end

	set_values(cursor, "allowed_public_key", "key", obj.AllowedPublicKeys)

	for interface, peers in pairs(obj.InterfacePeers) do
		for _, v in pairs(peers) do
			local name = cursor:add("yggdrasil", "interface_peer")
			cursor:set("yggdrasil", name, "interface", interface)
			cursor:set("yggdrasil", name, "uri", v)
		end
	end

	return cursor:commit("yggdrasil")
end

function set_values(cursor, section_name, parameter, values) 
	if values == nil then return false end

	for k, v in pairs(values) do
		local name = cursor:add("yggdrasil", section_name)
		cursor:set("yggdrasil", name, parameter, v)
	end
end

function to_int(bool) return bool and '1' or '0' end

function to_bool(int) return int ~= '0' end

function help()
	print("JSON interface to /etc/config/yggdrasil\n\nExamples: \
	ygguci get > /tmp/etc/yggdrasil.conf \
	cat /tmp/etc/yggdrasil.conf | ygguci set \
	uci changes \
	ygguci get | yggdrasil -useconf")
end

-- main 

if arg[1] == "get" then
	local json = dkjson.encode(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
		UCI.set(obj)
	else
		print("dkjson: " .. err)
		os.exit(1)
	end
else
	help()
end