]>
Commit | Line | Data |
---|---|---|
12471842 PL |
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 | */ | |
808c5ef7 | 22 | #include "lua-recursor4.hh" |
23 | #include <fstream> | |
808c5ef7 | 24 | #include "logger.hh" |
a3e7b735 | 25 | #include "dnsparser.hh" |
26 | #include "syncres.hh" | |
dd39e2dc | 27 | #include "namespaces.hh" |
b40562da RG |
28 | #include "rec_channel.hh" |
29 | #include "ednsoptions.hh" | |
5ecf1d7e | 30 | #include "ednssubnet.hh" |
db486de5 | 31 | #include "filterpo.hh" |
d705aad9 | 32 | #include "rec-snmp.hh" |
08dcccd6 | 33 | #include <unordered_set> |
410d750c | 34 | |
9694e14f | 35 | RecursorLua4::RecursorLua4() { prepareContext(); } |
70c21c40 | 36 | |
621e4e59 PL |
37 | boost::optional<dnsheader> RecursorLua4::DNSQuestion::getDH() const |
38 | { | |
39 | if (dh) | |
40 | return *dh; | |
41 | return boost::optional<dnsheader>(); | |
42 | } | |
43 | ||
e2fb3504 PL |
44 | vector<string> RecursorLua4::DNSQuestion::getEDNSFlags() const |
45 | { | |
46 | vector<string> ret; | |
47 | if (ednsFlags) { | |
48 | if (*ednsFlags & EDNSOpts::DNSSECOK) | |
49 | ret.push_back("DO"); | |
50 | } | |
51 | return ret; | |
52 | } | |
53 | ||
54 | bool RecursorLua4::DNSQuestion::getEDNSFlag(string flag) const | |
55 | { | |
56 | if (ednsFlags) { | |
57 | if (flag == "DO" && (*ednsFlags & EDNSOpts::DNSSECOK)) | |
58 | return true; | |
59 | } | |
60 | return false; | |
61 | } | |
62 | ||
ba21fcfe | 63 | vector<pair<uint16_t, string> > RecursorLua4::DNSQuestion::getEDNSOptions() const |
e8340d27 | 64 | { |
65 | if(ednsOptions) | |
66 | return *ednsOptions; | |
67 | else | |
68 | return vector<pair<uint16_t,string>>(); | |
69 | } | |
70 | ||
ba21fcfe | 71 | boost::optional<string> RecursorLua4::DNSQuestion::getEDNSOption(uint16_t code) const |
e8340d27 | 72 | { |
73 | if(ednsOptions) | |
74 | for(const auto& o : *ednsOptions) | |
75 | if(o.first==code) | |
76 | return o.second; | |
77 | ||
78 | return boost::optional<string>(); | |
79 | } | |
80 | ||
ba21fcfe | 81 | boost::optional<Netmask> RecursorLua4::DNSQuestion::getEDNSSubnet() const |
5ecf1d7e | 82 | { |
5ecf1d7e | 83 | if(ednsOptions) { |
84 | for(const auto& o : *ednsOptions) { | |
b40562da | 85 | if(o.first==EDNSOptionCode::ECS) { |
5ecf1d7e | 86 | EDNSSubnetOpts eso; |
87 | if(getEDNSSubnetOptsFromString(o.second, &eso)) | |
88 | return eso.source; | |
89 | else | |
90 | break; | |
91 | } | |
92 | } | |
93 | } | |
94 | return boost::optional<Netmask>(); | |
95 | } | |
96 | ||
3bdc4508 | 97 | std::vector<std::pair<int, ProxyProtocolValue>> RecursorLua4::DNSQuestion::getProxyProtocolValues() const |
38d8b937 | 98 | { |
3bdc4508 | 99 | std::vector<std::pair<int, ProxyProtocolValue>> result; |
38d8b937 RG |
100 | if (proxyProtocolValues) { |
101 | result.reserve(proxyProtocolValues->size()); | |
102 | ||
3bdc4508 | 103 | int idx = 1; |
38d8b937 | 104 | for (const auto& value: *proxyProtocolValues) { |
3bdc4508 | 105 | result.push_back({ idx++, value }); |
38d8b937 RG |
106 | } |
107 | } | |
108 | ||
109 | return result; | |
110 | } | |
e8340d27 | 111 | |
ba21fcfe | 112 | vector<pair<int, DNSRecord> > RecursorLua4::DNSQuestion::getRecords() const |
a3e7b735 | 113 | { |
114 | vector<pair<int, DNSRecord> > ret; | |
115 | int num=1; | |
116 | for(const auto& r : records) { | |
117 | ret.push_back({num++, r}); | |
118 | } | |
119 | return ret; | |
120 | } | |
121 | void RecursorLua4::DNSQuestion::setRecords(const vector<pair<int, DNSRecord> >& recs) | |
122 | { | |
123 | records.clear(); | |
124 | for(const auto& p : recs) { | |
125 | records.push_back(p.second); | |
a3e7b735 | 126 | } |
127 | } | |
128 | ||
aee72a7b | 129 | void RecursorLua4::DNSQuestion::addRecord(uint16_t type, const std::string& content, DNSResourceRecord::Place place, boost::optional<int> ttl, boost::optional<string> name) |
a3e7b735 | 130 | { |
131 | DNSRecord dr; | |
aee72a7b | 132 | dr.d_name=name ? DNSName(*name) : qname; |
a3e7b735 | 133 | dr.d_ttl=ttl.get_value_or(3600); |
134 | dr.d_type = type; | |
135 | dr.d_place = place; | |
6177a176 | 136 | dr.d_content = DNSRecordContent::mastermake(type, 1, content); |
a3e7b735 | 137 | records.push_back(dr); |
138 | } | |
139 | ||
aee72a7b | 140 | void RecursorLua4::DNSQuestion::addAnswer(uint16_t type, const std::string& content, boost::optional<int> ttl, boost::optional<string> name) |
a3e7b735 | 141 | { |
aee72a7b | 142 | addRecord(type, content, DNSResourceRecord::ANSWER, ttl, name); |
a3e7b735 | 143 | } |
9f89a5f1 | 144 | |
145 | struct DynMetric | |
146 | { | |
147 | std::atomic<unsigned long>* ptr; | |
148 | void inc() { (*ptr)++; } | |
149 | void incBy(unsigned int by) { (*ptr)+= by; } | |
150 | unsigned long get() { return *ptr; } | |
151 | void set(unsigned long val) { *ptr =val; } | |
152 | }; | |
153 | ||
70c21c40 | 154 | void RecursorLua4::postPrepareContext() |
808c5ef7 | 155 | { |
ba21fcfe RG |
156 | d_lw->registerMember<const DNSName (DNSQuestion::*)>("qname", [](const DNSQuestion& dq) -> const DNSName& { return dq.qname; }, [](DNSQuestion& dq, const DNSName& newName) { (void) newName; }); |
157 | d_lw->registerMember<uint16_t (DNSQuestion::*)>("qtype", [](const DNSQuestion& dq) -> uint16_t { return dq.qtype; }, [](DNSQuestion& dq, uint16_t newType) { (void) newType; }); | |
158 | d_lw->registerMember<bool (DNSQuestion::*)>("isTcp", [](const DNSQuestion& dq) -> bool { return dq.isTcp; }, [](DNSQuestion& dq, bool newTcp) { (void) newTcp; }); | |
159 | d_lw->registerMember<const ComboAddress (DNSQuestion::*)>("localaddr", [](const DNSQuestion& dq) -> const ComboAddress& { return dq.local; }, [](DNSQuestion& dq, const ComboAddress& newLocal) { (void) newLocal; }); | |
160 | d_lw->registerMember<const ComboAddress (DNSQuestion::*)>("remoteaddr", [](const DNSQuestion& dq) -> const ComboAddress& { return dq.remote; }, [](DNSQuestion& dq, const ComboAddress& newRemote) { (void) newRemote; }); | |
1921a4c2 | 161 | d_lw->registerMember<vState (DNSQuestion::*)>("validationState", [](const DNSQuestion& dq) -> vState { return dq.validationState; }, [](DNSQuestion& dq, vState newState) { (void) newState; }); |
ba21fcfe RG |
162 | |
163 | d_lw->registerMember<bool (DNSQuestion::*)>("variable", [](const DNSQuestion& dq) -> bool { return dq.variable; }, [](DNSQuestion& dq, bool newVariable) { dq.variable = newVariable; }); | |
164 | d_lw->registerMember<bool (DNSQuestion::*)>("wantsRPZ", [](const DNSQuestion& dq) -> bool { return dq.wantsRPZ; }, [](DNSQuestion& dq, bool newWantsRPZ) { dq.wantsRPZ = newWantsRPZ; }); | |
f1c7929a | 165 | d_lw->registerMember<bool (DNSQuestion::*)>("logResponse", [](const DNSQuestion& dq) -> bool { return dq.logResponse; }, [](DNSQuestion& dq, bool newLogResponse) { dq.logResponse = newLogResponse; }); |
ba21fcfe | 166 | |
a3e7b735 | 167 | d_lw->registerMember("rcode", &DNSQuestion::rcode); |
ba461517 | 168 | d_lw->registerMember("tag", &DNSQuestion::tag); |
67e31ebe | 169 | d_lw->registerMember("requestorId", &DNSQuestion::requestorId); |
e92fb64f CHB |
170 | d_lw->registerMember("deviceId", &DNSQuestion::deviceId); |
171 | d_lw->registerMember("deviceName", &DNSQuestion::deviceName); | |
a3e7b735 | 172 | d_lw->registerMember("followupFunction", &DNSQuestion::followupFunction); |
173 | d_lw->registerMember("followupPrefix", &DNSQuestion::followupPrefix); | |
174 | d_lw->registerMember("followupName", &DNSQuestion::followupName); | |
6b8b26c8 | 175 | d_lw->registerMember("data", &DNSQuestion::data); |
176 | d_lw->registerMember("udpQuery", &DNSQuestion::udpQuery); | |
177 | d_lw->registerMember("udpAnswer", &DNSQuestion::udpAnswer); | |
178 | d_lw->registerMember("udpQueryDest", &DNSQuestion::udpQueryDest); | |
179 | d_lw->registerMember("udpCallback", &DNSQuestion::udpCallback); | |
667f6c7c | 180 | d_lw->registerMember("appliedPolicy", &DNSQuestion::appliedPolicy); |
98c28a68 RG |
181 | d_lw->registerMember<DNSFilterEngine::Policy, std::string>("policyName", |
182 | [](const DNSFilterEngine::Policy& pol) -> std::string { | |
b502d522 | 183 | return pol.getName(); |
98c28a68 RG |
184 | }, |
185 | [](DNSFilterEngine::Policy& pol, const std::string& name) { | |
b502d522 | 186 | pol.setName(name); |
98c28a68 | 187 | }); |
db486de5 | 188 | d_lw->registerMember("policyKind", &DNSFilterEngine::Policy::d_kind); |
ed25b215 | 189 | d_lw->registerMember("policyType", &DNSFilterEngine::Policy::d_type); |
db486de5 | 190 | d_lw->registerMember("policyTTL", &DNSFilterEngine::Policy::d_ttl); |
98c28a68 RG |
191 | d_lw->registerMember<DNSFilterEngine::Policy, std::string>("policyCustom", |
192 | [](const DNSFilterEngine::Policy& pol) -> std::string { | |
6da513b2 RG |
193 | std::string result; |
194 | if (pol.d_kind != DNSFilterEngine::PolicyKind::Custom) { | |
195 | return result; | |
196 | } | |
197 | ||
198 | for (const auto& dr : pol.d_custom) { | |
199 | if (!result.empty()) { | |
200 | result += "\n"; | |
201 | } | |
202 | result += dr->getZoneRepresentation(); | |
203 | } | |
204 | ||
205 | return result; | |
db486de5 | 206 | }, |
98c28a68 | 207 | [](DNSFilterEngine::Policy& pol, const std::string& content) { |
db486de5 | 208 | // Only CNAMES for now, when we ever add a d_custom_type, there will be pain |
6da513b2 RG |
209 | pol.d_custom.clear(); |
210 | pol.d_custom.push_back(DNSRecordContent::mastermake(QType::CNAME, QClass::IN, content)); | |
db486de5 PL |
211 | } |
212 | ); | |
621e4e59 | 213 | d_lw->registerFunction("getDH", &DNSQuestion::getDH); |
e8340d27 | 214 | d_lw->registerFunction("getEDNSOptions", &DNSQuestion::getEDNSOptions); |
215 | d_lw->registerFunction("getEDNSOption", &DNSQuestion::getEDNSOption); | |
5ecf1d7e | 216 | d_lw->registerFunction("getEDNSSubnet", &DNSQuestion::getEDNSSubnet); |
38d8b937 | 217 | d_lw->registerFunction("getProxyProtocolValues", &DNSQuestion::getProxyProtocolValues); |
e2fb3504 PL |
218 | d_lw->registerFunction("getEDNSFlags", &DNSQuestion::getEDNSFlags); |
219 | d_lw->registerFunction("getEDNSFlag", &DNSQuestion::getEDNSFlag); | |
a3e7b735 | 220 | d_lw->registerMember("name", &DNSRecord::d_name); |
221 | d_lw->registerMember("type", &DNSRecord::d_type); | |
222 | d_lw->registerMember("ttl", &DNSRecord::d_ttl); | |
57d0c73b | 223 | d_lw->registerMember("place", &DNSRecord::d_place); |
00b8cadc | 224 | |
29e6303a RG |
225 | d_lw->registerMember("size", &EDNSOptionViewValue::size); |
226 | d_lw->registerFunction<std::string(EDNSOptionViewValue::*)()>("getContent", [](const EDNSOptionViewValue& value) { return std::string(value.content, value.size); }); | |
227 | d_lw->registerFunction<size_t(EDNSOptionView::*)()>("count", [](const EDNSOptionView& option) { return option.values.size(); }); | |
6158a3b3 PD |
228 | d_lw->registerFunction<std::vector<string>(EDNSOptionView::*)()>("getValues", [] (const EDNSOptionView& option) { |
229 | std::vector<string> values; | |
29e6303a | 230 | for (const auto& value : option.values) { |
6158a3b3 | 231 | values.push_back(std::string(value.content, value.size)); |
29e6303a RG |
232 | } |
233 | return values; | |
234 | }); | |
235 | ||
236 | /* pre 4.2 API compatibility, when we had only one value for a given EDNS option */ | |
237 | d_lw->registerMember<uint16_t(EDNSOptionView::*)>("size", [](const EDNSOptionView& option) -> uint16_t { | |
238 | uint16_t result = 0; | |
239 | ||
240 | if (!option.values.empty()) { | |
241 | result = option.values.at(0).size; | |
242 | } | |
243 | return result; | |
244 | }, | |
245 | [](EDNSOptionView& option, uint16_t newSize) { (void) newSize; }); | |
246 | d_lw->registerFunction<std::string(EDNSOptionView::*)()>("getContent", [](const EDNSOptionView& option) { | |
247 | if (option.values.empty()) { | |
248 | return std::string(); | |
249 | } | |
250 | return std::string(option.values.at(0).content, option.values.at(0).size); }); | |
00b8cadc | 251 | |
a3e7b735 | 252 | d_lw->registerFunction<string(DNSRecord::*)()>("getContent", [](const DNSRecord& dr) { return dr.d_content->getZoneRepresentation(); }); |
7d5f094a | 253 | d_lw->registerFunction<boost::optional<ComboAddress>(DNSRecord::*)()>("getCA", [](const DNSRecord& dr) { |
254 | boost::optional<ComboAddress> ret; | |
255 | ||
256 | if(auto rec = std::dynamic_pointer_cast<ARecordContent>(dr.d_content)) | |
257 | ret=rec->getCA(53); | |
dd079764 RG |
258 | else if(auto aaaarec = std::dynamic_pointer_cast<AAAARecordContent>(dr.d_content)) |
259 | ret=aaaarec->getCA(53); | |
7d5f094a | 260 | return ret; |
261 | }); | |
a3e7b735 | 262 | |
3bdc4508 RG |
263 | d_lw->registerFunction<const ProxyProtocolValue, std::string()>("getContent", [](const ProxyProtocolValue& value) { return value.content; }); |
264 | d_lw->registerFunction<const ProxyProtocolValue, uint8_t()>("getType", [](const ProxyProtocolValue& value) { return value.type; }); | |
a3e7b735 | 265 | |
6177a176 | 266 | d_lw->registerFunction<void(DNSRecord::*)(const std::string&)>("changeContent", [](DNSRecord& dr, const std::string& newContent) { dr.d_content = DNSRecordContent::mastermake(dr.d_type, 1, newContent); }); |
a3e7b735 | 267 | d_lw->registerFunction("addAnswer", &DNSQuestion::addAnswer); |
08dcccd6 | 268 | d_lw->registerFunction("addRecord", &DNSQuestion::addRecord); |
a3e7b735 | 269 | d_lw->registerFunction("getRecords", &DNSQuestion::getRecords); |
270 | d_lw->registerFunction("setRecords", &DNSQuestion::setRecords); | |
271 | ||
b502d522 | 272 | d_lw->registerFunction<void(DNSQuestion::*)(const std::string&)>("addPolicyTag", [](DNSQuestion& dq, const std::string& tag) { if (dq.policyTags) { dq.policyTags->insert(tag); } }); |
667f6c7c | 273 | d_lw->registerFunction<void(DNSQuestion::*)(const std::vector<std::pair<int, std::string> >&)>("setPolicyTags", [](DNSQuestion& dq, const std::vector<std::pair<int, std::string> >& tags) { |
48096cf0 RG |
274 | if (dq.policyTags) { |
275 | dq.policyTags->clear(); | |
b502d522 | 276 | dq.policyTags->reserve(tags.size()); |
48096cf0 | 277 | for (const auto& tag : tags) { |
b502d522 | 278 | dq.policyTags->insert(tag.second); |
48096cf0 | 279 | } |
667f6c7c RG |
280 | } |
281 | }); | |
282 | d_lw->registerFunction<std::vector<std::pair<int, std::string> >(DNSQuestion::*)()>("getPolicyTags", [](const DNSQuestion& dq) { | |
283 | std::vector<std::pair<int, std::string> > ret; | |
48096cf0 RG |
284 | if (dq.policyTags) { |
285 | int count = 1; | |
b502d522 | 286 | ret.reserve(dq.policyTags->size()); |
48096cf0 RG |
287 | for (const auto& tag : *dq.policyTags) { |
288 | ret.push_back({count++, tag}); | |
289 | } | |
667f6c7c RG |
290 | } |
291 | return ret; | |
292 | }); | |
293 | ||
0a273054 RG |
294 | d_lw->registerFunction<void(DNSQuestion::*)(const std::string&)>("discardPolicy", [](DNSQuestion& dq, const std::string& policy) { |
295 | if (dq.discardedPolicies) { | |
296 | (*dq.discardedPolicies)[policy] = true; | |
297 | } | |
298 | }); | |
299 | ||
a3e7b735 | 300 | d_lw->writeFunction("newDS", []() { return SuffixMatchNode(); }); |
805f3e03 PL |
301 | d_lw->registerFunction<void(SuffixMatchNode::*)(boost::variant<string,DNSName, vector<pair<unsigned int,string> > >)>( |
302 | "add", | |
303 | [](SuffixMatchNode&smn, const boost::variant<string,DNSName,vector<pair<unsigned int,string> > >& in){ | |
304 | try { | |
305 | if(auto s = boost::get<string>(&in)) { | |
306 | smn.add(DNSName(*s)); | |
307 | } | |
308 | else if(auto v = boost::get<vector<pair<unsigned int, string> > >(&in)) { | |
dd079764 RG |
309 | for(const auto& entry : *v) |
310 | smn.add(DNSName(entry.second)); | |
805f3e03 PL |
311 | } |
312 | else { | |
313 | smn.add(boost::get<DNSName>(in)); | |
314 | } | |
315 | } | |
316 | catch(std::exception& e) { | |
e6a9dde5 | 317 | g_log <<Logger::Error<<e.what()<<endl; |
805f3e03 PL |
318 | } |
319 | } | |
320 | ); | |
321 | ||
a3e7b735 | 322 | d_lw->registerFunction("check",(bool (SuffixMatchNode::*)(const DNSName&) const) &SuffixMatchNode::check); |
c6b99fc1 | 323 | d_lw->registerFunction("toString",(string (SuffixMatchNode::*)() const) &SuffixMatchNode::toString); |
a3e7b735 | 324 | |
70c21c40 | 325 | d_pd.push_back({"policykinds", in_t { |
db486de5 PL |
326 | {"NoAction", (int)DNSFilterEngine::PolicyKind::NoAction}, |
327 | {"Drop", (int)DNSFilterEngine::PolicyKind::Drop }, | |
328 | {"NXDOMAIN", (int)DNSFilterEngine::PolicyKind::NXDOMAIN}, | |
329 | {"NODATA", (int)DNSFilterEngine::PolicyKind::NODATA }, | |
330 | {"Truncate", (int)DNSFilterEngine::PolicyKind::Truncate}, | |
331 | {"Custom", (int)DNSFilterEngine::PolicyKind::Custom } | |
332 | }}); | |
333 | ||
a3e7b735 | 334 | for(const auto& n : QType::names) |
70c21c40 | 335 | d_pd.push_back({n.first, n.second}); |
1921a4c2 | 336 | |
70c21c40 | 337 | d_pd.push_back({"validationstates", in_t{ |
1921a4c2 RG |
338 | {"Indeterminate", Indeterminate }, |
339 | {"Bogus", Bogus }, | |
340 | {"Insecure", Insecure }, | |
341 | {"Secure", Secure }, | |
342 | }}); | |
343 | ||
70c21c40 | 344 | d_pd.push_back({"now", &g_now}); |
9f89a5f1 | 345 | |
346 | d_lw->writeFunction("getMetric", [](const std::string& str) { | |
347 | return DynMetric{getDynMetric(str)}; | |
348 | }); | |
349 | ||
350 | d_lw->registerFunction("inc", &DynMetric::inc); | |
351 | d_lw->registerFunction("incBy", &DynMetric::incBy); | |
352 | d_lw->registerFunction("set", &DynMetric::set); | |
353 | d_lw->registerFunction("get", &DynMetric::get); | |
b4015453 | 354 | |
b0b37121 RG |
355 | d_lw->writeFunction("getStat", [](const std::string& str) { |
356 | uint64_t result = 0; | |
357 | optional<uint64_t> value = getStatByName(str); | |
358 | if (value) { | |
359 | result = *value; | |
360 | } | |
361 | return result; | |
362 | }); | |
363 | ||
b4015453 RG |
364 | d_lw->writeFunction("getRecursorThreadId", []() { |
365 | return getRecursorThreadId(); | |
366 | }); | |
367 | ||
d705aad9 RG |
368 | d_lw->writeFunction("sendCustomSNMPTrap", [](const std::string& str) { |
369 | if (g_snmpAgent) { | |
370 | g_snmpAgent->sendCustomTrap(str); | |
371 | } | |
372 | }); | |
c2d0a26f AT |
373 | |
374 | d_lw->writeFunction("getregisteredname", [](const DNSName &dname) { | |
375 | return getRegisteredName(dname); | |
376 | }); | |
70c21c40 | 377 | } |
a3e7b735 | 378 | |
70c21c40 | 379 | void RecursorLua4::postLoad() { |
0a273054 | 380 | d_prerpz = d_lw->readVariable<boost::optional<luacall_t>>("prerpz").get_value_or(0); |
a3e7b735 | 381 | d_preresolve = d_lw->readVariable<boost::optional<luacall_t>>("preresolve").get_value_or(0); |
382 | d_nodata = d_lw->readVariable<boost::optional<luacall_t>>("nodata").get_value_or(0); | |
383 | d_nxdomain = d_lw->readVariable<boost::optional<luacall_t>>("nxdomain").get_value_or(0); | |
384 | d_postresolve = d_lw->readVariable<boost::optional<luacall_t>>("postresolve").get_value_or(0); | |
f90c7544 | 385 | d_preoutquery = d_lw->readVariable<boost::optional<luacall_t>>("preoutquery").get_value_or(0); |
a2f87dd1 | 386 | d_maintenance = d_lw->readVariable<boost::optional<luamaintenance_t>>("maintenance").get_value_or(0); |
f90c7544 | 387 | |
388 | d_ipfilter = d_lw->readVariable<boost::optional<ipfilter_t>>("ipfilter").get_value_or(0); | |
81c0afd8 | 389 | d_gettag = d_lw->readVariable<boost::optional<gettag_t>>("gettag").get_value_or(0); |
70fb28d9 | 390 | d_gettag_ffi = d_lw->readVariable<boost::optional<gettag_ffi_t>>("gettag_ffi").get_value_or(0); |
808c5ef7 | 391 | } |
392 | ||
c4e71b7c OM |
393 | void RecursorLua4::getFeatures(Features & features) { |
394 | // Add key-values pairs below. | |
ef2ea4bf | 395 | // Make sure you add string values explicitly converted to string. |
c4e71b7c OM |
396 | // e.g. features.push_back(make_pair("somekey", string("stringvalue")); |
397 | // Both int and double end up as a lua number type. | |
398 | features.push_back(make_pair("PR8001_devicename", true)); | |
399 | } | |
400 | ||
a2f87dd1 CHB |
401 | void RecursorLua4::maintenance() const |
402 | { | |
403 | if (d_maintenance) { | |
404 | d_maintenance(); | |
405 | } | |
406 | } | |
407 | ||
5899ee54 | 408 | bool RecursorLua4::prerpz(DNSQuestion& dq, int& ret) const |
0a273054 | 409 | { |
ba21fcfe | 410 | return genhook(d_prerpz, dq, ret); |
0a273054 RG |
411 | } |
412 | ||
5899ee54 | 413 | bool RecursorLua4::preresolve(DNSQuestion& dq, int& ret) const |
808c5ef7 | 414 | { |
ba21fcfe | 415 | return genhook(d_preresolve, dq, ret); |
a3e7b735 | 416 | } |
417 | ||
5899ee54 | 418 | bool RecursorLua4::nxdomain(DNSQuestion& dq, int& ret) const |
a3e7b735 | 419 | { |
ba21fcfe | 420 | return genhook(d_nxdomain, dq, ret); |
a3e7b735 | 421 | } |
422 | ||
5899ee54 | 423 | bool RecursorLua4::nodata(DNSQuestion& dq, int& ret) const |
a3e7b735 | 424 | { |
ba21fcfe | 425 | return genhook(d_nodata, dq, ret); |
a3e7b735 | 426 | } |
427 | ||
5899ee54 | 428 | bool RecursorLua4::postresolve(DNSQuestion& dq, int& ret) const |
a3e7b735 | 429 | { |
ba21fcfe | 430 | return genhook(d_postresolve, dq, ret); |
a3e7b735 | 431 | } |
432 | ||
5899ee54 | 433 | bool RecursorLua4::preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, int& ret) const |
a3e7b735 | 434 | { |
ba21fcfe RG |
435 | bool variableAnswer = false; |
436 | bool wantsRPZ = false; | |
f1c7929a RG |
437 | bool logQuery = false; |
438 | RecursorLua4::DNSQuestion dq(ns, requestor, query, qtype.getCode(), isTcp, variableAnswer, wantsRPZ, logQuery); | |
6e505c5e | 439 | dq.currentRecords = &res; |
ba21fcfe RG |
440 | |
441 | return genhook(d_preoutquery, dq, ret); | |
a3e7b735 | 442 | } |
443 | ||
5899ee54 | 444 | bool RecursorLua4::ipfilter(const ComboAddress& remote, const ComboAddress& local, const struct dnsheader& dh) const |
a3e7b735 | 445 | { |
446 | if(d_ipfilter) | |
f5062066 | 447 | return d_ipfilter(remote, local, dh); |
f90c7544 | 448 | return false; // don't block |
a3e7b735 | 449 | } |
450 | ||
163ed916 | 451 | unsigned int RecursorLua4::gettag(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::unordered_set<std::string>* policyTags, LuaContext::LuaObject& data, const EDNSOptionViewMap& ednsOptions, bool tcp, std::string& requestorId, std::string& deviceId, std::string& deviceName, std::string& routingTag, const std::vector<ProxyProtocolValue>& proxyProtocolValues) const |
81c0afd8 | 452 | { |
02b47f43 | 453 | if(d_gettag) { |
3bdc4508 RG |
454 | std::vector<std::pair<int, const ProxyProtocolValue*>> proxyProtocolValuesMap; |
455 | proxyProtocolValuesMap.reserve(proxyProtocolValues.size()); | |
456 | int num = 1; | |
457 | for (const auto& value : proxyProtocolValues) { | |
458 | proxyProtocolValuesMap.emplace_back(num++, &value); | |
459 | } | |
460 | ||
461 | auto ret = d_gettag(remote, ednssubnet, local, qname, qtype, ednsOptions, tcp, proxyProtocolValuesMap); | |
02b47f43 RG |
462 | |
463 | if (policyTags) { | |
464 | const auto& tags = std::get<1>(ret); | |
465 | if (tags) { | |
b502d522 | 466 | policyTags->reserve(policyTags->size() + tags->size()); |
02b47f43 | 467 | for (const auto& tag : *tags) { |
b502d522 | 468 | policyTags->insert(tag.second); |
02b47f43 RG |
469 | } |
470 | } | |
471 | } | |
5fd2577f | 472 | const auto dataret = std::get<2>(ret); |
05c74122 RG |
473 | if (dataret) { |
474 | data = *dataret; | |
475 | } | |
67e31ebe RG |
476 | const auto reqIdret = std::get<3>(ret); |
477 | if (reqIdret) { | |
478 | requestorId = *reqIdret; | |
479 | } | |
590388d2 NC |
480 | const auto deviceIdret = std::get<4>(ret); |
481 | if (deviceIdret) { | |
482 | deviceId = *deviceIdret; | |
483 | } | |
0a6a45c8 CHB |
484 | |
485 | const auto deviceNameret = std::get<5>(ret); | |
486 | if (deviceNameret) { | |
487 | deviceName = *deviceNameret; | |
488 | } | |
163ed916 | 489 | |
941eea94 JS |
490 | const auto routingTarget = std::get<6>(ret); |
491 | if (routingTarget) { | |
492 | routingTag = *routingTarget; | |
163ed916 OM |
493 | } |
494 | ||
02b47f43 RG |
495 | return std::get<0>(ret); |
496 | } | |
81c0afd8 | 497 | return 0; |
498 | } | |
499 | ||
70fb28d9 RG |
500 | struct pdns_ffi_param |
501 | { | |
502 | public: | |
163ed916 | 503 | pdns_ffi_param(const DNSName& qname_, uint16_t qtype_, const ComboAddress& local_, const ComboAddress& remote_, const Netmask& ednssubnet_, std::unordered_set<std::string>& policyTags_, std::vector<DNSRecord>& records_, const EDNSOptionViewMap& ednsOptions_, const std::vector<ProxyProtocolValue>& proxyProtocolValues_, std::string& requestorId_, std::string& deviceId_, std::string& deviceName_, std::string& routingTag_, boost::optional<int>& rcode_, uint32_t& ttlCap_, bool& variable_, bool tcp_, bool& logQuery_, bool& logResponse_, bool& followCNAMERecords_): qname(qname_), local(local_), remote(remote_), ednssubnet(ednssubnet_), policyTags(policyTags_), records(records_), ednsOptions(ednsOptions_), proxyProtocolValues(proxyProtocolValues_), requestorId(requestorId_), deviceId(deviceId_), deviceName(deviceName_), routingTag(routingTag_), rcode(rcode_), ttlCap(ttlCap_), variable(variable_), logQuery(logQuery_), logResponse(logResponse_), followCNAMERecords(followCNAMERecords_), qtype(qtype_), tcp(tcp_) |
70fb28d9 RG |
504 | { |
505 | } | |
506 | ||
507 | std::unique_ptr<std::string> qnameStr{nullptr}; | |
508 | std::unique_ptr<std::string> localStr{nullptr}; | |
509 | std::unique_ptr<std::string> remoteStr{nullptr}; | |
510 | std::unique_ptr<std::string> ednssubnetStr{nullptr}; | |
511 | std::vector<pdns_ednsoption_t> ednsOptionsVect; | |
3bdc4508 | 512 | std::vector<pdns_proxyprotocol_value_t> proxyProtocolValuesVect; |
70fb28d9 RG |
513 | |
514 | const DNSName& qname; | |
515 | const ComboAddress& local; | |
516 | const ComboAddress& remote; | |
517 | const Netmask& ednssubnet; | |
b502d522 | 518 | std::unordered_set<std::string>& policyTags; |
37a919d4 | 519 | std::vector<DNSRecord>& records; |
29e6303a | 520 | const EDNSOptionViewMap& ednsOptions; |
3bdc4508 | 521 | const std::vector<ProxyProtocolValue>& proxyProtocolValues; |
70fb28d9 RG |
522 | std::string& requestorId; |
523 | std::string& deviceId; | |
0a6a45c8 | 524 | std::string& deviceName; |
163ed916 | 525 | std::string& routingTag; |
37a919d4 | 526 | boost::optional<int>& rcode; |
70fb28d9 RG |
527 | uint32_t& ttlCap; |
528 | bool& variable; | |
f1c7929a | 529 | bool& logQuery; |
406b722e | 530 | bool& logResponse; |
37a919d4 | 531 | bool& followCNAMERecords; |
70fb28d9 RG |
532 | |
533 | unsigned int tag{0}; | |
534 | uint16_t qtype; | |
535 | bool tcp; | |
536 | }; | |
537 | ||
163ed916 | 538 | unsigned int RecursorLua4::gettag_ffi(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::unordered_set<std::string>* policyTags, std::vector<DNSRecord>& records, LuaContext::LuaObject& data, const EDNSOptionViewMap& ednsOptions, bool tcp, const std::vector<ProxyProtocolValue>& proxyProtocolValues, std::string& requestorId, std::string& deviceId, std::string& deviceName, std::string& routingTag, boost::optional<int>& rcode, uint32_t& ttlCap, bool& variable, bool& logQuery, bool& logResponse, bool& followCNAMERecords) const |
70fb28d9 RG |
539 | { |
540 | if (d_gettag_ffi) { | |
163ed916 | 541 | pdns_ffi_param_t param(qname, qtype, local, remote, ednssubnet, *policyTags, records, ednsOptions, proxyProtocolValues, requestorId, deviceId, deviceName, routingTag, rcode, ttlCap, variable, tcp, logQuery, logResponse, followCNAMERecords); |
70fb28d9 RG |
542 | |
543 | auto ret = d_gettag_ffi(¶m); | |
544 | if (ret) { | |
545 | data = *ret; | |
546 | } | |
547 | ||
548 | return param.tag; | |
549 | } | |
550 | return 0; | |
551 | } | |
552 | ||
5899ee54 | 553 | bool RecursorLua4::genhook(const luacall_t& func, DNSQuestion& dq, int& ret) const |
a3e7b735 | 554 | { |
555 | if(!func) | |
808c5ef7 | 556 | return false; |
a3e7b735 | 557 | |
6e505c5e RG |
558 | if (dq.currentRecords) { |
559 | dq.records = *dq.currentRecords; | |
ba21fcfe | 560 | } else { |
6e505c5e | 561 | dq.records.clear(); |
ba21fcfe RG |
562 | } |
563 | ||
6e505c5e RG |
564 | dq.followupFunction.clear(); |
565 | dq.followupPrefix.clear(); | |
566 | dq.followupName.clear(); | |
567 | dq.udpQuery.clear(); | |
568 | dq.udpAnswer.clear(); | |
569 | dq.udpCallback.clear(); | |
ba21fcfe | 570 | |
6e505c5e | 571 | dq.rcode = ret; |
1c567515 | 572 | bool handled=func(&dq); |
2205c52b | 573 | |
a3e7b735 | 574 | if(handled) { |
f9e5e573 | 575 | loop:; |
6e505c5e | 576 | ret=dq.rcode; |
d2f97f2a | 577 | |
6e505c5e RG |
578 | if(!dq.followupFunction.empty()) { |
579 | if(dq.followupFunction=="followCNAMERecords") { | |
580 | ret = followCNAMERecords(dq.records, QType(dq.qtype)); | |
a3e7b735 | 581 | } |
6e505c5e | 582 | else if(dq.followupFunction=="getFakeAAAARecords") { |
ef3ee606 | 583 | ret=getFakeAAAARecords(dq.followupName, ComboAddress(dq.followupPrefix), dq.records); |
a3e7b735 | 584 | } |
6e505c5e | 585 | else if(dq.followupFunction=="getFakePTRRecords") { |
ef3ee606 | 586 | ret=getFakePTRRecords(dq.followupName, dq.records); |
a3e7b735 | 587 | } |
6e505c5e RG |
588 | else if(dq.followupFunction=="udpQueryResponse") { |
589 | dq.udpAnswer = GenUDPQueryResponse(dq.udpQueryDest, dq.udpQuery); | |
dd079764 RG |
590 | auto cbFunc = d_lw->readVariable<boost::optional<luacall_t>>(dq.udpCallback).get_value_or(0); |
591 | if(!cbFunc) { | |
e6a9dde5 | 592 | g_log<<Logger::Error<<"Attempted callback for Lua UDP Query/Response which could not be found"<<endl; |
6b8b26c8 | 593 | return false; |
d2f97f2a | 594 | } |
dd079764 | 595 | bool result=cbFunc(&dq); |
ba21fcfe | 596 | if(!result) { |
d2f97f2a | 597 | return false; |
598 | } | |
599 | goto loop; | |
f90c7544 | 600 | } |
a3e7b735 | 601 | } |
6e505c5e RG |
602 | if (dq.currentRecords) { |
603 | *dq.currentRecords = dq.records; | |
ba21fcfe | 604 | } |
a3e7b735 | 605 | } |
606 | ||
a3e7b735 | 607 | // see if they added followup work for us too |
608 | return handled; | |
609 | } | |
3dcc3fde | 610 | |
3dcc3fde | 611 | RecursorLua4::~RecursorLua4(){} |
70fb28d9 RG |
612 | |
613 | const char* pdns_ffi_param_get_qname(pdns_ffi_param_t* ref) | |
614 | { | |
615 | if (!ref->qnameStr) { | |
616 | ref->qnameStr = std::unique_ptr<std::string>(new std::string(ref->qname.toStringNoDot())); | |
617 | } | |
618 | ||
619 | return ref->qnameStr->c_str(); | |
620 | } | |
621 | ||
aedec560 RG |
622 | void pdns_ffi_param_get_qname_raw(pdns_ffi_param_t* ref, const char** qname, size_t* qnameSize) |
623 | { | |
624 | const auto& storage = ref->qname.getStorage(); | |
625 | *qname = storage.data(); | |
626 | *qnameSize = storage.size(); | |
627 | } | |
628 | ||
70fb28d9 RG |
629 | uint16_t pdns_ffi_param_get_qtype(const pdns_ffi_param_t* ref) |
630 | { | |
631 | return ref->qtype; | |
632 | } | |
633 | ||
634 | const char* pdns_ffi_param_get_remote(pdns_ffi_param_t* ref) | |
635 | { | |
636 | if (!ref->remoteStr) { | |
637 | ref->remoteStr = std::unique_ptr<std::string>(new std::string(ref->remote.toString())); | |
638 | } | |
639 | ||
640 | return ref->remoteStr->c_str(); | |
641 | } | |
642 | ||
aedec560 RG |
643 | static void pdns_ffi_comboaddress_to_raw(const ComboAddress& ca, const void** addr, size_t* addrSize) |
644 | { | |
645 | if (ca.isIPv4()) { | |
646 | *addr = &ca.sin4.sin_addr.s_addr; | |
647 | *addrSize = sizeof(ca.sin4.sin_addr.s_addr); | |
648 | } | |
649 | else { | |
650 | *addr = &ca.sin6.sin6_addr.s6_addr; | |
651 | *addrSize = sizeof(ca.sin6.sin6_addr.s6_addr); | |
652 | } | |
653 | } | |
654 | ||
655 | void pdns_ffi_param_get_remote_raw(pdns_ffi_param_t* ref, const void** addr, size_t* addrSize) | |
656 | { | |
657 | pdns_ffi_comboaddress_to_raw(ref->remote, addr, addrSize); | |
658 | } | |
659 | ||
70fb28d9 RG |
660 | uint16_t pdns_ffi_param_get_remote_port(const pdns_ffi_param_t* ref) |
661 | { | |
662 | return ref->remote.getPort(); | |
663 | } | |
664 | ||
665 | const char* pdns_ffi_param_get_local(pdns_ffi_param_t* ref) | |
666 | { | |
667 | if (!ref->localStr) { | |
668 | ref->localStr = std::unique_ptr<std::string>(new std::string(ref->local.toString())); | |
669 | } | |
670 | ||
671 | return ref->localStr->c_str(); | |
672 | } | |
673 | ||
aedec560 RG |
674 | void pdns_ffi_param_get_local_raw(pdns_ffi_param_t* ref, const void** addr, size_t* addrSize) |
675 | { | |
676 | pdns_ffi_comboaddress_to_raw(ref->local, addr, addrSize); | |
677 | } | |
678 | ||
70fb28d9 RG |
679 | uint16_t pdns_ffi_param_get_local_port(const pdns_ffi_param_t* ref) |
680 | { | |
681 | return ref->local.getPort(); | |
682 | } | |
683 | ||
684 | const char* pdns_ffi_param_get_edns_cs(pdns_ffi_param_t* ref) | |
685 | { | |
686 | if (ref->ednssubnet.empty()) { | |
687 | return nullptr; | |
688 | } | |
689 | ||
690 | if (!ref->ednssubnetStr) { | |
691 | ref->ednssubnetStr = std::unique_ptr<std::string>(new std::string(ref->ednssubnet.toStringNoMask())); | |
692 | } | |
693 | ||
694 | return ref->ednssubnetStr->c_str(); | |
695 | } | |
696 | ||
aedec560 RG |
697 | void pdns_ffi_param_get_edns_cs_raw(pdns_ffi_param_t* ref, const void** net, size_t* netSize) |
698 | { | |
699 | if (ref->ednssubnet.empty()) { | |
700 | *net = nullptr; | |
701 | *netSize = 0; | |
702 | return; | |
703 | } | |
704 | ||
705 | pdns_ffi_comboaddress_to_raw(ref->ednssubnet.getNetwork(), net, netSize); | |
706 | } | |
707 | ||
70fb28d9 RG |
708 | uint8_t pdns_ffi_param_get_edns_cs_source_mask(const pdns_ffi_param_t* ref) |
709 | { | |
710 | return ref->ednssubnet.getBits(); | |
711 | } | |
712 | ||
29e6303a | 713 | static void fill_edns_option(const EDNSOptionViewValue& value, pdns_ednsoption_t& option) |
70fb28d9 | 714 | { |
29e6303a | 715 | option.len = value.size; |
70fb28d9 RG |
716 | option.data = nullptr; |
717 | ||
29e6303a RG |
718 | if (value.size > 0) { |
719 | option.data = value.content; | |
70fb28d9 RG |
720 | } |
721 | } | |
722 | ||
723 | size_t pdns_ffi_param_get_edns_options(pdns_ffi_param_t* ref, const pdns_ednsoption_t** out) | |
724 | { | |
725 | if (ref->ednsOptions.empty()) { | |
726 | return 0; | |
727 | } | |
728 | ||
29e6303a RG |
729 | size_t totalCount = 0; |
730 | for (const auto& option : ref->ednsOptions) { | |
731 | totalCount += option.second.values.size(); | |
732 | } | |
733 | ||
734 | ref->ednsOptionsVect.resize(totalCount); | |
70fb28d9 RG |
735 | |
736 | size_t pos = 0; | |
29e6303a RG |
737 | for (const auto& option : ref->ednsOptions) { |
738 | for (const auto& entry : option.second.values) { | |
739 | fill_edns_option(entry, ref->ednsOptionsVect.at(pos)); | |
740 | ref->ednsOptionsVect.at(pos).optionCode = option.first; | |
741 | pos++; | |
742 | } | |
70fb28d9 RG |
743 | } |
744 | ||
745 | *out = ref->ednsOptionsVect.data(); | |
746 | ||
29e6303a | 747 | return totalCount; |
70fb28d9 RG |
748 | } |
749 | ||
750 | size_t pdns_ffi_param_get_edns_options_by_code(pdns_ffi_param_t* ref, uint16_t optionCode, const pdns_ednsoption_t** out) | |
751 | { | |
752 | const auto& it = ref->ednsOptions.find(optionCode); | |
29e6303a | 753 | if (it == ref->ednsOptions.cend() || it->second.values.empty()) { |
70fb28d9 RG |
754 | return 0; |
755 | } | |
756 | ||
29e6303a RG |
757 | ref->ednsOptionsVect.resize(it->second.values.size()); |
758 | ||
759 | size_t pos = 0; | |
760 | for (const auto& entry : it->second.values) { | |
761 | fill_edns_option(entry, ref->ednsOptionsVect.at(pos)); | |
762 | ref->ednsOptionsVect.at(pos).optionCode = optionCode; | |
763 | pos++; | |
764 | } | |
70fb28d9 RG |
765 | |
766 | *out = ref->ednsOptionsVect.data(); | |
767 | ||
29e6303a | 768 | return pos; |
70fb28d9 RG |
769 | } |
770 | ||
3bdc4508 RG |
771 | size_t pdns_ffi_param_get_proxy_protocol_values(pdns_ffi_param_t* ref, const pdns_proxyprotocol_value_t** out) |
772 | { | |
773 | if (ref->proxyProtocolValues.empty()) { | |
774 | return 0; | |
775 | } | |
776 | ||
777 | ref->proxyProtocolValuesVect.resize(ref->proxyProtocolValues.size()); | |
778 | ||
779 | size_t pos = 0; | |
780 | for (const auto& value : ref->proxyProtocolValues) { | |
781 | auto& dest = ref->proxyProtocolValuesVect.at(pos); | |
782 | dest.type = value.type; | |
783 | dest.len = value.content.size(); | |
784 | if (dest.len > 0) { | |
785 | dest.data = value.content.data(); | |
786 | } | |
787 | pos++; | |
788 | } | |
789 | ||
790 | *out = ref->proxyProtocolValuesVect.data(); | |
791 | ||
792 | return ref->proxyProtocolValuesVect.size(); | |
793 | } | |
794 | ||
70fb28d9 RG |
795 | void pdns_ffi_param_set_tag(pdns_ffi_param_t* ref, unsigned int tag) |
796 | { | |
797 | ref->tag = tag; | |
798 | } | |
799 | ||
800 | void pdns_ffi_param_add_policytag(pdns_ffi_param_t *ref, const char* name) | |
801 | { | |
b502d522 | 802 | ref->policyTags.insert(std::string(name)); |
70fb28d9 RG |
803 | } |
804 | ||
805 | void pdns_ffi_param_set_requestorid(pdns_ffi_param_t* ref, const char* name) | |
806 | { | |
807 | ref->requestorId = std::string(name); | |
808 | } | |
809 | ||
810 | void pdns_ffi_param_set_devicename(pdns_ffi_param_t* ref, const char* name) | |
811 | { | |
0a6a45c8 | 812 | ref->deviceName = std::string(name); |
70fb28d9 RG |
813 | } |
814 | ||
815 | void pdns_ffi_param_set_deviceid(pdns_ffi_param_t* ref, size_t len, const void* name) | |
816 | { | |
817 | ref->deviceId = std::string(reinterpret_cast<const char*>(name), len); | |
818 | } | |
819 | ||
163ed916 OM |
820 | void pdns_ffi_param_set_routingtag(pdns_ffi_param_t* ref, const char* rtag) |
821 | { | |
822 | ref->routingTag = std::string(rtag); | |
823 | } | |
824 | ||
70fb28d9 RG |
825 | void pdns_ffi_param_set_variable(pdns_ffi_param_t* ref, bool variable) |
826 | { | |
827 | ref->variable = variable; | |
828 | } | |
829 | ||
830 | void pdns_ffi_param_set_ttl_cap(pdns_ffi_param_t* ref, uint32_t ttl) | |
831 | { | |
832 | ref->ttlCap = ttl; | |
833 | } | |
f1c7929a RG |
834 | |
835 | void pdns_ffi_param_set_log_query(pdns_ffi_param_t* ref, bool logQuery) | |
836 | { | |
837 | ref->logQuery = logQuery; | |
838 | } | |
37a919d4 | 839 | |
406b722e RG |
840 | void pdns_ffi_param_set_log_response(pdns_ffi_param_t* ref, bool logResponse) |
841 | { | |
842 | ref->logResponse = logResponse; | |
843 | } | |
844 | ||
37a919d4 RG |
845 | void pdns_ffi_param_set_rcode(pdns_ffi_param_t* ref, int rcode) |
846 | { | |
847 | ref->rcode = rcode; | |
848 | } | |
849 | ||
850 | void pdns_ffi_param_set_follow_cname_records(pdns_ffi_param_t* ref, bool follow) | |
851 | { | |
852 | ref->followCNAMERecords = follow; | |
853 | } | |
854 | ||
855 | bool pdns_ffi_param_add_record(pdns_ffi_param_t *ref, const char* name, uint16_t type, uint32_t ttl, const char* content, size_t contentSize, pdns_record_place_t place) | |
856 | { | |
857 | try { | |
858 | DNSRecord dr; | |
32aa5e9b | 859 | dr.d_name = name != nullptr ? DNSName(name) : ref->qname; |
37a919d4 RG |
860 | dr.d_ttl = ttl; |
861 | dr.d_type = type; | |
862 | dr.d_class = QClass::IN; | |
863 | dr.d_place = DNSResourceRecord::Place(place); | |
864 | dr.d_content = DNSRecordContent::mastermake(type, QClass::IN, std::string(content, contentSize)); | |
865 | ref->records.push_back(std::move(dr)); | |
866 | ||
867 | return true; | |
868 | } | |
869 | catch (const std::exception& e) { | |
870 | g_log<<Logger::Error<<"Error attempting to add a record from Lua via pdns_ffi_param_add_record(): "<<e.what()<<endl; | |
871 | return false; | |
872 | } | |
873 | } |