-- Copyright (c) 2019-2020 CZ.NIC, z.s.p.o. -- All rights reserved. -- -- This file is part of dnsjit. -- -- dnsjit is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- -- dnsjit is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with dnsjit. If not, see . -- dnsjit.filter.ipsplit -- Pass objects to receivers based on the source IP address -- local ipsplit = require("dnsjit.filter.ipsplit").new() -- ipsplit.receiver(...) -- ipsplit.receiver(...) -- ipsplit.receiver(...) -- input.receiver(ipsplit) -- -- The filter passes objects to other receivers. -- Object chains without IPv4/IPv6 packet are discarded. -- Packets which have the same source IP address are considered to be sent -- from the same "client". -- When the first packet from a client is processed, the client is assigned -- to a receiver. -- All objects from this client will be passed to the assigned receiver. -- The filter can also write a receiver-specific client ID (starting from 1) -- to the source or destination IP in the packet. module(...,package.seeall) require("dnsjit.filter.ipsplit_h") local bit = require("bit") local object = require("dnsjit.core.objects") local ffi = require("ffi") local C = ffi.C local IpSplit = {} -- Create a new IpSplit filter. function IpSplit.new() local self = { obj = C.filter_ipsplit_new(), } ffi.gc(self.obj, C.filter_ipsplit_free) return setmetatable(self, { __index = IpSplit }) end -- Return the Log object to control logging of this instance or module. function IpSplit:log() if self == nil then return C.filter_ipsplit_log() end return self.obj._log end -- Return the C functions and context for receiving objects. function IpSplit:receive() local recv = C.filter_ipsplit_receiver(self.obj) return recv, self.obj end -- Set the receiver to pass objects to, this can be called multiple times to -- set additional receivers. -- The weight parameter can be used to adjust distribution of clients among -- receivers. -- Weight must be a positive integer (default is 1). function IpSplit:receiver(o, weight) local recv, ctx = o:receive() if weight == nil then weight = 1 end C.filter_ipsplit_add(self.obj, recv, ctx, weight) end -- Number of input packets discarded due to various reasons. -- To investigate causes, run with increased logging level. function IpSplit:discarded() return tonumber(self.obj.discarded) end -- Set the client assignment mode to sequential. -- Assigns `weight` clients to a receiver before continuing with the next -- receiver (default mode). function IpSplit:sequential() self.obj.mode = "IPSPLIT_MODE_SEQUENTIAL" end -- Set the client assignment mode to random. -- Each client is randomly assigned to a receiver (weight affects the -- probability). -- The client assignment is stable (and portable) for given seed. function IpSplit:random(seed) self.obj.mode = "IPSPLIT_MODE_RANDOM" if seed then C.filter_ipsplit_srand(seed) end end -- Don't overwrite source or destination IP (default). function IpSplit:overwrite_none() self.obj.overwrite = "IPSPLIT_OVERWRITE_NONE" end -- Write receiver-specific client ID to bytes 0-3 of source IP (host byte order). function IpSplit:overwrite_src() self.obj.overwrite = "IPSPLIT_OVERWRITE_SRC" end -- Write receiver-specific client ID to bytes 0-3 of destination IP (host byte -- order). function IpSplit:overwrite_dst() self.obj.overwrite = "IPSPLIT_OVERWRITE_DST" end return IpSplit