-- -- (C) 2020-22 - ntop.org -- local dirs = ntop.getDirs() package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path package.path = dirs.installdir .. "/scripts/lua/modules/pools/?.lua;" .. package.path require "lua_utils" -- ############################################## local radius_handler = {} local session_id_length = 32 local redis_accounting_key = "ntopng.radius.accounting.%s" -- ############################################## ---@brief Handles the Radius accounting start request ---@param name string, used to identify the the user logged in ---@param username string, used to login the account to radius ---@param password string, used to login the account to radius ---@return boolean, true if the accounting start went well, false otherwise function radius_handler.accountingStart(name, username, password) if not radius_handler.isAccountingEnabled() then return true end math.randomseed(os.time()) local session_id = tostring(math.random(100000000000000000, 999999999999999999)) local accounting_started = interface.radiusAccountingStart(name --[[ MAC Address ]] , session_id) if accounting_started then local json = require("dkjson") local key = string.format(redis_accounting_key, name) local user_data = { name = name, username = username, password = password, session_id = session_id } ntop.setCache(key, json.encode(user_data)) end return accounting_started end -- ############################################## -- @brief Handles the Radius accounting stop request ---@param name string, used to check if name is an accounting going on ---@return boolean, true if the accounting went well, false otherwise and the stop was called function radius_handler.accountingStop(name, bytes_sent, bytes_rcvd, packets_sent, packets_rcvd) if not radius_handler.isAccountingEnabled() then return true end local is_accounting_on, user_data = radius_handler.isAccountingRequested(name) if is_accounting_on then interface.radiusAccountingStop(name --[[ MAC Address ]] , user_data.session_id, bytes_sent, bytes_rcvd, packets_sent, packets_rcvd) ntop.delCache(string.format(redis_accounting_key, name)) end end -- ############################################## -- @brief Execute the accounting update if the name has to be updated ---@param name string, used to check if name is an accounting going on ---@return boolean, true if the accounting went well, false otherwise and the stop was called function radius_handler.accountingUpdate(name, info) if not radius_handler.isAccountingEnabled() then return true end local is_accounting_on, user_data = radius_handler.isAccountingRequested(name) local res = true if is_accounting_on then local bytes_sent = info["bytes.sent"] local bytes_rcvd = info["bytes.rcvd"] local packets_sent = info["packets.sent"] local packets_rcvd = info["packets.rcvd"] local is_accounting_ok = interface.radiusAccountingUpdate(name, user_data.session_id, user_data.username, user_data.password, bytes_sent, bytes_rcvd, packets_sent, packets_rcvd) if not is_accounting_ok then -- An accounting stop has to be sent, the allowed data for name -- are expired, requesting stop radius_handler.accountingStop(name, bytes_sent, bytes_rcvd, packets_sent, packets_rcvd) res = false end end return res end -- ############################################## -- @brief Check if name has an accounting going on ---@param name string, used to check if name is an accounting going on ---@return boolean, in case the accounting is up or not ---@return table, containing the user data in case an accounting is up function radius_handler.isAccountingRequested(name) local key = string.format(redis_accounting_key, name) local user_data = ntop.getCache(key) if not isEmptyString(user_data) then local json = require("dkjson") return true, json.decode(user_data) end return false, nil end -- ############################################## function radius_handler.isAccountingEnabled() local accounting_enabled = ntop.getPref("ntopng.prefs.radius.accounting_enabled") if (not accounting_enabled) or (isEmptyString(accounting_enabled) or (accounting_enabled == "0")) then return false end return true end -- ############################################## return radius_handler -- ##############################################