Merge pull request #1705 from Mushoz/add-igmp-snooping
[project/luci.git] / modules / luci-base / luasrc / sys / iptparser.lua
index d823633..7ff665e 100644 (file)
@@ -1,7 +1,7 @@
 --[[
 
 Iptables parser and query library
-(c) 2008-2009 Jo-Philipp Wich <xm@leipzig.freifunk.net>
+(c) 2008-2009 Jo-Philipp Wich <jow@openwrt.org>
 (c) 2008-2009 Steven Barth <steven@midlink.org>
 
 Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,38 +19,55 @@ luci.util   = require "luci.util"
 luci.sys    = require "luci.sys"
 luci.ip     = require "luci.ip"
 
+local pcall = pcall
+local io = require "io"
 local tonumber, ipairs, table = tonumber, ipairs, table
 
---- LuCI iptables parser and query library
--- @cstyle     instance
 module("luci.sys.iptparser")
 
---- Create a new iptables parser object.
--- @class      function
--- @name       IptParser
--- @param      family  Number specifying the address family. 4 for IPv4, 6 for IPv6
--- @return     IptParser instance
 IptParser = luci.util.class()
 
 function IptParser.__init__( self, family )
        self._family = (tonumber(family) == 6) and 6 or 4
        self._rules  = { }
        self._chains = { }
+       self._tables = { }
+
+       local t = self._tables
+       local s = self:_supported_tables(self._family)
+
+       if s.filter then t[#t+1] = "filter" end
+       if s.nat    then t[#t+1] = "nat"    end
+       if s.mangle then t[#t+1] = "mangle" end
+       if s.raw    then t[#t+1] = "raw"    end
 
        if self._family == 4 then
                self._nulladdr = "0.0.0.0/0"
-               self._tables   = { "filter", "nat", "mangle", "raw" }
                self._command  = "iptables -t %s --line-numbers -nxvL"
        else
                self._nulladdr = "::/0"
-               self._tables   = { "filter", "mangle", "raw" }
                self._command  = "ip6tables -t %s --line-numbers -nxvL"
        end
 
        self:_parse_rules()
 end
 
---- Find all firewall rules that match the given criteria. Expects a table with
+function IptParser._supported_tables( self, family )
+       local tables = { }
+       local ok, lines = pcall(io.lines,
+               (family == 6) and "/proc/net/ip6_tables_names"
+                              or "/proc/net/ip_tables_names")
+
+       if ok and lines then
+               local line
+               for line in lines do
+                       tables[line] = true
+               end
+       end
+
+       return tables
+end
+
 -- search criteria as only argument. If args is nil or an empty table then all
 -- rules will be returned.
 --
@@ -108,8 +125,6 @@ end
 -- 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 )
 
        local args = args or { }
@@ -205,9 +220,7 @@ function IptParser.find( self, args )
 end
 
 
---- Rebuild the internal lookup table, for example when rules have changed
 -- through external commands.
--- @return     nothing
 function IptParser.resync( self )
        self._rules = { }
        self._chain = nil
@@ -215,16 +228,11 @@ function IptParser.resync( self )
 end
 
 
---- Find the names of all tables.
--- @return             Table of table names.
 function IptParser.tables( self )
        return self._tables
 end
 
 
---- Find the names of all chains within the given table name.
--- @param table        String containing the table name
--- @return             Table of chain names in the order they occur.
 function IptParser.chains( self, table )
        local lookup = { }
        local chains = { }
@@ -238,19 +246,12 @@ function IptParser.chains( self, table )
 end
 
 
---- Return the given firewall chain within the given table name.
--- @param table        String containing the table name
--- @param chain        String containing the chain name
--- @return             Table containing the fields "policy", "packets", "bytes"
 --                             and "rules". The "rules" field is a table of rule tables.
 function IptParser.chain( self, table, chain )
        return self._chains[table:lower()] and self._chains[table:lower()][chain]
 end
 
 
---- Test whether the given target points to a custom chain.
--- @param target       String containing the target action
--- @return                     Boolean indicating whether target is a custom chain.
 function IptParser.is_custom_target( self, target )
        for _, r in ipairs(self._rules) do
                if r.chain == target then