summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--shorewall-config-html.lsp12
-rw-r--r--shorewall-controller.lua179
-rw-r--r--shorewall-html.lsp12
-rw-r--r--shorewall-model.lua264
-rw-r--r--shorewall.menu2
5 files changed, 301 insertions, 168 deletions
diff --git a/shorewall-config-html.lsp b/shorewall-config-html.lsp
index db97aa5..3f8eb8d 100644
--- a/shorewall-config-html.lsp
+++ b/shorewall-config-html.lsp
@@ -60,7 +60,7 @@ displayinfo(myform,tags,"viewonly")
<H3>Parameters</H3>
<DL>
<?
-local tags = { "params_list", "params_list_cmd", }
+local tags = { "params", "params_cmd", }
displayinfo(myform,tags)
?>
</DL>
@@ -68,7 +68,7 @@ displayinfo(myform,tags)
<H3>Interfaces</H3>
<DL>
<?
-local tags = { "interfaces_list", "interfaces_list_cmd", }
+local tags = { "interfaces", "interfaces_cmd", }
displayinfo(myform,tags)
?>
</DL>
@@ -77,15 +77,15 @@ displayinfo(myform,tags)
<H3>Defince zones</H3>
<DL>
<?
-local tags = { "zones_list", "zones_list_cmd", }
+local tags = { "zones", "zones_cmd", }
displayinfo(myform,tags)
?>
</DL>
-<h3>Default policies</h3>
+<h3>Default policy</h3>
<DL>
<?
-local tags = { "policies_list", "policies_list_cmd",}
+local tags = { "policy", "policy_cmd",}
displayinfo(myform,tags)
?>
</DL>
@@ -93,7 +93,7 @@ displayinfo(myform,tags)
<h3>Rules</h3>
<DL>
<?
-local tags = { "rules_list", "rules_list_cmd",}
+local tags = { "rules", "rules_cmd",}
displayinfo(myform,tags)
?>
</DL>
diff --git a/shorewall-controller.lua b/shorewall-controller.lua
index b358e67..dd64ae2 100644
--- a/shorewall-controller.lua
+++ b/shorewall-controller.lua
@@ -61,29 +61,38 @@ end
-- ################################################################################
-- PUBLIC FUNCTIONS
-function save_records(self)
- return {
- edit={},
- option={ script=ENV["SCRIPT_NAME"],
- prefix=self.conf.prefix,
- controller = self.conf.controller,
- action = "save_records",
- link = ENV["SCRIPT_NAME"] .. self.conf.prefix .. self.conf.controller, },
- clientdata=self.clientdata,
- }
-end
-
-function edit_records(self,types,record)
+function edit_records(self,types,record,errormessage)
local recorddetails = {}
local edit = {}
local config=self.model:getconfig()
+
-- Split the record into a table
local recordtable = {}
for word in string.gmatch(record, "%S+") do
table.insert(recordtable, word)
end
+ -- Save info on how the original record looked like
+ edit.orgrecord = cfe({
+ name="orgrecord",
+ label="Original record",
+ value=record,
+ type="hidden",
+ })
+
+ -- Specify a actiontype (this is then used when we make changes)
+ edit.actiontype = cfe({
+ name="actiontype",
+ label="Type of action [add|delete|modify]",
+ type="hidden",
+ })
+ if (record == newrecordtxt) then
+ edit.actiontype.value = "add"
+ else
+ edit.actiontype.value = "modify"
+ end
+
if (types == "params") then
table.insert(edit, cfe({
name=1,
@@ -97,8 +106,7 @@ function edit_records(self,types,record)
-- Display save button
local cmdsave = displaycmdsave()
--- cmdsave.disabled="yes" -- DEBUGGING
--- cmdsave.descr="This button is not yet programmed to work" -- DEBUGGING
+ cmdsave.errtxt=errormessage or ""
-- Display delete button
cmddelete = cfe({ name="cmddelete",
@@ -106,9 +114,6 @@ function edit_records(self,types,record)
value="Delete",
type="submit",
})
- cmddelete.disabled="yes" -- DEBUGGING
- cmddelete.descr="This button is not yet programmed to work" -- DEBUGGING
-
if (types == "interfaces") then
@@ -134,7 +139,7 @@ function edit_records(self,types,record)
edit[fieldnum]["value"] = "-"
end
table.insert(edit[fieldnum]["option"], "-")
- for k,v in pairs(config.zones_list.option or {}) do
+ for k,v in pairs(config.zones.option or {}) do
table.insert(edit[fieldnum]["option"], string.match(v, "^%s*(%S*)"))
end
-- IF the value is not one of the existing options, then warn and add this option.
@@ -456,7 +461,7 @@ function edit_records(self,types,record)
end
-- Add a hidden input where we define which config-file should be modified
- edit.file = cfe({
+ edit.filename = cfe({
label="File to edit",
name="filename",
value=types,
@@ -469,7 +474,7 @@ function edit_records(self,types,record)
option={ script=ENV["SCRIPT_NAME"],
prefix=self.conf.prefix,
controller = self.conf.controller,
- action = "save_records",
+ action = "config",
link = ENV["SCRIPT_NAME"] .. self.conf.prefix .. self.conf.controller, },
cmdsave=cmdsave,
cmddelete=cmddelete,
@@ -482,114 +487,163 @@ function status(self)
end
function config(self)
+
+ -- If we made some changes to a recods... then proceed with the modification
+ local savesuccess, configmessage
+ if (self.clientdata.cmdsave) or (self.clientdata.cmddelete) then
+
+ -- Check to see that user has entered accepted values
+ local inputfields = {}
+ local invalidinputfields
+ if (self.clientdata) then
+ for i=1,#self.clientdata do
+ table.insert(inputfields, self.clientdata[i])
+ if (self.clientdata[i+1]) and (#self.clientdata[i+1] > 0 ) and (#self.clientdata[i] == 0) then
+ configmessage = cfe({errtxt="Skipped fileds should contain '-'"})
+ end
+ end
+ end
+
+ -- What are we going to do with the record...
+ local modify_actiontype = self.clientdata.actiontype or "unknown"
+ if (self.clientdata.cmddelete) then
+ modify_actiontype = "delete"
+ end
+
+
+
+ if not ((configmessage) and (#configmessage.errtxt > 0)) then
+ --Actually change the values
+ savesuccess, configmessage = self.model:modify_config(modify_actiontype,
+ self.clientdata.filename,
+ inputfields,
+ self.clientdata.orgrecord)
+ end
+
+ end
+ -- If we previously made some changes, report this to user
+ if ((self.clientdata.cmdsave) or (self.clientdata.cmddelete)) and not (savesuccess) then
+ self.conf.action = "edit_records"
+ self.conf.type = "redir"
+ return edit_records(self,self.clientdata.filename, self.clientdata.orgrecord,tostring((configmessage.errtxt or "")))
+ end
+
local config=self.model:getconfig()
local status=self.model.getstatus()
-- Add a [New] record to the options
- table.insert(config.interfaces_list.option, newrecordtxt)
- table.insert(config.zones_list.option, newrecordtxt)
- table.insert(config.policies_list.option, newrecordtxt)
- table.insert(config.rules_list.option, newrecordtxt)
- table.insert(config.params_list.option, newrecordtxt)
+ table.insert(config.interfaces.option, newrecordtxt)
+ table.insert(config.zones.option, newrecordtxt)
+ table.insert(config.policy.option, newrecordtxt)
+ table.insert(config.rules.option, newrecordtxt)
+ table.insert(config.params.option, newrecordtxt)
-- Add button
- config.params_list_cmd = cfe ({
- name="params_list_cmd",
+ config.params_cmd = cfe ({
+ name="params_cmd",
label="Edit above record",
value="Edit",
type="submit",
-- disabled="yes",
})
- config.params_list_cmd.descr="Mark a item in above list before pressing [" .. config.params_list_cmd.value .. "]"
+ config.params_cmd.descr="Mark a item in above list before pressing [" .. config.params_cmd.value .. "]"
-- Add button
- config.interfaces_list_cmd = cfe ({
- name="interfaces_list_cmd",
+ config.interfaces_cmd = cfe ({
+ name="interfaces_cmd",
label="Edit above record",
value="Edit",
type="submit",
-- disabled="yes",
})
- config.interfaces_list_cmd.descr="Mark a item in above list before pressing [" .. config.interfaces_list_cmd.value .. "]"
+ config.interfaces_cmd.descr="Mark a item in above list before pressing [" .. config.interfaces_cmd.value .. "]"
-- Add button
- config.zones_list_cmd = cfe ({
- name="zones_list_cmd",
+ config.zones_cmd = cfe ({
+ name="zones_cmd",
label="Edit above record",
value="Edit",
type="submit",
-- disabled="yes",
})
- config.zones_list_cmd.descr="Mark a item in above list before pressing [" .. config.zones_list_cmd.value .. "]"
+ config.zones_cmd.descr="Mark a item in above list before pressing [" .. config.zones_cmd.value .. "]"
-- Add button
- config.policies_list_cmd = cfe ({
- name="policies_list_cmd",
+ config.policy_cmd = cfe ({
+ name="policy_cmd",
label="Edit above record",
value="Edit",
type="submit",
-- disabled="yes",
})
- config.policies_list_cmd.descr="Mark a item in above list before pressing [" .. config.policies_list_cmd.value .. "]"
+ config.policy_cmd.descr="Mark a item in above list before pressing [" .. config.policy_cmd.value .. "]"
-- Add button
- config.rules_list_cmd = cfe ({
- name="rules_list_cmd",
+ config.rules_cmd = cfe ({
+ name="rules_cmd",
label="Edit above record",
value="Edit",
type="submit",
-- disabled="yes",
-- errtxt="This button is not yet programmed!",
})
- config.rules_list_cmd.descr="Mark a item in above list before pressing [" .. config.rules_list_cmd.value .. "]"
+ config.rules_cmd.descr="Mark a item in above list before pressing [" .. config.rules_cmd.value .. "]"
-- Management buttons
-- Display management buttons
local management = displaycmdmanagement(disablestart,disablestop,disablerestart)
-- Redirect if button is pressed
- if (self.clientdata.params_list_cmd) and (self.clientdata.params_list) then
+ if (self.clientdata.params_cmd) and (self.clientdata.params) then
self.conf.action = "edit_records"
self.conf.type = "redir"
- return edit_records(self,"params", self.clientdata.params_list)
- elseif (self.clientdata.params_list_cmd) and not (self.clientdata.params_list) then
- config.params_list_cmd.errtxt = "You need to specify a record to edit!"
+ return edit_records(self,"params", self.clientdata.params)
+ elseif (self.clientdata.params_cmd) and not (self.clientdata.params) then
+ config.params_cmd.errtxt = "You need to specify a record to edit!"
end
-- Redirect if button is pressed
- if (self.clientdata.interfaces_list_cmd) and (self.clientdata.interfaces_list) then
+ if (self.clientdata.interfaces_cmd) and (self.clientdata.interfaces) then
self.conf.action = "edit_records"
self.conf.type = "redir"
- return edit_records(self,"interfaces", self.clientdata.interfaces_list)
- elseif (self.clientdata.interfaces_list_cmd) and not (self.clientdata.interfaces_list) then
- config.interfaces_list_cmd.errtxt = "You need to specify a record to edit!"
+ return edit_records(self,"interfaces", self.clientdata.interfaces)
+ elseif (self.clientdata.interfaces_cmd) and not (self.clientdata.interfaces) then
+ config.interfaces_cmd.errtxt = "You need to specify a record to edit!"
end
-- Redirect if button is pressed
- if (self.clientdata.zones_list_cmd) and (self.clientdata.zones_list) then
+ if (self.clientdata.zones_cmd) and (self.clientdata.zones) then
self.conf.action = "edit_records"
self.conf.type = "redir"
- return edit_records(self,"zones", self.clientdata.zones_list)
- elseif (self.clientdata.zones_list_cmd) and not (self.clientdata.zones_list) then
- config.zones_list_cmd.errtxt = "You need to specify a record to edit!"
+ return edit_records(self,"zones", self.clientdata.zones)
+ elseif (self.clientdata.zones_cmd) and not (self.clientdata.zones) then
+ config.zones_cmd.errtxt = "You need to specify a record to edit!"
end
-- Redirect if button is pressed
- if (self.clientdata.policies_list_cmd) and (self.clientdata.policies_list) then
+ if (self.clientdata.policy_cmd) and (self.clientdata.policy) then
self.conf.action = "edit_records"
self.conf.type = "redir"
- return edit_records(self,"policy", self.clientdata.policies_list)
- elseif (self.clientdata.policies_list_cmd) and not (self.clientdata.policies_list) then
- config.policies_list_cmd.errtxt = "You need to specify a record to edit!"
+ return edit_records(self,"policy", self.clientdata.policy)
+ elseif (self.clientdata.policy_cmd) and not (self.clientdata.policy) then
+ config.policy_cmd.errtxt = "You need to specify a record to edit!"
end
-- Redirect if button is pressed
- if (self.clientdata.rules_list_cmd) and (self.clientdata.rules_list) then
+ if (self.clientdata.rules_cmd) and (self.clientdata.rules) then
self.conf.action = "edit_records"
self.conf.type = "redir"
- return edit_records(self,"rules", self.clientdata.rules_list)
- elseif (self.clientdata.rules_list_cmd) and not (self.clientdata.rules_list) then
- config.rules_list_cmd.errtxt = "You need to specify a record to edit!"
+ return edit_records(self,"rules", self.clientdata.rules)
+ elseif (self.clientdata.rules_cmd) and not (self.clientdata.rules) then
+ config.rules_cmd.errtxt = "You need to specify a record to edit!"
+ end
+
+ -- If we previously made some changes, report this to user
+ if ((self.clientdata.cmdsave) or (self.clientdata.cmddelete)) and (savesuccess) and (configmessage) and (configmessage.descr) then
+ local reporttobutton = self.clientdata.filename .. "_cmd"
+ if (config[reporttobutton]) then
+ config[reporttobutton]["descr"] = tostring(configmessage.descr)
+ end
end
return {
@@ -602,7 +656,8 @@ function config(self)
action = "expert",
link = ENV["SCRIPT_NAME"] .. self.conf.prefix .. self.conf.controller, },
clientdata=clientdata,
-
+ savesuccess=savesuccess,
+ configmessage=configmessage,
}
end
diff --git a/shorewall-html.lsp b/shorewall-html.lsp
index 1672808..7f99407 100644
--- a/shorewall-html.lsp
+++ b/shorewall-html.lsp
@@ -78,7 +78,15 @@ displayinfo(myform,tags)
?>
<? -- Add the field that holds the filename
-local myform = form.edit.file
+local myform = form.edit.filename
+if (type(myform) == "table") then
+ io.write(html.form[myform.type](myform))
+end
+local myform = form.edit.orgrecord
+if (type(myform) == "table") then
+ io.write(html.form[myform.type](myform))
+end
+local myform = form.edit.actiontype
if (type(myform) == "table") then
io.write(html.form[myform.type](myform))
end
@@ -89,7 +97,7 @@ end
</form>
<?
----[[ DEBUG INFORMATION
+--[[ DEBUG INFORMATION
io.write("<H1>DEBUGGING</H1><span style='color:red'><H2>DEBUG INFO: CFE</H2>")
io.write(html.cfe_unpack(form))
io.write("</span>")
diff --git a/shorewall-model.lua b/shorewall-model.lua
index 0375b06..e9ca529 100644
--- a/shorewall-model.lua
+++ b/shorewall-model.lua
@@ -48,9 +48,160 @@ local function read_config(file)
end
return output
end
+
+---[[
+local function addremove_config( addremove, file, value, orgvalue )
+ filepath = baseurl .. file
+ local cmdoutput
+
+ -- Check if we are about to change a valid filename
+ local isvalidfile
+ for k,v in pairs(getfilelist()) do
+ isvalidfile = true
+ if (v.value == filepath) then
+ break
+ end
+ isvalidfile = false
+ end
+ if not (fs.is_file(filepath)) or not (isvalidfile) then
+ return false, cfe({
+ name="model:addremove_config()",
+ errtxt="'" .. filepath .. "' is not a valid file!",
+ })
+ end
+
+ if not (type(value) == "table") then
+ return false, cfe({
+ name="model:addremove_config()",
+ errtxt="Value should come as an array!",
+ })
+ end
+
+ local filecontentarray = fs.read_file_as_array(filepath)
+
+ if (addremove == "delete" ) then
+ local modifyrow
+ local orgrecordtable = {}
+ for word in string.gmatch(orgvalue, "%S+") do
+ table.insert(orgrecordtable, word)
+ end
+ for i=1, #filecontentarray do
+ local recordtable = {}
+ for word in string.gmatch(filecontentarray[i], "%S+") do
+ table.insert(recordtable, word)
+ end
+
+ if (table.concat(recordtable) == table.concat(orgrecordtable)) then
+ modifyrow = i
+ end
+ end
+
+ if (tonumber(modifyrow)) then
+ table.remove(filecontentarray, modifyrow)
+ fs.write_file(filepath, table.concat(filecontentarray, "\n"))
+ return true, cfe({
+ name="model:addremove_config()",
+ descr="* Record was successfully deleted!",
+ })
+ else
+ return false, cfe({
+ name="model:addremove_config()",
+ errtxt="Record was not deleted!" ..
+"<BR>orgvalue:" .. tostring(orgvalue) ..
+"<BR>modifyrow:" .. tostring(modifyrow) ..
+"<BR>orgrecordtable:" .. table.concat(orgrecordtable, ";") ..
+"<BR>file:" .. tostring(file) ..
+"<BR>filecontentarray:" .. table.concat(filecontentarray, ";") ..
+""
+ ,
+ })
+ end
+
+ elseif (addremove == "add" ) then
+ --Check if such record already exists
+ for k,v in pairs(filecontentarray) do
+ if not string.find ( v, "^[;#].*" ) then
+ local recordtable = {}
+ for word in string.gmatch(v, "%S+") do
+ table.insert(recordtable, word)
+ end
+ if (table.concat(recordtable) == table.concat(value)) then
+ return false, cfe({
+ name="model:addremove_config()",
+ errtxt="The config already holds this kind of config!",
+ })
+ end
+ end
+ end
+
+ table.insert(filecontentarray, (#filecontentarray), table.concat(value, "\t"))
+ fs.write_file(filepath, table.concat(filecontentarray, "\n"))
+ return true, cfe({
+ name="model:addremove_config()",
+ descr="* Record was successfully added!",
+ })
+
+ elseif (addremove == "modify" ) then
+ local modifyrow
+ local orgrecordtable = {}
+ for word in string.gmatch(orgvalue, "%S+") do
+ table.insert(orgrecordtable, word)
+ end
+ for i=1, #filecontentarray do
+ local recordtable = {}
+ for word in string.gmatch(filecontentarray[i], "%S+") do
+ table.insert(recordtable, word)
+ end
+
+ if (table.concat(recordtable) == table.concat(orgrecordtable)) then
+ modifyrow = i
+ end
+ end
+
+ if (tonumber(modifyrow)) then
+ table.remove(filecontentarray, modifyrow)
+ table.insert(filecontentarray, modifyrow, table.concat(value, "\t"))
+ fs.write_file(filepath, table.concat(filecontentarray, "\n"))
+ return true, cfe({
+ name="model:addremove_config()",
+ descr="* Record was successfully modified!",
+ })
+ else
+ return false, cfe({
+ name="model:addremove_config()",
+ errtxt="Record was not modified!"..
+"<BR>orgvalue:" .. tostring(orgvalue) ..
+"<BR>modifyrow:" .. tostring(modifyrow) ..
+"<BR>orgrecordtable:" .. table.concat(orgrecordtable, ";") ..
+"<BR>file:" .. tostring(file) ..
+"<BR>filecontentarray:" .. table.concat(filecontentarray, ";") ..
+""
+,
+ })
+ end
+
+ else
+ return false, cfe({
+ name="model:addremove_config()",
+ errtxt="Wrong usage of this function! Available options are [add|delete|modify]. You chose '" .. addremove .. "'",
+ })
+ end
+
+ return false, cfe({
+ name="model:addremove_config()",
+ errtxt="Something went wrong!",
+ debug=value,
+ })
+end
+--]]
+
-- ################################################################################
-- PUBLIC FUNCTIONS
+function modify_config(self, addremove, file, value, orgvalue )
+ return addremove_config(addremove, file, value, orgvalue )
+end
+
-- action should be a CFE
function startstop_service ( self, action )
local cmd = action.value
@@ -65,45 +216,45 @@ end
function getconfig()
local config = {}
- config.params_list = cfe({
- name = "params_list",
+ config.params = cfe({
+ name = "params",
label="List of parameters",
type="select",
option=read_config("params"),
})
- config.params_list.size=#config.params_list.option + 1
+ config.params.size=#config.params.option + 1
- config.interfaces_list = cfe({
- name = "interfaces_list",
+ config.interfaces = cfe({
+ name = "interfaces",
label="List of interfaces",
type="select",
option=read_config("interfaces"),
})
- config.interfaces_list.size=#config.interfaces_list.option + 1
+ config.interfaces.size=#config.interfaces.option + 1
- config.zones_list = cfe({
- name = "zones_list",
+ config.zones = cfe({
+ name = "zones",
label="List of zones",
type="select",
option=read_config("zones"),
})
- config.zones_list.size=#config.zones_list.option + 1
+ config.zones.size=#config.zones.option + 1
- config.policies_list = cfe({
- name = "policies_list",
- label="List of policies",
+ config.policy = cfe({
+ name = "policy",
+ label="List of policy",
type="select",
option=read_config("policy"),
})
- config.policies_list.size=#config.policies_list.option + 1
+ config.policy.size=#config.policy.option + 1
- config.rules_list = cfe({
- name = "rules_list",
+ config.rules = cfe({
+ name = "rules",
label="List of rules",
type="select",
option=read_config("rules"),
})
- config.rules_list.size=#config.rules_list.option + 1
+ config.rules.size=#config.rules.option + 1
return config
@@ -228,87 +379,6 @@ function getfiledetails(self,search)
return file
end
-
--- IMPORTANT! This function is a exception! It's not fed with CFE's
--- Parameter should be one of the ones defined in the variable 'variabletranslator'.
--- value should be whatever the new value should be.
-function setconfigs(self,parameter,value)
- -- Set variables
- local variable = "SYSLOGD_OPTS"
- local variabletranslator = ({
- logfile = "-O",
- loglevel = "-l",
- smallerlogs = "-S",
- maxsize = "-s",
- numrotate = "-b",
- localandnetworklog = "-L",
- remotelogging = "-R",
- })
- cmdparameter = variabletranslator[parameter]
-
- -- Report a error if someone tryes to use a invalid parameter
- if not (cmdparameter) then
- local availablevariables = ""
- for k,v in pairs(variabletranslator) do
- availablevariables = k .. ", " .. availablevariables
- end
- parameter = parameter or ""
- return false, cfe({
- name="syslog.model.setconfigs()",
- errtxt="'" .. parameter .. "' is not a valid parameter!\nValid options are: " .. availablevariables,
- })
- end
-
- --TODO: Validate so that user cant add values with '-' (could cause major breakage next time you do getopts)
-
- -- This config-file only accepts one type of parameters (report error if someone uses wrong parameter)
- if not (string.find(cmdparameter, "-%a$")) then
- return false, cfe({
- name="syslog.model.setconfigs()",
- errtxt="Parameter must be formated '-a' (where a is one upper/lowercase letter [a-z])",
- })
- end
-
- -- Validate userinput (if valid path/filename)
- if (value) and (cmdparameter == "-O") then
- local cmdresult, cmdmessage = validator.is_valid_filename(value, "/var/log" )
- if not (cmdresult) then
- return false, cfe({
- name="syslog.model.setconfigs()",
- errtxt=cmdmessage,
- })
- end
- end
-
- -- Validate userinput (Has the user entered a valid hostname and/or port)
- if (value) and (cmdparameter == "-R") then
- local hostport = format.string_to_table(value, ":")
- local host = hostport[1]
- local port = hostport[2]
- if (port) and not (validator.is_port(port)) then
- return false, cfe({
- name="syslog.model.setconfigs.getopts.setoptsinfile()",
- errtxt="You entered '" .. tostring(port) .. "' as port - This is not valid!",
- })
- end
- end
-
- -- Set/Unset checkbox variables
- if (value) and ((cmdparameter == "-S") or (cmdparameter == "-L")) then value = "" end
-
- local cmdresult, cmdmessage, cmderror = getopts.setoptsinfile(configfile,variable,cmdparameter,value)
- if (cmderror) then
- return false, cfe({
- name="syslog.model.setconfigs.getopts.setoptsinfile()",
- errtxt=cmderror,
- })
- end
- return true, cfe({
- name="syslog.model.setconfigs()",
- value=cmdmessage,
- })
-end
-
-- modifications should be a CFE
function updatefilecontent (self, filetochange)
local path = nil
diff --git a/shorewall.menu b/shorewall.menu
index 557f401..fac6de9 100644
--- a/shorewall.menu
+++ b/shorewall.menu
@@ -1,7 +1,7 @@
#CAT GROUP/DESC TAB ACTION
Networking 40Firewall Status status
+Networking 40Firewall Config config
Networking 40Firewall Expert expert
Networking 40Firewall Check check
Networking 40Firewall Logfile logfile
-Networking 40Firewall Config_(Example) config