]>
Commit | Line | Data |
---|---|---|
6bb38cd6 RG |
1 | /* |
2 | * This file is part of PowerDNS or dnsdist. | |
3 | * Copyright -- PowerDNS.COM B.V. and its contributors | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * In addition, for the avoidance of any doubt, permission is granted to | |
10 | * link this program with OpenSSL and to (re)distribute the binaries | |
11 | * produced as the result of such linking. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
21 | */ | |
22 | #include "dnsdist.hh" | |
23 | #include "dnsdist-lua.hh" | |
05f4003d | 24 | #include "dnsdist-rules.hh" |
6bb38cd6 | 25 | |
6bb38cd6 RG |
26 | std::shared_ptr<DNSRule> makeRule(const luadnsrule_t& var) |
27 | { | |
28 | if (var.type() == typeid(std::shared_ptr<DNSRule>)) | |
29 | return *boost::get<std::shared_ptr<DNSRule>>(&var); | |
30 | ||
31 | SuffixMatchNode smn; | |
32 | NetmaskGroup nmg; | |
33 | auto add=[&](string src) { | |
34 | try { | |
35 | nmg.addMask(src); // need to try mask first, all masks are domain names! | |
36 | } catch(...) { | |
37 | smn.add(DNSName(src)); | |
38 | } | |
39 | }; | |
40 | ||
41 | if (var.type() == typeid(string)) | |
42 | add(*boost::get<string>(&var)); | |
43 | ||
44 | else if (var.type() == typeid(vector<pair<int, string>>)) | |
45 | for(const auto& a : *boost::get<vector<pair<int, string>>>(&var)) | |
46 | add(a.second); | |
47 | ||
48 | else if (var.type() == typeid(DNSName)) | |
49 | smn.add(*boost::get<DNSName>(&var)); | |
50 | ||
51 | else if (var.type() == typeid(vector<pair<int, DNSName>>)) | |
52 | for(const auto& a : *boost::get<vector<pair<int, DNSName>>>(&var)) | |
53 | smn.add(a.second); | |
54 | ||
55 | if(nmg.empty()) | |
56 | return std::make_shared<SuffixMatchNodeRule>(smn); | |
57 | else | |
58 | return std::make_shared<NetmaskGroupRule>(nmg, true); | |
59 | } | |
60 | ||
6a510eff | 61 | static boost::uuids::uuid makeRuleID(std::string& id) |
4d5959e6 RG |
62 | { |
63 | if (id.empty()) { | |
d61aa945 | 64 | return getUniqueID(); |
4d5959e6 RG |
65 | } |
66 | ||
d61aa945 | 67 | return getUniqueID(id); |
4d5959e6 RG |
68 | } |
69 | ||
f8a222ac | 70 | void parseRuleParams(boost::optional<luaruleparams_t> params, boost::uuids::uuid& uuid, uint64_t& creationOrder) |
4d5959e6 | 71 | { |
f8a222ac RG |
72 | static uint64_t s_creationOrder = 0; |
73 | ||
4d5959e6 RG |
74 | string uuidStr; |
75 | ||
76 | if (params) { | |
77 | if (params->count("uuid")) { | |
78 | uuidStr = boost::get<std::string>((*params)["uuid"]); | |
79 | } | |
80 | } | |
81 | ||
6a510eff | 82 | uuid = makeRuleID(uuidStr); |
f8a222ac | 83 | creationOrder = s_creationOrder++; |
4d5959e6 RG |
84 | } |
85 | ||
15bb664c | 86 | typedef std::unordered_map<std::string, boost::variant<bool, int, std::string, std::vector<std::pair<int,int> > > > ruleparams_t; |
3a5a3376 | 87 | |
d18eab67 | 88 | template<typename T> |
15bb664c | 89 | static void showRules(GlobalStateHolder<vector<T> > *someRulActions, boost::optional<ruleparams_t> vars) { |
d18eab67 CH |
90 | setLuaNoSideEffect(); |
91 | int num=0; | |
3a5a3376 CHB |
92 | bool showUUIDs = false; |
93 | size_t truncateRuleWidth = string::npos; | |
94 | ||
95 | if (vars) { | |
96 | if (vars->count("showUUIDs")) { | |
97 | showUUIDs = boost::get<bool>((*vars)["showUUIDs"]); | |
98 | } | |
99 | if (vars->count("truncateRuleWidth")) { | |
100 | truncateRuleWidth = boost::get<int>((*vars)["truncateRuleWidth"]); | |
101 | } | |
102 | } | |
103 | ||
104 | auto rules = someRulActions->getLocal(); | |
105 | if (showUUIDs) { | |
f8a222ac RG |
106 | boost::format fmt("%-3d %-38s %9d %9d %-56s %s\n"); |
107 | g_outputBuffer += (fmt % "#" % "UUID" % "Cr. Order" % "Matches" % "Rule" % "Action").str(); | |
3a5a3376 CHB |
108 | for(const auto& lim : *rules) { |
109 | string name = lim.d_rule->toString().substr(0, truncateRuleWidth); | |
f8a222ac | 110 | g_outputBuffer += (fmt % num % boost::uuids::to_string(lim.d_id) % lim.d_creationOrder % lim.d_rule->d_matches % name % lim.d_action->toString()).str(); |
d18eab67 CH |
111 | ++num; |
112 | } | |
113 | } | |
114 | else { | |
115 | boost::format fmt("%-3d %9d %-56s %s\n"); | |
116 | g_outputBuffer += (fmt % "#" % "Matches" % "Rule" % "Action").str(); | |
3a5a3376 CHB |
117 | for(const auto& lim : *rules) { |
118 | string name = lim.d_rule->toString().substr(0, truncateRuleWidth); | |
d18eab67 CH |
119 | g_outputBuffer += (fmt % num % lim.d_rule->d_matches % name % lim.d_action->toString()).str(); |
120 | ++num; | |
121 | } | |
122 | } | |
123 | } | |
124 | ||
125 | template<typename T> | |
126 | static void rmRule(GlobalStateHolder<vector<T> > *someRulActions, boost::variant<unsigned int, std::string> id) { | |
127 | setLuaSideEffect(); | |
128 | auto rules = someRulActions->getCopy(); | |
129 | if (auto str = boost::get<std::string>(&id)) { | |
d61aa945 | 130 | const auto uuid = getUniqueID(*str); |
d18eab67 CH |
131 | if (rules.erase(std::remove_if(rules.begin(), |
132 | rules.end(), | |
133 | [uuid](const T& a) { return a.d_id == uuid; }), | |
134 | rules.end()) == rules.end()) { | |
135 | g_outputBuffer = "Error: no rule matched\n"; | |
136 | return; | |
137 | } | |
138 | } | |
139 | else if (auto pos = boost::get<unsigned int>(&id)) { | |
140 | if (*pos >= rules.size()) { | |
141 | g_outputBuffer = "Error: attempt to delete non-existing rule\n"; | |
142 | return; | |
143 | } | |
144 | rules.erase(rules.begin()+*pos); | |
145 | } | |
146 | someRulActions->setState(rules); | |
147 | } | |
148 | ||
149 | template<typename T> | |
150 | static void topRule(GlobalStateHolder<vector<T> > *someRulActions) { | |
151 | setLuaSideEffect(); | |
152 | auto rules = someRulActions->getCopy(); | |
153 | if(rules.empty()) | |
154 | return; | |
155 | auto subject = *rules.rbegin(); | |
156 | rules.erase(std::prev(rules.end())); | |
157 | rules.insert(rules.begin(), subject); | |
158 | someRulActions->setState(rules); | |
159 | } | |
160 | ||
161 | template<typename T> | |
162 | static void mvRule(GlobalStateHolder<vector<T> > *someRespRulActions, unsigned int from, unsigned int to) { | |
163 | setLuaSideEffect(); | |
164 | auto rules = someRespRulActions->getCopy(); | |
165 | if(from >= rules.size() || to > rules.size()) { | |
166 | g_outputBuffer = "Error: attempt to move rules from/to invalid index\n"; | |
167 | return; | |
168 | } | |
169 | auto subject = rules[from]; | |
170 | rules.erase(rules.begin()+from); | |
171 | if(to == rules.size()) | |
172 | rules.push_back(subject); | |
173 | else { | |
174 | if(from < to) | |
175 | --to; | |
176 | rules.insert(rules.begin()+to, subject); | |
177 | } | |
178 | someRespRulActions->setState(rules); | |
179 | } | |
180 | ||
6bb38cd6 RG |
181 | void setupLuaRules() |
182 | { | |
183 | g_lua.writeFunction("makeRule", makeRule); | |
184 | ||
185 | g_lua.registerFunction<string(std::shared_ptr<DNSRule>::*)()>("toString", [](const std::shared_ptr<DNSRule>& rule) { return rule->toString(); }); | |
186 | ||
15bb664c | 187 | g_lua.writeFunction("showResponseRules", [](boost::optional<ruleparams_t> vars) { |
3a5a3376 | 188 | showRules(&g_resprulactions, vars); |
6bb38cd6 RG |
189 | }); |
190 | ||
7762339e | 191 | g_lua.writeFunction("rmResponseRule", [](boost::variant<unsigned int, std::string> id) { |
d18eab67 | 192 | rmRule(&g_resprulactions, id); |
6bb38cd6 RG |
193 | }); |
194 | ||
195 | g_lua.writeFunction("topResponseRule", []() { | |
d18eab67 | 196 | topRule(&g_resprulactions); |
6bb38cd6 RG |
197 | }); |
198 | ||
199 | g_lua.writeFunction("mvResponseRule", [](unsigned int from, unsigned int to) { | |
d18eab67 | 200 | mvRule(&g_resprulactions, from, to); |
6bb38cd6 RG |
201 | }); |
202 | ||
15bb664c | 203 | g_lua.writeFunction("showCacheHitResponseRules", [](boost::optional<ruleparams_t> vars) { |
3a5a3376 | 204 | showRules(&g_cachehitresprulactions, vars); |
6bb38cd6 RG |
205 | }); |
206 | ||
7762339e | 207 | g_lua.writeFunction("rmCacheHitResponseRule", [](boost::variant<unsigned int, std::string> id) { |
d18eab67 | 208 | rmRule(&g_cachehitresprulactions, id); |
6bb38cd6 RG |
209 | }); |
210 | ||
211 | g_lua.writeFunction("topCacheHitResponseRule", []() { | |
d18eab67 | 212 | topRule(&g_cachehitresprulactions); |
6bb38cd6 RG |
213 | }); |
214 | ||
215 | g_lua.writeFunction("mvCacheHitResponseRule", [](unsigned int from, unsigned int to) { | |
d18eab67 | 216 | mvRule(&g_cachehitresprulactions, from, to); |
6bb38cd6 RG |
217 | }); |
218 | ||
15bb664c | 219 | g_lua.writeFunction("showSelfAnsweredResponseRules", [](boost::optional<ruleparams_t> vars) { |
3a5a3376 | 220 | showRules(&g_selfansweredresprulactions, vars); |
2d4783a8 CH |
221 | }); |
222 | ||
223 | g_lua.writeFunction("rmSelfAnsweredResponseRule", [](boost::variant<unsigned int, std::string> id) { | |
224 | rmRule(&g_selfansweredresprulactions, id); | |
225 | }); | |
226 | ||
227 | g_lua.writeFunction("topSelfAnsweredResponseRule", []() { | |
228 | topRule(&g_selfansweredresprulactions); | |
229 | }); | |
230 | ||
231 | g_lua.writeFunction("mvSelfAnsweredResponseRule", [](unsigned int from, unsigned int to) { | |
232 | mvRule(&g_selfansweredresprulactions, from, to); | |
233 | }); | |
234 | ||
7762339e | 235 | g_lua.writeFunction("rmRule", [](boost::variant<unsigned int, std::string> id) { |
d18eab67 | 236 | rmRule(&g_rulactions, id); |
6bb38cd6 RG |
237 | }); |
238 | ||
239 | g_lua.writeFunction("topRule", []() { | |
d18eab67 | 240 | topRule(&g_rulactions); |
6bb38cd6 RG |
241 | }); |
242 | ||
243 | g_lua.writeFunction("mvRule", [](unsigned int from, unsigned int to) { | |
d18eab67 | 244 | mvRule(&g_rulactions, from, to); |
6bb38cd6 RG |
245 | }); |
246 | ||
247 | g_lua.writeFunction("clearRules", []() { | |
248 | setLuaSideEffect(); | |
249 | g_rulactions.modify([](decltype(g_rulactions)::value_type& rulactions) { | |
250 | rulactions.clear(); | |
251 | }); | |
252 | }); | |
253 | ||
4d5959e6 | 254 | g_lua.writeFunction("setRules", [](std::vector<DNSDistRuleAction>& newruleactions) { |
6bb38cd6 RG |
255 | setLuaSideEffect(); |
256 | g_rulactions.modify([newruleactions](decltype(g_rulactions)::value_type& gruleactions) { | |
257 | gruleactions.clear(); | |
258 | for (const auto& newruleaction : newruleactions) { | |
4d5959e6 RG |
259 | if (newruleaction.d_action) { |
260 | auto rule=makeRule(newruleaction.d_rule); | |
261 | gruleactions.push_back({rule, newruleaction.d_action, newruleaction.d_id}); | |
6bb38cd6 RG |
262 | } |
263 | } | |
264 | }); | |
265 | }); | |
266 | ||
05f4003d RG |
267 | g_lua.writeFunction("MaxQPSIPRule", [](unsigned int qps, boost::optional<int> ipv4trunc, boost::optional<int> ipv6trunc, boost::optional<int> burst, boost::optional<unsigned int> expiration, boost::optional<unsigned int> cleanupDelay, boost::optional<unsigned int> scanFraction) { |
268 | return std::shared_ptr<DNSRule>(new MaxQPSIPRule(qps, burst.get_value_or(qps), ipv4trunc.get_value_or(32), ipv6trunc.get_value_or(64), expiration.get_value_or(300), cleanupDelay.get_value_or(60), scanFraction.get_value_or(10))); | |
6bb38cd6 RG |
269 | }); |
270 | ||
271 | g_lua.writeFunction("MaxQPSRule", [](unsigned int qps, boost::optional<int> burst) { | |
272 | if(!burst) | |
273 | return std::shared_ptr<DNSRule>(new MaxQPSRule(qps)); | |
274 | else | |
275 | return std::shared_ptr<DNSRule>(new MaxQPSRule(qps, *burst)); | |
276 | }); | |
277 | ||
278 | g_lua.writeFunction("RegexRule", [](const std::string& str) { | |
279 | return std::shared_ptr<DNSRule>(new RegexRule(str)); | |
280 | }); | |
281 | ||
282 | #ifdef HAVE_RE2 | |
283 | g_lua.writeFunction("RE2Rule", [](const std::string& str) { | |
284 | return std::shared_ptr<DNSRule>(new RE2Rule(str)); | |
285 | }); | |
286 | #endif | |
287 | ||
288 | g_lua.writeFunction("SuffixMatchNodeRule", [](const SuffixMatchNode& smn, boost::optional<bool> quiet) { | |
289 | return std::shared_ptr<DNSRule>(new SuffixMatchNodeRule(smn, quiet ? *quiet : false)); | |
290 | }); | |
291 | ||
292 | g_lua.writeFunction("NetmaskGroupRule", [](const NetmaskGroup& nmg, boost::optional<bool> src) { | |
293 | return std::shared_ptr<DNSRule>(new NetmaskGroupRule(nmg, src ? *src : true)); | |
294 | }); | |
295 | ||
296 | g_lua.writeFunction("benchRule", [](std::shared_ptr<DNSRule> rule, boost::optional<int> times_, boost::optional<string> suffix_) { | |
297 | setLuaNoSideEffect(); | |
298 | int times = times_.get_value_or(100000); | |
299 | DNSName suffix(suffix_.get_value_or("powerdns.com")); | |
300 | struct item { | |
301 | vector<uint8_t> packet; | |
302 | ComboAddress rem; | |
303 | DNSName qname; | |
304 | uint16_t qtype, qclass; | |
305 | }; | |
306 | vector<item> items; | |
307 | items.reserve(1000); | |
308 | for(int n=0; n < 1000; ++n) { | |
309 | struct item i; | |
310 | i.qname=DNSName(std::to_string(random())); | |
311 | i.qname += suffix; | |
312 | i.qtype = random() % 0xff; | |
313 | i.qclass = 1; | |
314 | i.rem=ComboAddress("127.0.0.1"); | |
315 | i.rem.sin4.sin_addr.s_addr = random(); | |
316 | DNSPacketWriter pw(i.packet, i.qname, i.qtype); | |
317 | items.push_back(i); | |
318 | } | |
319 | ||
320 | int matches=0; | |
321 | ComboAddress dummy("127.0.0.1"); | |
5ffb2f83 CH |
322 | StopWatch sw; |
323 | sw.start(); | |
6bb38cd6 RG |
324 | for(int n=0; n < times; ++n) { |
325 | const item& i = items[n % items.size()]; | |
e7c732b8 | 326 | DNSQuestion dq(&i.qname, i.qtype, i.qclass, 0, &i.rem, &i.rem, (struct dnsheader*)&i.packet[0], i.packet.size(), i.packet.size(), false, &sw.d_start); |
6bb38cd6 RG |
327 | if(rule->matches(&dq)) |
328 | matches++; | |
329 | } | |
5ffb2f83 | 330 | double udiff=sw.udiff(); |
6bb38cd6 RG |
331 | g_outputBuffer=(boost::format("Had %d matches out of %d, %.1f qps, in %.1f usec\n") % matches % times % (1000000*(1.0*times/udiff)) % udiff).str(); |
332 | ||
333 | }); | |
334 | ||
335 | g_lua.writeFunction("AllRule", []() { | |
336 | return std::shared_ptr<DNSRule>(new AllRule()); | |
337 | }); | |
338 | ||
339 | g_lua.writeFunction("ProbaRule", [](double proba) { | |
340 | return std::shared_ptr<DNSRule>(new ProbaRule(proba)); | |
341 | }); | |
342 | ||
343 | g_lua.writeFunction("QNameRule", [](const std::string& qname) { | |
344 | return std::shared_ptr<DNSRule>(new QNameRule(DNSName(qname))); | |
345 | }); | |
346 | ||
347 | g_lua.writeFunction("QTypeRule", [](boost::variant<int, std::string> str) { | |
348 | uint16_t qtype; | |
349 | if(auto dir = boost::get<int>(&str)) { | |
350 | qtype = *dir; | |
351 | } | |
352 | else { | |
353 | string val=boost::get<string>(str); | |
354 | qtype = QType::chartocode(val.c_str()); | |
355 | if(!qtype) | |
356 | throw std::runtime_error("Unable to convert '"+val+"' to a DNS type"); | |
357 | } | |
358 | return std::shared_ptr<DNSRule>(new QTypeRule(qtype)); | |
359 | }); | |
360 | ||
361 | g_lua.writeFunction("QClassRule", [](int c) { | |
362 | return std::shared_ptr<DNSRule>(new QClassRule(c)); | |
363 | }); | |
364 | ||
365 | g_lua.writeFunction("OpcodeRule", [](uint8_t code) { | |
366 | return std::shared_ptr<DNSRule>(new OpcodeRule(code)); | |
367 | }); | |
368 | ||
369 | g_lua.writeFunction("AndRule", [](vector<pair<int, std::shared_ptr<DNSRule> > >a) { | |
370 | return std::shared_ptr<DNSRule>(new AndRule(a)); | |
371 | }); | |
372 | ||
373 | g_lua.writeFunction("OrRule", [](vector<pair<int, std::shared_ptr<DNSRule> > >a) { | |
374 | return std::shared_ptr<DNSRule>(new OrRule(a)); | |
375 | }); | |
376 | ||
dfa098fb | 377 | g_lua.writeFunction("DSTPortRule", [](uint16_t port) { |
378 | return std::shared_ptr<DNSRule>(new DSTPortRule(port)); | |
379 | }); | |
380 | ||
6bb38cd6 RG |
381 | g_lua.writeFunction("TCPRule", [](bool tcp) { |
382 | return std::shared_ptr<DNSRule>(new TCPRule(tcp)); | |
383 | }); | |
384 | ||
385 | g_lua.writeFunction("DNSSECRule", []() { | |
386 | return std::shared_ptr<DNSRule>(new DNSSECRule()); | |
387 | }); | |
388 | ||
389 | g_lua.writeFunction("NotRule", [](std::shared_ptr<DNSRule>rule) { | |
390 | return std::shared_ptr<DNSRule>(new NotRule(rule)); | |
391 | }); | |
392 | ||
393 | g_lua.writeFunction("RecordsCountRule", [](uint8_t section, uint16_t minCount, uint16_t maxCount) { | |
394 | return std::shared_ptr<DNSRule>(new RecordsCountRule(section, minCount, maxCount)); | |
395 | }); | |
396 | ||
397 | g_lua.writeFunction("RecordsTypeCountRule", [](uint8_t section, uint16_t type, uint16_t minCount, uint16_t maxCount) { | |
398 | return std::shared_ptr<DNSRule>(new RecordsTypeCountRule(section, type, minCount, maxCount)); | |
399 | }); | |
400 | ||
401 | g_lua.writeFunction("TrailingDataRule", []() { | |
402 | return std::shared_ptr<DNSRule>(new TrailingDataRule()); | |
403 | }); | |
404 | ||
405 | g_lua.writeFunction("QNameLabelsCountRule", [](unsigned int minLabelsCount, unsigned int maxLabelsCount) { | |
406 | return std::shared_ptr<DNSRule>(new QNameLabelsCountRule(minLabelsCount, maxLabelsCount)); | |
407 | }); | |
408 | ||
409 | g_lua.writeFunction("QNameWireLengthRule", [](size_t min, size_t max) { | |
410 | return std::shared_ptr<DNSRule>(new QNameWireLengthRule(min, max)); | |
411 | }); | |
412 | ||
f6007449 | 413 | g_lua.writeFunction("RCodeRule", [](uint8_t rcode) { |
6bb38cd6 RG |
414 | return std::shared_ptr<DNSRule>(new RCodeRule(rcode)); |
415 | }); | |
416 | ||
f6007449 | 417 | g_lua.writeFunction("ERCodeRule", [](uint8_t rcode) { |
d83feb68 CH |
418 | return std::shared_ptr<DNSRule>(new ERCodeRule(rcode)); |
419 | }); | |
420 | ||
4bfdbd34 PD |
421 | g_lua.writeFunction("EDNSOptionRule", [](uint16_t optcode) { |
422 | return std::shared_ptr<DNSRule>(new EDNSOptionRule(optcode)); | |
423 | }); | |
424 | ||
15bb664c | 425 | g_lua.writeFunction("showRules", [](boost::optional<ruleparams_t> vars) { |
3a5a3376 | 426 | showRules(&g_rulactions, vars); |
6bb38cd6 RG |
427 | }); |
428 | ||
429 | g_lua.writeFunction("RDRule", []() { | |
430 | return std::shared_ptr<DNSRule>(new RDRule()); | |
431 | }); | |
432 | ||
433 | g_lua.writeFunction("TagRule", [](std::string tag, boost::optional<std::string> value) { | |
434 | return std::shared_ptr<DNSRule>(new TagRule(tag, value)); | |
435 | }); | |
436 | ||
437 | g_lua.writeFunction("TimedIPSetRule", []() { | |
438 | return std::shared_ptr<TimedIPSetRule>(new TimedIPSetRule()); | |
439 | }); | |
440 | ||
83145026 | 441 | g_lua.writeFunction("PoolAvailableRule", [](std::string poolname) { |
510c45d0 | 442 | return std::shared_ptr<DNSRule>(new PoolAvailableRule(poolname)); |
83145026 RG |
443 | }); |
444 | ||
6bb38cd6 RG |
445 | g_lua.registerFunction<void(std::shared_ptr<TimedIPSetRule>::*)()>("clear", [](std::shared_ptr<TimedIPSetRule> tisr) { |
446 | tisr->clear(); | |
447 | }); | |
448 | ||
449 | g_lua.registerFunction<void(std::shared_ptr<TimedIPSetRule>::*)()>("cleanup", [](std::shared_ptr<TimedIPSetRule> tisr) { | |
450 | tisr->cleanup(); | |
451 | }); | |
452 | ||
453 | g_lua.registerFunction<void(std::shared_ptr<TimedIPSetRule>::*)(const ComboAddress& ca, int t)>("add", [](std::shared_ptr<TimedIPSetRule> tisr, const ComboAddress& ca, int t) { | |
454 | tisr->add(ca, time(0)+t); | |
455 | }); | |
456 | ||
457 | g_lua.registerFunction<std::shared_ptr<DNSRule>(std::shared_ptr<TimedIPSetRule>::*)()>("slice", [](std::shared_ptr<TimedIPSetRule> tisr) { | |
458 | return std::dynamic_pointer_cast<DNSRule>(tisr); | |
459 | }); | |
460 | } |