You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
4.6 KiB

  1. #!/usr/bin/env lua
  2. dkjson = require("dkjson")
  3. uci = require("uci")
  4. UCI = {}
  5. --- Return the configuration defaults as a table suitable for JSON output
  6. --
  7. -- Mostly taken from yggdrasil -genconf -json
  8. -- @return table with configuration defaults
  9. function UCI.defaults()
  10. return {
  11. AdminListen = "unix:///var/run/yggdrasil.sock", IfName = "ygg0",
  12. NodeInfoPrivacy = false,
  13. IfMTU = 65535,
  14. Peers = { }, Listen = { }, MulticastInterfaces = { }, AllowedPublicKeys = { },
  15. InterfacePeers = setmetatable({ }, {__jsontype = "object"}),
  16. NodeInfo = setmetatable({ }, {__jsontype = "object"})
  17. }
  18. end
  19. --- Return the yggdrasil configuration as a table suitable for JSON output
  20. --
  21. -- @return table with yggdrasil configuration
  22. function UCI.get()
  23. local obj = UCI.defaults()
  24. local cursor = uci.cursor()
  25. local config = cursor:get_all("yggdrasil", "yggdrasil")
  26. if not config then return obj end
  27. obj.PublicKey = config.PublicKey
  28. obj.PrivateKey = config.PrivateKey
  29. obj.AdminListen = config.AdminListen or obj.AdminListen
  30. obj.IfName = config.IfName or obj.IfName
  31. obj.NodeInfo = dkjson.decode(config.NodeInfo) or obj.NodeInfo
  32. for _, v in pairs({ "NodeInfoPrivacy" }) do
  33. if config[v] ~= nil then obj[v] = to_bool(config[v]) end
  34. end
  35. if config["IfMTU"] ~= nil then obj["IfMTU"] = tonumber(config["IfMTU"]) end
  36. cursor:foreach("yggdrasil", "peer", function (s)
  37. table.insert(obj.Peers, s.uri)
  38. end)
  39. cursor:foreach("yggdrasil", "listen_address", function (s)
  40. table.insert(obj.Listen, s.uri)
  41. end)
  42. cursor:foreach("yggdrasil", "multicast_interface", function (s)
  43. table.insert(obj.MulticastInterfaces, {
  44. Beacon = to_bool(s.beacon), Listen = to_bool(s.listen),
  45. Port = tonumber(s.port), Regex = s.regex
  46. })
  47. end)
  48. cursor:foreach("yggdrasil", "allowed_public_key", function (s)
  49. table.insert(obj.AllowedPublicKeys, s.key)
  50. end)
  51. cursor:foreach("yggdrasil", "interface_peer", function (s)
  52. if obj.InterfacePeers[s.interface] == nil then
  53. obj.InterfacePeers[s.interface] = {}
  54. end
  55. table.insert(obj.InterfacePeers[s["interface"]], s.uri)
  56. end)
  57. return obj
  58. end
  59. --- Parse and save updated configuration from JSON input
  60. --
  61. -- Transforms general settings into UCI sections, and replaces the UCI config's
  62. -- contents with them.
  63. -- @param table JSON input
  64. -- @return Boolean whether saving succeeded
  65. function UCI.set(obj)
  66. local cursor = uci.cursor()
  67. for i, section in pairs(cursor:get_all("yggdrasil")) do
  68. cursor:delete("yggdrasil", section[".name"])
  69. end
  70. cursor:set("yggdrasil", "yggdrasil", "yggdrasil")
  71. cursor:set("yggdrasil", "yggdrasil", "PublicKey", obj.PublicKey)
  72. cursor:set("yggdrasil", "yggdrasil", "PrivateKey", obj.PrivateKey)
  73. cursor:set("yggdrasil", "yggdrasil", "AdminListen", obj.AdminListen)
  74. cursor:set("yggdrasil", "yggdrasil", "IfName", obj.IfName)
  75. cursor:set("yggdrasil", "yggdrasil", "NodeInfoPrivacy", to_int(obj.NodeInfoPrivacy))
  76. cursor:set("yggdrasil", "yggdrasil", "NodeInfo", dkjson.encode(obj.NodeInfo))
  77. cursor:set("yggdrasil", "yggdrasil", "IfMTU", obj.IfMTU)
  78. set_values(cursor, "peer", "uri", obj.Peers)
  79. set_values(cursor, "listen_address", "uri", obj.Listen)
  80. for _, interface in pairs(obj.MulticastInterfaces) do
  81. local name = cursor:add("yggdrasil", "multicast_interface")
  82. cursor:set("yggdrasil", name, "beacon", to_int(interface.Beacon))
  83. cursor:set("yggdrasil", name, "listen", to_int(interface.Listen))
  84. cursor:set("yggdrasil", name, "port", interface.Port)
  85. cursor:set("yggdrasil", name, "regex", interface.Regex)
  86. end
  87. set_values(cursor, "allowed_public_key", "key", obj.AllowedPublicKeys)
  88. for interface, peers in pairs(obj.InterfacePeers) do
  89. for _, v in pairs(peers) do
  90. local name = cursor:add("yggdrasil", "interface_peer")
  91. cursor:set("yggdrasil", name, "interface", interface)
  92. cursor:set("yggdrasil", name, "uri", v)
  93. end
  94. end
  95. return cursor:commit("yggdrasil")
  96. end
  97. function set_values(cursor, section_name, parameter, values)
  98. if values == nil then return false end
  99. for k, v in pairs(values) do
  100. local name = cursor:add("yggdrasil", section_name)
  101. cursor:set("yggdrasil", name, parameter, v)
  102. end
  103. end
  104. function to_int(bool) return bool and '1' or '0' end
  105. function to_bool(int) return int ~= '0' end
  106. function help()
  107. print("JSON interface to /etc/config/yggdrasil\n\nExamples: \
  108. ygguci get > /tmp/etc/yggdrasil.conf \
  109. cat /tmp/etc/yggdrasil.conf | ygguci set \
  110. uci changes \
  111. ygguci get | yggdrasil -useconf")
  112. end
  113. -- main
  114. if arg[1] == "get" then
  115. local json = dkjson.encode(UCI.get(), { indent = true })
  116. print(json)
  117. elseif arg[1] == "set" then
  118. local json = io.stdin:read("*a")
  119. local obj, pos, err = dkjson.decode(json, 1, nil)
  120. if obj then
  121. UCI.set(obj)
  122. else
  123. print("dkjson: " .. err)
  124. os.exit(1)
  125. end
  126. else
  127. help()
  128. end