• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PowerDNS / pdns / 22225698541

20 Feb 2026 01:20PM UTC coverage: 70.913% (-0.7%) from 71.654%
22225698541

Pull #16693

github

web-flow
Merge 12ab81d89 into da25f7afd
Pull Request #16693: auth: plumbing for structured logging

45342 of 79966 branches covered (56.7%)

Branch coverage included in aggregate %.

892 of 2611 new or added lines in 70 files covered. (34.16%)

390 existing lines in 48 files now uncovered.

130608 of 168156 relevant lines covered (77.67%)

7371735.34 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

49.36
/pdns/lua-auth4.cc
1
#include "config.h"
2
#include "ext/luawrapper/include/LuaContext.hpp"
3
#include "lua-auth4.hh"
4
#include "stubresolver.hh"
5
#include <fstream>
6
#include "logger.hh"
7
#include "dnsparser.hh"
8
#include "namespaces.hh"
9
#include "ednssubnet.hh"
10
#include <unordered_set>
11
#include "sstuff.hh"
12
#include <thread>
13

14
#include "ueberbackend.hh"
15

16
LuaContext* AuthLua4::getLua()
17
{
×
18
  return d_lw.get();
×
19
}
×
20

21
void AuthLua4::postPrepareContext() {
474✔
22
  d_lw->writeFunction("resolve", [](const std::string& qname, uint16_t qtype) {
474✔
23
      std::vector<DNSZoneRecord> ret;
×
24
      std::unordered_map<int, DNSResourceRecord> luaResult;
×
NEW
25
      std::shared_ptr<Logr::Logger> slog;
×
NEW
26
      if (g_slogStructured) {
×
NEW
27
        slog = g_slog->withName("lua");
×
NEW
28
      }
×
NEW
29
      stubDoResolve(slog, DNSName(qname), qtype, ret);
×
30
      int i = 0;
×
31
      for(const auto &row: ret) {
×
32
        luaResult[++i] = DNSResourceRecord::fromWire(row.dr);
×
33
        luaResult[i].auth = row.auth;
×
34
      }
×
35
      return luaResult;
×
36
  });
×
37

38
/* DNSPacket */
39
  d_lw->registerFunction<DNSPacket, int(const char *, size_t)>("noparse", [](DNSPacket &p, const char *mesg, size_t len){ return p.noparse(mesg, len); });
474✔
40
  d_lw->registerFunction<DNSPacket, int(const char *, size_t)>("parse", [](DNSPacket &p, const char *mesg, size_t len){ return p.parse(mesg, len); });
474✔
41
  d_lw->registerFunction<DNSPacket, const std::string()>("getString", [](DNSPacket &p) { return p.getString(); });
474✔
42
  d_lw->registerFunction<DNSPacket, void(const ComboAddress&)>("setRemote", [](DNSPacket &p, const ComboAddress &ca) { p.setRemote(&ca); });
474✔
43
  d_lw->registerFunction<DNSPacket, ComboAddress()>("getRemote", [](DNSPacket &p) { return p.getInnerRemote(); });
97,164✔
44
  d_lw->registerFunction<DNSPacket, Netmask()>("getRealRemote", [](DNSPacket &p) { return p.getRealRemote(); });
474✔
45
  d_lw->registerFunction<DNSPacket, ComboAddress()>("getLocal", [](DNSPacket &p) { return p.getLocal(); });
474✔
46
  d_lw->registerFunction<DNSPacket, unsigned int()>("getRemotePort", [](DNSPacket &p) { return p.getInnerRemote().getPort(); });
474✔
47
  d_lw->registerFunction<DNSPacket, std::tuple<const std::string, unsigned int>()>("getQuestion", [](DNSPacket &p) { return std::tuple(p.qdomain.toString(), static_cast<unsigned int>(p.qtype.getCode())); });
97,153✔
48
  d_lw->registerFunction<DNSPacket, void(bool)>("setA", [](DNSPacket &p, bool a) { return p.setA(a); });
474✔
49
  d_lw->registerFunction<DNSPacket, void(unsigned int)>("setID", [](DNSPacket &p, unsigned int id) { return p.setID(static_cast<uint16_t>(id)); });
474✔
50
  d_lw->registerFunction<DNSPacket, void(bool)>("setRA", [](DNSPacket &p, bool ra) { return p.setRA(ra); });
474✔
51
  d_lw->registerFunction<DNSPacket, void(bool)>("setRD", [](DNSPacket &p, bool rd) { return p.setRD(rd); });
474✔
52
  d_lw->registerFunction<DNSPacket, void(bool)>("setAnswer", [](DNSPacket &p, bool answer) { return p.setAnswer(answer); });
474✔
53
  d_lw->registerFunction<DNSPacket, void(unsigned int)>("setOpCode", [](DNSPacket &p, unsigned int opcode) { return p.setOpcode(static_cast<uint16_t>(opcode)); });
474✔
54
  d_lw->registerFunction<DNSPacket, void(int)>("setRcode", [](DNSPacket &p, int rcode) { return p.setRcode(rcode); });
474✔
55
  d_lw->registerFunction<DNSPacket, void()>("clearRecords",[](DNSPacket &p){p.clearRecords();});
474✔
56
  d_lw->registerFunction<DNSPacket, void(DNSRecord&, bool)>("addRecord", [](DNSPacket &p, DNSRecord &dr, bool auth) { DNSZoneRecord dzr; dzr.dr = dr; dzr.auth = auth; p.addRecord(std::move(dzr)); });
474✔
57
  d_lw->registerFunction<DNSPacket, void(const vector<pair<unsigned int, DNSRecord> >&)>("addRecords", [](DNSPacket &p, const vector<pair<unsigned int, DNSRecord> >& records){ for(const auto &dr: records){ DNSZoneRecord dzr; dzr.dr = std::get<1>(dr); dzr.auth = true; p.addRecord(std::move(dzr)); }});
474!
58
  d_lw->registerFunction<DNSPacket, void(unsigned int, const DNSName&, const std::string&)>("setQuestion", [](DNSPacket &p, unsigned int opcode, const DNSName &name, const string &type){ QType qtype; qtype = type; p.setQuestion(static_cast<int>(opcode), name, static_cast<int>(qtype.getCode())); });
474✔
59
  d_lw->registerFunction<DNSPacket, bool()>("isEmpty", [](DNSPacket &p){return p.isEmpty();});
474✔
60
  d_lw->registerFunction<DNSPacket, std::shared_ptr<DNSPacket>()>("replyPacket",[](DNSPacket& p){ return p.replyPacket();});
474✔
61
  d_lw->registerFunction<DNSPacket, bool()>("hasEDNSSubnet", [](DNSPacket &p){return p.hasEDNSSubnet();});
474✔
62
  d_lw->registerFunction<DNSPacket, bool()>("hasEDNS",[](DNSPacket &p){return p.hasEDNS();});
474✔
63
  d_lw->registerFunction<DNSPacket, unsigned int()>("getEDNSVersion",[](DNSPacket &p){return p.getEDNSVersion();});
474✔
64
  d_lw->registerFunction<DNSPacket, void(unsigned int)>("setEDNSRcode",[](DNSPacket &p, unsigned int extRCode){p.setEDNSRcode(static_cast<uint16_t>(extRCode));});
474✔
65
  d_lw->registerFunction<DNSPacket, unsigned int()>("getEDNSRcode",[](DNSPacket &p){return p.getEDNSRCode();});
474✔
66
  d_lw->registerFunction<DNSPacket, DNSName()>("getTSIGKeyname",[](DNSPacket &p){ return p.getTSIGKeyname();});
474✔
67
  d_lw->registerFunction<DNSPacket, std::unordered_map<unsigned int, DNSRecord>()>("getRRS", [](DNSPacket &p){ std::unordered_map<unsigned int, DNSRecord> ret; unsigned int i = 0; for(const auto &rec: p.getRRS()) { ret.insert({i++, rec.dr}); } return ret;});
474!
68
  d_lw->registerMember<DNSPacket, DNSName>("qdomain", [](const DNSPacket &p) -> DNSName { return p.qdomain; }, [](DNSPacket &p, const DNSName& name) { p.qdomain = name; });
474✔
69
  d_lw->registerMember<DNSPacket, DNSName>("qdomainwild", [](const DNSPacket &p) -> DNSName { return p.qdomainwild; }, [](DNSPacket &p, const DNSName& name) { p.qdomainwild = name; });
474✔
70
  d_lw->registerMember<DNSPacket, DNSName>("qdomainzone", [](const DNSPacket &pkt) -> DNSName { return pkt.qdomainzone.operator const DNSName&(); }, [](DNSPacket &pkt, const DNSName& name) { pkt.qdomainzone = ZoneName(name); });
474✔
71

72
  d_lw->registerMember<DNSPacket, std::string>("d_peer_principal", [](const DNSPacket &p) -> std::string { return p.d_peer_principal; }, [](DNSPacket &p, const std::string &princ) { p.d_peer_principal = princ; });
474✔
73
  d_lw->registerMember<DNSPacket, const std::string>("qtype", [](const DNSPacket &p) ->  const std::string { return p.qtype.toString(); }, [](DNSPacket &p, const std::string &type) { p.qtype = type; });
474✔
74
/* End of DNSPacket */
75

76

77
/* update policy */
78
  d_lw->registerFunction<DNSName(UpdatePolicyQuery::*)()>("getQName", [](UpdatePolicyQuery& upq) { return upq.qname; });
474✔
79
  d_lw->registerFunction<DNSName(UpdatePolicyQuery::*)()>("getZoneName", [](UpdatePolicyQuery& upq) { return upq.zonename; });
474✔
80
  d_lw->registerFunction<uint16_t(UpdatePolicyQuery::*)()>("getQType", [](UpdatePolicyQuery& upq) { return upq.qtype; });
474✔
81
  d_lw->registerFunction<ComboAddress(UpdatePolicyQuery::*)()>("getLocal", [](UpdatePolicyQuery& upq) { return upq.local; });
474✔
82
  d_lw->registerFunction<ComboAddress(UpdatePolicyQuery::*)()>("getRemote", [](UpdatePolicyQuery& upq) { return upq.remote; });
474✔
83
  d_lw->registerFunction<Netmask(UpdatePolicyQuery::*)()>("getRealRemote", [](UpdatePolicyQuery& upq) { return upq.realRemote; });
474✔
84
  d_lw->registerFunction<DNSName(UpdatePolicyQuery::*)()>("getTsigName", [](UpdatePolicyQuery& upq) { return upq.tsigName; });
474✔
85
  d_lw->registerFunction<std::string(UpdatePolicyQuery::*)()>("getPeerPrincipal", [](UpdatePolicyQuery& upq) { return upq.peerPrincipal; });
474✔
86
/* end of update policy */
87
  if (!d_include_path.empty()) {
474!
88
    includePath(d_include_path);
×
89
  }
×
90
}
474✔
91

92
void AuthLua4::postLoad() {
429✔
93
  d_update_policy = d_lw->readVariable<boost::optional<luacall_update_policy_t>>("updatepolicy").get_value_or(nullptr);
429✔
94
  d_axfr_filter = d_lw->readVariable<boost::optional<luacall_axfr_filter_t>>("axfrfilter").get_value_or(nullptr);
429✔
95
  d_prequery = d_lw->readVariable<boost::optional<luacall_prequery_t>>("prequery").get_value_or(nullptr);
429✔
96
}
429✔
97

98
bool AuthLua4::axfrfilter(const ComboAddress& remote, const DNSName& zone, const DNSResourceRecord& in, vector<DNSResourceRecord>& out) {
×
99
  if (!d_axfr_filter) {
×
100
    return false;
×
101
  }
×
102

103
  const auto& [rcode, rows] = d_axfr_filter(remote, zone, in);
×
104
  if (rcode < 0) {
×
105
    // no modification, handle normally
106
    return false;
×
107
  }
×
108
  else if (rcode == 0) {
×
109
    // replace the matching record by the filtered record(s)
110
  }
×
111
  else if (rcode == 1) {
×
112
    // append the filtered record(s) after the matching record
113
    out.push_back(in);
×
114
  }
×
115
  else
×
116
    throw PDNSException("Cannot understand return code "+std::to_string(rcode)+" in axfr filter response");
×
117

118
  try {
×
119
    for(const auto& row: rows) {
×
120
      DNSResourceRecord rec;
×
121

122
      const auto& map = row.second;
×
123
      rec.qtype = QType(boost::get<unsigned int>(map.at("qtype")));
×
124
      rec.qname = DNSName(boost::get<std::string>(map.at("qname")));
×
125
      rec.qname.makeUsLowerCase();
×
126
      if (map.count("ttl")) {
×
127
        rec.ttl = boost::get<unsigned int>(map.at("ttl"));
×
128
      }
×
129
      rec.setContent(boost::get<std::string>(map.at("content")));
×
130

131
      out.push_back(rec);
×
132
    }
×
133
  }
×
134
  catch (const std::exception& e) {
×
135
    throw PDNSException("Cannot understand axfr filter response: " + std::string(e.what()));
×
136
  }
×
137
  catch (const PDNSException& e) {
×
138
    throw PDNSException("Cannot understand axfr filter response: " + e.reason);
×
139
  }
×
140

141
  return true;
×
142
}
×
143

144

145
bool AuthLua4::updatePolicy(const DNSName &qname, const QType& qtype, const DNSName &zonename, const DNSPacket& packet) {
3✔
146
  // default decision is all goes
147
  if (d_update_policy == nullptr) return true;
3!
148

149
  UpdatePolicyQuery upq;
3✔
150
  upq.qname = qname;
3✔
151
  upq.qtype = qtype.getCode();
3✔
152
  upq.zonename = zonename;
3✔
153
  upq.local = packet.getLocal();
3✔
154
  upq.remote = packet.getInnerRemote();
3✔
155
  upq.realRemote = packet.getRealRemote();
3✔
156
  upq.tsigName = packet.getTSIGKeyname();
3✔
157
  upq.peerPrincipal = packet.d_peer_principal;
3✔
158

159
  return d_update_policy(upq);
3✔
160
}
3✔
161

162
std::unique_ptr<DNSPacket> AuthLua4::prequery(const DNSPacket& q) {
97,122✔
163
  if (d_prequery == nullptr) return nullptr;
97,122!
164

165
  auto r = q.replyPacket();
97,122✔
166
  if (d_prequery(r.get()))
97,122✔
167
    return r;
1✔
168

169
  return nullptr;
97,121✔
170
}
97,122✔
171

172
AuthLua4::~AuthLua4() = default;
19✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc