module(..., package.seeall) -- Load libraries require("modelfunctions") require("fs") require("format") require("posix") require("validator") -- Set variables local configfile = "/etc/dnsmasq.conf" local processname = "dnsmasq" local packagename = "dnsmasq" local baseurl = "/etc/" local descr = { } -- ################################################################################ -- LOCAL FUNCTIONS local function validateconfig(config) local success = true if config.value.IPSEND and not validator.is_ipv4(config.value.IPSEND.value) then config.value.IPSEND.errtxt = "Invalid IP address" success = false end if config.value.IP and not validator.is_ipv4(config.value.IP.value) then config.value.IP.errtxt = "Invalid IP address" success = false end return success, config end local function validatedomain(domain) local success = false local domains = getDomains() domain.value.domain.errtxt = "Invalid domain" for i,name in ipairs(domains.value) do if name == domain.value.domain.value then domain.value.domain.errtxt = nil success = true break end end for i,name in ipairs(domain.value.iplist.value) do if not validator.is_ipv4(name) then domain.value.iplist.errtxt = "Invalid IP address" success = false break end end return success, domain end -- ################################################################################ -- PUBLIC FUNCTIONS function startstop_service(action) return modelfunctions.startstop_service(processname, action) end function getstatus() return modelfunctions.getstatus(processname, packagename, "DNS Masq Status") end function getconfig() local conf = format.parse_ini_file(fs.read_file(configfile), "") or {} require ("html") local output = {} output.DOMAIN = cfe({ value = conf.domain or "", label="Local Domain to use", descr="Internal Domain for your LAN" }) output.INTERFACE = cfe({ value=conf.interface, label="Interface" }) output.IP = cfe({ value=conf["listen-address"] or "", label="IP address to listen on" }) output.RANGE = cfe ({value=conf["dhcp-range"] or "", label="Range of IPs", descr="First,Last,Netmask,Time in hours"}) -- APP.logevent(html.cfe_unpack(output)) return cfe({ type="group", value=output, label="DNS Masq Config" }) end function setconfig(config) local success, config = validateconfig(config) if success then local file = fs.read_file(configfile) file = format.update_ini_file(file,"","domain",config.value.DOMAIN.value) file = format.update_ini_file(file,"","interface",config.value.INTERFACE.value) file = format.update_ini_file(file,"","listen-address",config.value.IP.value) file = format.update_ini_file(file,"","dhcp-range",config.value.RANGE.value) fs.write_file(configfile, file) else config.errtxt = "Failed to set config" end return config end function getconfigfile() -- FIXME Validate return modelfunctions.getfiledetails(configfile) end function setconfigfile(filedetails) -- FIXME Validate return modelfunctions.setfiledetails(filedetails, {configfile}) end function getIPs() local ipdir = baseurl.."ip" local iplist = cfe({ type="list", value={}, label="IP prefixes to respond to" }) if fs.is_dir(ipdir) then for i,name in ipairs(posix.dir(ipdir)) do if not string.match(name, "^%.") then if (fs.is_file(ipdir.."/"..name)) then table.insert(iplist.value, name) end end end end return cfe({ type="group", value={iplist=iplist} }) end function setIPs(iplist) local reverseIPs = {} for i,name in ipairs(iplist.value.iplist.value) do -- check if a valid (or partial) ip if not validator.is_partial_ipv4(name) then iplist.value.iplist.errtxt = "Invalid IP address" iplist.errtxt = "Failed to set IP list" break end reverseIPs[name] = i end if not iplist.errtxt then local currentIPlist = getIPs() for i,name in ipairs(currentIPlist.value.iplist.value) do if reverseIPs[name] then reverseIPs[name] = nil else -- need to delete the file local f = io.popen("rm "..baseurl.."ip/"..name) f:close() end end for name in pairs(reverseIPs) do -- need to create the file local f = io.popen("touch "..baseurl.."ip/"..name) f:close() end end return iplist end function getDomains() local domaindir = baseurl.."servers" local domainlist = cfe({ type="list", value={}, label="DNS Server Domains" }) if fs.is_dir(domaindir) then for i,name in ipairs(posix.dir(domaindir)) do if not string.match(name, "^%.") then if (fs.is_file(domaindir.."/"..name)) then table.insert(domainlist.value, name) end end end end return domainlist end function getNewDomain() local domain = cfe({ label="Domain" }) return cfe({ type="group", value={domain=domain} }) end function setNewDomain(domain) if "" ~= string.gsub(domain.value.domain.value..".", "%w+%.", "") then domain.value.domain.errtxt = "Invalid domain" domain.errtxt = "Failed to create domain" elseif fs.is_file(baseurl.."servers/"..domain.value.domain.value) then domain.value.domain.errtxt = "Domain already exists" domain.errtxt = "Failed to create domain" else local f = io.popen("touch "..baseurl.."servers/"..domain.value.domain.value) f:close() domain.descr = "Created domain" end return domain end function getDomain(getdomainname) local domain = cfe({ value=getdomainname, label="Domain", errtxt="Invalid domain" }) local iplist = cfe({ type="list", value={}, label="List of DNS servers" }) local domains = getDomains() for i,name in ipairs(domains.value) do if name == getdomainname then domain.errtxt = nil break end end if not domain.errtxt then local content = fs.read_file(baseurl.."servers/"..getdomainname) for name in string.gmatch(content.."\n", "([^\n]+)\n") do table.insert(iplist.value, name) end end return cfe({ type="group", value={domain=domain, iplist=iplist} }) end function setDomain(domain) local success, domain = validatedomain(domain) if success then fs.write_file(baseurl.."servers/"..domain.value.domain.value, table.concat(domain.value.iplist.value, "\n") ) else domain.errtxt = "Failed to save domain" end return domain end function deleteDomain(domainname) local cmdresult = cfe({ value="Domain not deleted", label="Delete domain result", errtxt="Invalid domain" }) local domains = getDomains() if domainname == "@" then cmdresult.errtxt = "Cannot delete root domain" else for i,name in ipairs(domains.value) do if name == domainname then local f = io.popen("rm "..baseurl.."servers/"..name) f:close() cmdresult.errtxt = nil cmdresult.value = "Domain deleted" break end end end return cmdresult end