libs/sys/iptparser:

- rewrite inline documentation to luadoc
	- utilize luci.ip for source and destination comparisations
This commit is contained in:
Jo-Philipp Wich 2009-02-08 00:45:13 +00:00
parent 15029e4279
commit a9f58b0c52

View file

@ -1,7 +1,8 @@
--[[ --[[
LuCI - Iptables parser and query library
Copyright 2008 Jo-Philipp Wich <freifunk@wwsnet.net> Iptables parser and query library
(c) 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
(c) 2008 Steven Barth <steven@midlink.org>
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -9,89 +10,99 @@ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
$Id$ $Id$
]]-- ]]--
module("luci.sys.iptparser", package.seeall) local luci = {}
require("luci.util") luci.util = require "luci.util"
luci.sys = require "luci.sys"
luci.ip = require "luci.ip"
--- LuCI iptables parser and query library
-- @cstyle instance
module("luci.sys.iptparser")
--- Create a new iptables parser object.
-- @class function
-- @name IptParser
-- @return IptParser instance
IptParser = luci.util.class() IptParser = luci.util.class()
--[[
IptParser.__init__( ... )
The class constructor, initializes the internal lookup table.
]]--
function IptParser.__init__( self, ... ) function IptParser.__init__( self, ... )
self._rules = { } self._rules = { }
self._chain = nil self._chain = nil
self:_parse_rules() self:_parse_rules()
end end
--- Find all firewall rules that match the given criteria. Expects a table with
--[[ -- search criteria as only argument. If args is nil or an empty table then all
IptParser.find( args ) -- rules will be returned.
--
Find all firewall rules that match the given criteria. Expects a table with search criteria as only argument. -- The following keys in the args table are recognized:
If args is nil or an empty table then all rules will be returned. -- <ul>
-- <li> table - Match rules that are located within the given table
The following keys in the args table are recognized: -- <li> chain - Match rules that are located within the given chain
-- <li> target - Match rules with the given target
- table Match rules that are located within the given table -- <li> protocol - Match rules that match the given protocol, rules with
- chain Match rules that are located within the given chain -- protocol "all" are always matched
- target Match rules with the given target -- <li> source - Match rules with the given source, rules with source
- protocol Match rules that match the given protocol, rules with protocol "all" are always matched -- "0.0.0.0/0" are always matched
- source Match rules with the given source, rules with source "0.0.0.0/0" are always matched -- <li> destination - Match rules with the given destination, rules with
- destination Match rules with the given destination, rules with destination "0.0.0.0/0" are always matched -- destination "0.0.0.0/0" are always matched
- inputif Match rules with the given input interface, rules with input interface "*" (=all) are always matched -- <li> inputif - Match rules with the given input interface, rules
- outputif Match rules with the given output interface, rules with output interface "*" (=all) are always matched -- with input interface "*" (=all) are always matched
- flags Match rules that match the given flags, current supported values are "-f" (--fragment) and "!f" (! --fragment) -- <li> outputif - Match rules with the given output interface, rules
- options Match rules containing all given options -- with output interface "*" (=all) are always matched
-- <li> flags - Match rules that match the given flags, current
The return value is a list of tables representing the matched rules. -- supported values are "-f" (--fragment)
Each rule table contains the following fields: -- and "!f" (! --fragment)
-- <li> options - Match rules containing all given options
- index The index number of the rule -- </ul>
- table The table where the rule is located, can be one of "filter", "nat" or "mangle" -- The return value is a list of tables representing the matched rules.
- chain The chain where the rule is located, e.g. "INPUT" or "postrouting_wan" -- Each rule table contains the following fields:
- target The rule target, e.g. "REJECT" or "DROP" -- <ul>
- protocol The matching protocols, e.g. "all" or "tcp" -- <li> index - The index number of the rule
- flags Special rule options ("--", "-f" or "!f") -- <li> table - The table where the rule is located, can be one
- inputif Input interface of the rule, e.g. "eth0.0" or "*" for all interfaces -- of "filter", "nat" or "mangle"
- outputif Output interface of the rule, e.g. "eth0.0" or "*" for all interfaces -- <li> chain - The chain where the rule is located, e.g. "INPUT"
- source The source ip range, e.g. "0.0.0.0/0" -- or "postrouting_wan"
- destination The destination ip range, e.g. "0.0.0.0/0" -- <li> target - The rule target, e.g. "REJECT" or "DROP"
- options A list of specific options of the rule, e.g. { "reject-with", "tcp-reset" } -- <li> protocol The matching protocols, e.g. "all" or "tcp"
- packets The number of packets matched by the rule -- <li> flags - Special rule options ("--", "-f" or "!f")
- bytes The number of total bytes matched by the rule -- <li> inputif - Input interface of the rule, e.g. "eth0.0"
-- or "*" for all interfaces
Example: -- <li> outputif - Output interface of the rule,e.g. "eth0.0"
-- or "*" for all interfaces
ip = luci.sys.iptparser.IptParser() -- <li> source - The source ip range, e.g. "0.0.0.0/0"
result = ip.find( { -- <li> destination - The destination ip range, e.g. "0.0.0.0/0"
target="REJECT", -- <li> options - A list of specific options of the rule,
protocol="tcp", -- e.g. { "reject-with", "tcp-reset" }
options={ "reject-with", "tcp-reset" } -- <li> packets - The number of packets matched by the rule
} ) -- <li> bytes - The number of total bytes matched by the rule
-- </ul>
This will match all rules with target "-j REJECT", protocol "-p tcp" (or "-p all") and the option "--reject-with tcp-reset". -- Example:
-- <pre>
]]-- -- ip = luci.sys.iptparser.IptParser()
-- result = ip.find( {
-- target="REJECT",
-- protocol="tcp",
-- options={ "reject-with", "tcp-reset" }
-- } )
-- </pre>
-- This will match all rules with target "-j REJECT",
-- protocol "-p tcp" (or "-p all")
-- and the option "--reject-with tcp-reset".
-- @params args Table containing the search arguments (optional)
-- @return Table of matching rule tables
function IptParser.find( self, args ) function IptParser.find( self, args )
local args = args or { } local args = args or { }
local rv = { } local rv = { }
args.source = args.source and luci.ip.IPv4(args.source)
args.destination = args.destination and luci.ip.IPv4(args.destination)
for i, rule in ipairs(self._rules) do for i, rule in ipairs(self._rules) do
local match = true local match = true
@ -101,51 +112,74 @@ function IptParser.find( self, args )
end end
-- match chain -- match chain
if not ( match == true and ( not args.chain or args.chain == rule.chain ) ) then if not ( match == true and (
not args.chain or args.chain == rule.chain
) ) then
match = false match = false
end end
-- match target -- match target
if not ( match == true and ( not args.target or args.target == rule.target ) ) then if not ( match == true and (
not args.target or args.target:upper() == rule.target
) ) then
match = false match = false
end end
-- match protocol -- match protocol
if not ( match == true and ( not args.protocol or rule.protocol == "all" or args.protocol == rule.protocol ) ) then if not ( match == true and (
not args.protocol or rule.protocol == "all" or
args.protocol:lower() == rule.protocol
) ) then
match = false match = false
end end
-- match source (XXX: implement ipcalc stuff so that 192.168.1.0/24 matches 0.0.0.0/0 etc.) -- match source
if not ( match == true and ( not args.source or rule.source == "0.0.0.0/0" or rule.source == args.source ) ) then if not ( match == true and (
not args.source or rule.source == "0.0.0.0/0" or
luci.ip.IPv4(rule.source):contains(args.source)
) ) then
match = false match = false
end end
-- match destination (XXX: implement ipcalc stuff so that 192.168.1.0/24 matches 0.0.0.0/0 etc.) -- match destination
if not ( match == true and ( not args.destination or rule.destination == "0.0.0.0/0" or rule.destination == args.destination ) ) then if not ( match == true and (
not args.destination or rule.destination == "0.0.0.0/0" or
luci.ip.IPv4(rule.destination):contains(args.destination)
) ) then
match = false match = false
end end
-- match input interface -- match input interface
if not ( match == true and ( not args.inputif or rule.inputif == "*" or args.inputif == rule.inputif ) ) then if not ( match == true and (
not args.inputif or rule.inputif == "*" or
args.inputif == rule.inputif
) ) then
match = false match = false
end end
-- match output interface -- match output interface
if not ( match == true and ( not args.outputif or rule.outputif == "*" or args.outputif == rule.outputif ) ) then if not ( match == true and (
not args.outputif or rule.outputif == "*" or
args.outputif == rule.outputif
) ) then
match = false match = false
end end
-- match flags (the "opt" column) -- match flags (the "opt" column)
if not ( match == true and ( not args.flags or rule.flags == args.flags ) ) then if not ( match == true and (
not args.flags or rule.flags == args.flags
) ) then
match = false match = false
end end
-- match specific options -- match specific options
if not ( match == true and ( not args.options or self:_match_options( rule.options, args.options ) ) ) then if not ( match == true and (
not args.options or
self:_match_options( rule.options, args.options )
) ) then
match = false match = false
end end
-- insert match -- insert match
if match == true then if match == true then
table.insert( rv, rule ) table.insert( rv, rule )
@ -156,12 +190,9 @@ function IptParser.find( self, args )
end end
--[[ --- Rebuild the internal lookup table, for example when rules have changed
IptParser.resync() -- through external commands.
-- @return nothing
Rebuild the internal lookup table, for example when rules have changed through external commands.
]]--
function IptParser.resync( self ) function IptParser.resync( self )
self._rules = { } self._rules = { }
self._chain = nil self._chain = nil
@ -169,12 +200,7 @@ function IptParser.resync( self )
end end
--[[ -- [internal] Parse iptables output from all tables.
IptParser._parse_rules()
[internal] Parse iptables output from all tables.
]]--
function IptParser._parse_rules( self ) function IptParser._parse_rules( self )
for i, tbl in ipairs({ "filter", "nat", "mangle" }) do for i, tbl in ipairs({ "filter", "nat", "mangle" }) do
@ -188,7 +214,7 @@ function IptParser._parse_rules( self )
else else
if rule:find("%d") == 1 then if rule:find("%d") == 1 then
local rule_parts = luci.util.split( rule, "%s+", nil, true ) local rule_partmays = luci.util.split( rule, "%s+", nil, true )
local rule_details = { } local rule_details = { }
rule_details["table"] = tbl rule_details["table"] = tbl
@ -219,12 +245,8 @@ function IptParser._parse_rules( self )
end end
--[[ -- [internal] Return true if optlist1 contains all elements of optlist 2.
IptParser._match_options( optlist1, optlist2 ) -- Return false in all other cases.
[internal] Return true if optlist1 contains all elements of optlist2. Return false in all other cases.
]]--
function IptParser._match_options( self, o1, o2 ) function IptParser._match_options( self, o1, o2 )
-- construct a hashtable of first options list to speed up lookups -- construct a hashtable of first options list to speed up lookups