module(..., package.seeall) -- Load libraries require("modelfunctions") require("validator") -- Set variables local configfile = "/etc/opennhrp/opennhrp.conf" local processname = "opennhrp" local packagename = "opennhrp" --[[ local descr = { Type = { ['incomplete']="The protocol address is being resolved", ['negative']="This protocol address is not available", ['cached']="Protocol address was resolved successfully", ['route']="This is a dynamic shortcut", ['dynamic']="This entry is from a node that connected to us", ['local']="Local interface address", ['static']="Static mapping from configuration file (e.g. address of core)", }, Flags= { -- ['up']="Connection is fully usable", ['lower-up']="ipsec connections is up, but registration is not yet done", }, } -- ################################################################################ -- LOCAL FUNCTIONS local function opennhrpctl_show() local cmd_output_result={} local cmd_output_result_table={} local cmd_output_error, opennhrpstatus local cmd = "/usr/sbin/opennhrpctl show 2>/dev/null" local f = io.popen( cmd ) for line in f:lines() do if string.find(line, "^Status:") then opennhrpstatus=line else table.insert(cmd_output_result, line) end end f:close() local cnt = 0 for k,v in pairs(cmd_output_result) do if string.find(v,"^Interface") then cnt = cnt + 1 cmd_output_result_table[cnt] = {} end if ( cnt > 0 ) and (v ~= "") then local k = string.match(v,"^(.-):%s?.*") cmd_output_result_table[cnt][k]=cfe({value=string.match(v,"^.-:%s?(.*)")}) local statusdescription = string.lower(string.match(v,"^.-:%s?(.*)")) if (type(descr[k]) == "table") then cmd_output_result_table[cnt][k]['descr']=descr[k][statusdescription] end end end local peers_list = {} for k,v in pairs(cmd_output_result_table) do if (v.Interface.value) and not (peers_list[v.Interface.value]) then peers_list[v.Interface.value] = {} end table.insert(peers_list[v.Interface.value], v) end return peers_list,opennhrpstatus,cmd_output_error end --]] local function parseconfigfile(self, configfile) if fs.is_file(configfile) then configfile = fs.read_file(configfile) end -- Get the list of available interfaces local interfaces = self:new("alpine-baselayout/interfaces") local availableinterfaces = interfaces:read() local listinterfaces = {} local reverseinterfaces = {} for i,int in ipairs(availableinterfaces.value) do listinterfaces[#listinterfaces + 1] = int.value.name.value reverseinterfaces[int.value.name.value] = #listinterfaces end interfaces:destroy() local outgoinginterface = cfe({ type="select", label="Outgoing Interface", option=listinterfaces }) local publishedinterfaces = cfe({ type="multi", value={}, label="Published Interfaces", option=listinterfaces }) local peers = cfe({ type="list", value={}, label="Registered Peers", descr="protocol-address[/prefix] nbma-address" }) local currentinterface = "" local words = {} for word in configfile:gmatch("%S+") do words[#words + 1] = word end for i,word in ipairs(words) do if word == "interface" then currentinterface = words[i+1] elseif word == "map" then if outgoinginterface.value ~= "" and outgoinginterface.value ~= currentinterface then outgoinginterface.errtxt = "Multiple outgoing interfaces not supported" else outgoinginterface.value = currentinterface peers.value[#peers.value + 1] = words[i+1] .. " " .. words[i+2] end elseif word == "shortcut-destination" then publishedinterfaces.value[#publishedinterfaces.value + 1] = currentinterface end end return cfe({ type="group", value={outgoinginterface=outgoinginterface, peers=peers, publishedinterfaces=publishedinterfaces}, label="OpenNHRP Config" }) end local function generateconfigfile(config) local filelines = {} filelines[#filelines + 1] = "interface " .. config.value.outgoinginterface.value for i,value in ipairs(config.value.peers.value) do filelines[#filelines + 1] = " map " .. value .. " register" end filelines[#filelines + 1] = " shortcut" filelines[#filelines + 1] = " redirect" filelines[#filelines + 1] = " non-caching" filelines[#filelines + 1] = "" for i,value in ipairs(config.value.publishedinterfaces.value) do filelines[#filelines + 1] = "interface " .. value filelines[#filelines + 1] = " shortcut-destination" filelines[#filelines + 1] = "" end return table.concat(filelines, "\n") end local function validateconfig(config) local success = true if not modelfunctions.validateselect(config.value.outgoinginterface) then success = false end if not modelfunctions.validatemulti(config.value.publishedinterfaces) then success = false end -- make sure don't try to publish the outgoing interface for i,value in ipairs(config.value.publishedinterfaces.value) do if value == config.value.outgoinginterface.value then success = false config.value.publishedinterfaces.errtxt = "Cannot publish outgoing interface" break end end for i,value in ipairs(config.value.peers.value) do if not validator.is_ipv4(value:match("[^%s/]+")) or not validator.is_ipv4(value:match("%s(%S+)")) then success = false config.value.peers.errtxt = "Syntax error - invalid ip address" break elseif value:match("/(%d*)") and not validator.is_integer_in_range(value:match("/(%d*)"), 1, 31) then success = false config.value.peers.errtxt = "Syntax error - invalid prefix" break end end return success, config end local function validateconfigfile(self, configfile) local config = parseconfigfile(self, configfile.value.filecontent.value) local success, config = validateconfig(config) if not success then local errtxt = {} for name,value in pairs(config.value) do if value.errtxt then errtxt[#errtxt + 1] = name .. " - " .. value.errtxt end end if #errtxt then configfile.value.filecontent.errtxt = table.concat(errtxt, "\n") end end return success, configfile end -- ################################################################################ -- PUBLIC FUNCTIONS function startstop_service(action) return modelfunctions.startstop_service(processname, action) end function getstatus() return modelfunctions.getstatus(processname, packagename, "Opennhrp Status") end function getshowreport() local show = cfe({ type="longtext", label="OpenNHRP show report" }) local cmd = "/usr/sbin/opennhrpctl show 2>/dev/null" local f = io.popen( cmd ) show.value = f:read("*a") if not show.value or show.value == "" then show.value = "No report available" end return show end function getconfig(self) local config = parseconfigfile(self, configfile) local result, config = validateconfig(config) return config end function setconfig(self, config) local success, config = validateconfig(config) if success then fs.write_file(configfile, generateconfigfile(config)) else config.errtxt = "Failed to set configuration" end return config end function getconfigfile(self) local filedetails = modelfunctions.getfiledetails(configfile) local result, filedetails = validateconfigfile(self, filedetails) return filedetails end function setconfigfile(self, filedetails) filedetails.value.filename.value = configfile filedetails.value.filecontent.value = string.gsub(format.dostounix(filedetails.value.filecontent.value), "\n+$", "") local success, filedetails = validateconfigfile(self, filedetails) if success then fs.write_file(configfile, filedetails.value.filecontent.value) filedetails = getconfigfile(self) else filedetails.errtxt = "Failed to set configuration file" end return filedetails end