RecursorLua4::RecursorLua4() { prepareContext(); }
-static int followCNAMERecords(vector<DNSRecord>& ret, const QType& qtype)
-{
- vector<DNSRecord> resolved;
- DNSName target;
- for(const DNSRecord& rr : ret) {
- if(rr.d_type == QType::CNAME) {
- auto rec = getRR<CNAMERecordContent>(rr);
- if(rec) {
- target=rec->getTarget();
- break;
- }
- }
- }
- if(target.empty())
- return 0;
-
- int rcode=directResolve(target, qtype, 1, resolved); // 1 == class
-
- for(const DNSRecord& rr : resolved) {
- ret.push_back(rr);
- }
- return rcode;
-
-}
-
static int getFakeAAAARecords(const DNSName& qname, const std::string& prefix, vector<DNSRecord>& ret)
{
int rcode=directResolve(qname, QType(QType::A), 1, ret);
ComboAddress prefixAddress(prefix);
+ // Remove double CNAME records
+ std::set<DNSName> seenCNAMEs;
+ ret.erase(std::remove_if(
+ ret.begin(),
+ ret.end(),
+ [&seenCNAMEs](DNSRecord& rr) {
+ if (rr.d_type == QType::CNAME) {
+ auto target = getRR<CNAMERecordContent>(rr);
+ if (target == nullptr) {
+ return false;
+ }
+ if (seenCNAMEs.count(target->getTarget()) > 0) {
+ // We've had this CNAME before, remove it
+ return true;
+ }
+ seenCNAMEs.insert(target->getTarget());
+ }
+ return false;
+ }),
+ ret.end());
+
+ bool seenA = false;
for(DNSRecord& rr : ret)
{
if(rr.d_type == QType::A && rr.d_place==DNSResourceRecord::ANSWER) {
rr.d_content = std::make_shared<AAAARecordContent>(prefixAddress);
rr.d_type = QType::AAAA;
}
+ seenA = true;
}
}
+
+ if (seenA) {
+ // We've seen an A in the ANSWER section, so there is no need to keep any
+ // SOA in the AUTHORITY section as this is not a NODATA response.
+ ret.erase(std::remove_if(
+ ret.begin(),
+ ret.end(),
+ [](DNSRecord& rr) {
+ return (rr.d_type == QType::SOA && rr.d_place==DNSResourceRecord::AUTHORITY);
+ }),
+ ret.end());
+ }
return rcode;
}
d_lw->registerMember("rcode", &DNSQuestion::rcode);
d_lw->registerMember("tag", &DNSQuestion::tag);
d_lw->registerMember("requestorId", &DNSQuestion::requestorId);
+ d_lw->registerMember("deviceId", &DNSQuestion::deviceId);
+ d_lw->registerMember("deviceName", &DNSQuestion::deviceName);
d_lw->registerMember("followupFunction", &DNSQuestion::followupFunction);
d_lw->registerMember("followupPrefix", &DNSQuestion::followupPrefix);
d_lw->registerMember("followupName", &DNSQuestion::followupName);
d_lw->registerMember("size", &EDNSOptionViewValue::size);
d_lw->registerFunction<std::string(EDNSOptionViewValue::*)()>("getContent", [](const EDNSOptionViewValue& value) { return std::string(value.content, value.size); });
d_lw->registerFunction<size_t(EDNSOptionView::*)()>("count", [](const EDNSOptionView& option) { return option.values.size(); });
- d_lw->registerFunction<std::vector<std::pair<int, string>>(EDNSOptionView::*)()>("getValues", [] (const EDNSOptionView& option) {
- std::vector<std::pair<int, string> > values;
+ d_lw->registerFunction<std::vector<string>(EDNSOptionView::*)()>("getValues", [] (const EDNSOptionView& option) {
+ std::vector<string> values;
for (const auto& value : option.values) {
- values.push_back(std::make_pair(values.size(), std::string(value.content, value.size)));
+ values.push_back(std::string(value.content, value.size));
}
return values;
});
g_snmpAgent->sendCustomTrap(str);
}
});
+
+ d_lw->writeFunction("getregisteredname", [](const DNSName &dname) {
+ return getRegisteredName(dname);
+ });
}
void RecursorLua4::postLoad() {
return false; // don't block
}
-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) const
+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
{
if(d_gettag) {
auto ret = d_gettag(remote, ednssubnet, local, qname, qtype, ednsOptions, tcp);
if (deviceIdret) {
deviceId = *deviceIdret;
}
+
+ const auto deviceNameret = std::get<5>(ret);
+ if (deviceNameret) {
+ deviceName = *deviceNameret;
+ }
return std::get<0>(ret);
}
return 0;
struct pdns_ffi_param
{
public:
- pdns_ffi_param(const DNSName& qname_, uint16_t qtype_, const ComboAddress& local_, const ComboAddress& remote_, const Netmask& ednssubnet_, std::vector<std::string>& policyTags_, const EDNSOptionViewMap& ednsOptions_, std::string& requestorId_, std::string& deviceId_, uint32_t& ttlCap_, bool& variable_, bool tcp_, bool& logQuery_): qname(qname_), local(local_), remote(remote_), ednssubnet(ednssubnet_), policyTags(policyTags_), ednsOptions(ednsOptions_), requestorId(requestorId_), deviceId(deviceId_), ttlCap(ttlCap_), variable(variable_), logQuery(logQuery_), qtype(qtype_), tcp(tcp_)
+ 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_)
{
}
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& logQuery;
+ bool& logResponse;
+ bool& followCNAMERecords;
unsigned int tag{0};
uint16_t qtype;
bool tcp;
};
-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, LuaContext::LuaObject& data, const EDNSOptionViewMap& ednsOptions, bool tcp, std::string& requestorId, std::string& deviceId, uint32_t& ttlCap, bool& variable, bool& logQuery) const
+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
{
if (d_gettag_ffi) {
- pdns_ffi_param_t param(qname, qtype, local, remote, ednssubnet, *policyTags, ednsOptions, requestorId, deviceId, ttlCap, variable, tcp, logQuery);
+ pdns_ffi_param_t param(qname, qtype, local, remote, ednssubnet, *policyTags, records, ednsOptions, requestorId, deviceId, deviceName, rcode, ttlCap, variable, tcp, logQuery, logResponse, followCNAMERecords);
auto ret = d_gettag_ffi(¶m);
if (ret) {
void pdns_ffi_param_set_devicename(pdns_ffi_param_t* ref, const char* name)
{
- ref->deviceId = std::string(name);
+ ref->deviceName = std::string(name);
}
void pdns_ffi_param_set_deviceid(pdns_ffi_param_t* ref, size_t len, const void* name)
{
ref->logQuery = logQuery;
}
+
+void pdns_ffi_param_set_log_response(pdns_ffi_param_t* ref, bool logResponse)
+{
+ ref->logResponse = logResponse;
+}
+
+void pdns_ffi_param_set_rcode(pdns_ffi_param_t* ref, int rcode)
+{
+ ref->rcode = rcode;
+}
+
+void pdns_ffi_param_set_follow_cname_records(pdns_ffi_param_t* ref, bool follow)
+{
+ ref->followCNAMERecords = follow;
+}
+
+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)
+{
+ try {
+ DNSRecord dr;
+ dr.d_name = name != nullptr ? DNSName(name) : ref->qname;
+ dr.d_ttl = ttl;
+ dr.d_type = type;
+ dr.d_class = QClass::IN;
+ dr.d_place = DNSResourceRecord::Place(place);
+ dr.d_content = DNSRecordContent::mastermake(type, QClass::IN, std::string(content, contentSize));
+ ref->records.push_back(std::move(dr));
+
+ return true;
+ }
+ catch (const std::exception& e) {
+ g_log<<Logger::Error<<"Error attempting to add a record from Lua via pdns_ffi_param_add_record(): "<<e.what()<<endl;
+ return false;
+ }
+}