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