log.lua 2.83 KB
Newer Older
1 2
--[[
Packet logging module for Alpine Wall
3
Copyright (C) 2012-2018 Kaarle Ritvanen
4 5 6 7
See LICENSE file for license details
]]--


8
local resolvelist = require('awall.host').resolvelist
9

10
local model = require('awall.model')
11 12
local class = model.class

13
local combinations = require('awall.optfrag').combinations
14
local util = require('awall.util')
15 16 17 18 19


local LogLimit = class(model.Limit)

function LogLimit:init(...)
20
   util.setdefault(self, 'src-mask', false)
21 22
   LogLimit.super(self):init(...)
end
23 24


25
local Log = class(model.ConfigObject)
26

27
function Log:optfrags()
28
   local mode = self.mode
29
   if mode == 'none' then return {} end
30
   if not (mode or self.mirror) then mode = 'log' end
31

32
   local selector, ofrags
33 34 35 36 37 38 39 40 41 42

   for i, sel in ipairs{'every', 'limit', 'probability'} do
      local value = self[sel]
      if value then
	 if selector then
	    self:error('Cannot combine '..sel..' with '..selector)
	 end
	 selector = sel

	 if sel == 'every' then
43
	    ofrags = {
44
	       {match='-m statistic --mode nth --every '..value..' --packet 0'}
45
	    }
46
	 elseif sel == 'limit' then
47
	    ofrags = self:create(LogLimit, value, 'loglimit'):limitofrags()
48
	 elseif sel == 'probability' then
49
	    ofrags = {{match='-m statistic --mode random --probability '..value}}
50 51 52 53
	 else assert(false) end
      end
   end

54 55 56
   local targets = {}

   if mode then
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
      local optmap = (
	 {
	    log={level='level', prefix='prefix'},
	    nflog={
	       group='group',
	       prefix='prefix',
	       range='size',
	       threshold='threshold'
	    },
	    ulog={
	       group='nlgroup',
	       prefix='prefix',
	       range='cprange',
	       threshold='qthreshold'
	    }
72
	 }
73 74
      )[mode]
      if not optmap then self:error('Invalid logging mode: '..mode) end
75 76

      local target = mode:upper()
77
      for _, s in util.sortedkeys(optmap) do
78 79 80
	 local value = self[s]
	 if value then
	    if s == 'prefix' then value = util.quote(value) end
81
	    target = target..' --'..mode..'-'..optmap[s]..' '..value
82 83
	 end
      end
84

85 86 87 88 89
      table.insert(
	 targets, {family=mode == 'ulog' and 'inet' or nil, target=target}
      )
   end

90 91
   for _, addr in resolvelist(self.mirror) do
      table.insert(targets, {family=addr[1], target='TEE --gateway '..addr[2]})
92 93
   end

94
   return combinations(ofrags, targets)
95
end
96 97 98 99 100 101 102 103 104

function Log.get(rule, spec, default)
   if spec == nil then spec = default end
   if spec == false then return end
   if spec == true then spec = '_default' end
   return rule.root.log[spec] or rule:error('Invalid log: '..spec)
end


105
local LogRule = class(model.Rule)
106 107

function LogRule:init(...)
108
   LogRule.super(self):init(...)
109 110 111 112 113
   self.log = Log.get(self, self.log, true)
end

function LogRule:position() return 'prepend' end

114
function LogRule:mangleoptfrags(ofrags)
115
   return combinations(ofrags, self.log:optfrags())
116 117
end

118 119 120 121 122

return {
   export={
      log={class=Log}, ['packet-log']={class=LogRule, after='%filter-after'}
   }
123
}