-- hostname model methods module (..., package.seeall) require ("posix") require ("fs") -- no initializer in model - use controller.init for that -- ################################################################################ -- UNKNOWN --local function read_file_as_array ( path ) -- local file, error = io.open(path) -- if ( file == nil ) then -- return nil, error -- end -- local f = {} -- for line in file:lines() do -- table.insert ( f , line ) -- end -- file:close() -- return f --end local function has_init_script ( f ) local initprefix = "/etc/init.d/openvpn" local file = initprefix .. "." .. f if f ~= "openvpn" then if ( fs.is_file(file)) then init = "yes" else init = nil end else if ( fs.is_file(initprefix)) then init = "yes" else init = nil end end return init end -- ################################################################################ -- LOCAL FUNCTIONS local function config_content( f ) local config = {} config.name = "/etc/openvpn/" .. f local conf_file = fs.read_file_as_array ( config.name ) for i=1,table.maxn(conf_file) do local l = conf_file[i] -- Filter out commented lines if not string.find ( l, "^[;#].*" ) then local a,b = string.match ( l, "^%s*(%S*)%s+(%S*).*$" ) -- Working exept on 'remote xxxxx xxxx' -- local a,b = string.match ( l, "^%s*(%S*)%s+(.*)%s+$" ) -- This brakes client/server check if (a) then config[a]=b end end end if not ( config.log ) then config.log = config["log-append"] end if not ( config["max-clients"] ) then config["max-clients"] = "Unlimited" end if not ( config["local"] ) then config["local"] = "0.0.0.0" end return config end local is_running = function( process, parameters ) local strsplit = require("split") local retval = "" local tst = "" local pidofsx, error = io.popen("pidof " .. process ,r) local pidofs = string.gsub(pidofsx:read("*a"), "\n", "") pidofsx:close() -- if ( pidofs ~= nil ) then for v in string.gmatch(pidofs, "%S+") do local path = string.gsub("/proc/".. v .. "/cmdline", "%s", "") local f,err = io.open(path,r) local file_resultx = f:read("*a") local file_result = string.match(file_resultx, parameters) f:close() if ( file_result ) then retval = "Running" end end -- end return retval end local function check_valid_config ( f ) config.err = "" if not (config.client) or not (config.ca) or not (config.cert) or not (config.key) or not (config.dev) or not (config.proto) or not (config.remote) then config.type = nil config.err = "" if not (config.ca) then config.err = config.err .. "Check CA; " end if not (config.cert) then config.err = config.err .. "Check CERT; " end if not (config.key) then config.err = config.err .. "Check KEY; " end if not (config.dev) then config.err = config.err .. "Check DEV; " end if not (config.proto) then config.err = config.err .. "Check PROTO; " end if (config.client) or not (config.ca) or not (config.cert) or not (config.key) or not (config.dev) or not (config.proto) or not (config.port) then config.type = nil else config.type = "server" config.err = "" end else config.type = "client" config.err = "" end if not (config.type) then config.type = "unknown" end return config.type, config.err end local function list_conffiles() local configfiles = {} local config = {} local files , errstr, errno = posix.dir ( "/etc/openvpn/" ) if files then for k,v in ipairs(files) do if string.match (v, "^.*conf$") then table.insert ( configfiles, cfe{ name = v } ) end end return configfiles end end -- FIXME: This should probably go in the time/date library -- This function gives diff (in seconds) between 'date' and current time. local function monthabbr_to_num ( month ) local nummonth = "" if (string.lower(month) == "jan") then nummonth = "1" end if (string.lower(month) == "feb") then nummonth = "2" end if (string.lower(month) == "mar") then nummonth = "3" end if (string.lower(month) == "apr") then nummonth = "4" end if (string.lower(month) == "may") then nummonth = "5" end if (string.lower(month) == "jun") then nummonth = "6" end if (string.lower(month) == "jul") then nummonth = "7" end if (string.lower(month) == "aug") then nummonth = "8" end if (string.lower(month) == "sep") then nummonth = "9" end if (string.lower(month) == "oct") then nummonth = "10" end if (string.lower(month) == "nov") then nummonth = "11" end if (string.lower(month) == "dec") then nummonth = "12" end return nummonth end local function month_to_num ( dt ) local strsplit = require("split") -- date is something like "Fri 11 23 10:34:07 2007" local olddate = strsplit(" ",dt) local hour,min,sec = string.match ( rawget(olddate,4), "(%d%d):(%d%d):(%d%d)" ) local olddatetable = { year = rawget(olddate,5), month = rawget(olddate,2), day = rawget(olddate,3), hour = hour, min = min, sec = sec } -- fetch current time local f,err = io.popen("date") currdate = f:read("*l") f:close() local newdate = strsplit(" ",currdate) local hour,min,sec = string.match ( rawget(newdate,4), "(%d%d):(%d%d):(%d%d)" ) local month = monthabbr_to_num(rawget(newdate,2)) local newdatetable = { year = rawget(newdate,6), month = nummonth, day = rawget(newdate,3), hour = hour, min = min, sec = sec } -- return os.difftime(os.time(newdatetable),os.time(olddatetable)) -- Return currdate, olddate, datediff return os.time(newdatetable), os.time(olddatetable), os.difftime(os.time(newdatetable),os.time(olddatetable)) end local function minmax_date ( userdate ) local maxdate = 0 local mindate = 0 local f,err = io.popen("date +%Y ") currdate = f:read("*l") f:close() local year,month,date,hour,min,sec = string.gmatch ( currdate, "(%d%d%d%d)%s+(%w+)%s+(%d%d)" ) -- local month = rawget(systemdate,2) -- local newdatetable = { year = rawget(systemdate,6), month = nummonth, day = rawget(systemdate,3), hour = hour, min = min, sec = sec } -- return os.difftime(os.time(newdatetable),os.time(olddatetable)) -- Return currdate, olddate, datediff return os.time(userdate[2]) end -- ################################################################################ -- PUBLIC FUNCTIONS function clientlist( self, path ) local clientlist = {} local routinglist = {} local datechange = {} local list = {} local f = "" local clientlst = nil local routinglst = nil local strsplit = require("split") if ( path ) then config = config_content ( path ) end if (config.status) then local f = fs.read_file_as_array( config.status ) if ( f ) then for k,v in ipairs(f) do local col = strsplit(",", v) if ( col[1] == "ROUTING TABLE" ) then clientlst = nil end if ( clientlst ) then table.insert(clientlist, { CN=col[1], REALADDR=col[2], BYTESRCV=col[3], BYTESSND=col[4], CONN=col[5] } ) end if ( routinglst ) then table.insert(routinglist, { VIRTADDR=col[1], CN=col[2], REALADDR=col[3], LAST=col[4] } ) table.insert(datechange, { year="2007", month=monthabbr_to_num("may"), day="10", hour="15", min="12", sec="13" } ) end if ( col[1] == "Common Name" ) then clientlst = "YES" end if ( col[1] == "ROUTING TABLE" ) then routinglst = "YES" end if ( col[1] == "GLOBAL STATS" ) then routinglst = nil end end end end -- JOIN 'CLIENT_LIST' and 'ROUTING_LIST' TABLES INTO ONE TABLE for k,v in ipairs(clientlist) do for kk,vv in ipairs(routinglist) do if ( v.CN == vv.CN ) then local maxdatesec, mindatesec = minmax_date(datechange) table.insert(list, { CN=v.CN, REALADDR=v.REALADDR, BYTESRCV=v.BYTESRCV, BYTESSND=v.BYTESSND, VIRTADDR=vv.VIRTADDR, CONN=v.CONN, LAST = LAST } ) end end end local connclients = table.maxn(list) local difftime = maxdatesec -- FIXME: This should probably be modifiead and go into a library!!! return list, connclients, difftime end function clientlistWORKING( self, path ) -- DEBUG -- local path = "openvpn.conf" local clientlist = {} local f = "" local f2 = "" if ( path ) then -- config = config_content ( config.name ) -- config = {} config = config_content ( path ) end if (config.status) then local f = fs.read_file_as_array( config.status ) if ( f ) then for k,v in ipairs(f) do -- The reason for this compex regexp is that I want to filter away the first 2-3 rows -- that doesn't mach this regexp. local clientname,clientip,clientport,bytesreceived,bytessent = string.match ( v, "([^,]*)[,]+([%w]+[.*][%w]+[.*][%w]+[.*][%w]+)[:]([%w]+)[,](%w*)[,](%w*)" ) -- Routing table is now intresting at this moment. So stop reading file. if ( v == "ROUTING TABLE" ) then break end if ( clientname ~= nil ) then table.insert ( clientlist, cfe{ name = clientname, ip = clientip , virtualip = "xXx.xXx.xXx.xXx", port = clientport, received = bytesreceived, sent = bytessent } ) end end end end local connclients = table.maxn(clientlist) return clientlist, connclients end function openvpn_version() local f,error = io.popen("/usr/sbin/openvpn --version") openvpnversion = f:read("*l") f:close() if not (openvpnversion) then openvpnversion = "Not installed!" end return openvpnversion end function get_serverconfig ( self, f ) local serverconfig = {} config = config_content ( f ) -- FIXME: change nex row to clientlist(config.name) local clientlist, connclients, lastupdate = clientlist () local isrunning = is_running ("openvpn", f) -- local isrunning = f -- FIXME: Get status for autostart_status = 'rc_status | grep this process' local autostart_status = "" serverconfig = cfe{ name = f, device = config.dev, log = config.log, verb = config.verb, maxclients = config["max-clients"], clients = connclients, status = isrunning, autostart = autostart_status, dh = config.dh, ca = config.ca, cert = config.cert, key = config.key, tls = config["tls-auth"] , crl = config["crl-verify"], port = config.port, proto = config.proto, loca = config["local"], longname = config.name, lastupdate = lastupdate, remote = config.remote } return serverconfig end function get_logfile( self, path) local logcontent = {} config = config_content ( path ) local logfilecontent = fs.read_file ( config.log ) if not (logfilecontent) then logfilecontent = "File is empty or missing!" end return ( { name = config.log, value = logfilecontent } ) end function get_config( self, path) local logcontent = {} config = config_content ( path ) local logfilecontent = fs.read_file ( config.name ) if not (logfilecontent) then logfilecontent = "File is empty or missing!" end return ( { name = config.name, shortname = path, value = logfilecontent } ) end function get_conflist () local configlist = {} for k,v in pairs(list_conffiles()) do config = config_content ( v.name ) local conf_type, err = check_valid_config ( v.name ) local isrunning = is_running ("openvpn", v.name) local clientlist, connclients = clientlist () table.insert ( configlist, cfe{ name = v.name, type = conf_type, test = config.ca, err = err, status = isrunning, clients = connclients } ) end local countconfigs = table.maxn(configlist) return configlist, countconfigs end get = function (self) return list_conffiles() end