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

PowerDNS / pdns / 12595591960

03 Jan 2025 09:27AM UTC coverage: 62.774% (+2.5%) from 60.245%
12595591960

Pull #15008

github

web-flow
Merge c2a2749d3 into 788f396a7
Pull Request #15008: Do not follow CNAME records for ANY or CNAME queries

30393 of 78644 branches covered (38.65%)

Branch coverage included in aggregate %.

105822 of 138350 relevant lines covered (76.49%)

4613078.44 hits per line

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

90.32
/pdns/recursordist/lua-recursor4.hh
1
/*
2
 * This file is part of PowerDNS or dnsdist.
3
 * Copyright -- PowerDNS.COM B.V. and its contributors
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of version 2 of the GNU General Public License as
7
 * published by the Free Software Foundation.
8
 *
9
 * In addition, for the avoidance of any doubt, permission is granted to
10
 * link this program with OpenSSL and to (re)distribute the binaries
11
 * produced as the result of such linking.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
 */
22
#pragma once
23

24
#ifdef HAVE_CONFIG_H
25
#include "config.h"
26
#endif
27

28
#include "iputils.hh"
29
#include "dnsname.hh"
30
#include "namespaces.hh"
31
#include "dnsrecords.hh"
32
#include "filterpo.hh"
33
#include "ednsoptions.hh"
34
#include "validate.hh"
35
#include "lua-base4.hh"
36
#include "proxy-protocol.hh"
37
#include "noinitvector.hh"
38
#include "rec-eventtrace.hh"
39

40
#include <unordered_map>
41

42
#include "lua-recursor4-ffi.hh"
43

44
// pdns_ffi_param_t is a lightuserdata
45
template <>
46
struct LuaContext::Pusher<pdns_ffi_param*>
47
{
48
  static const int minSize = 1;
49
  static const int maxSize = 1;
50

51
  static PushedObject push(lua_State* state, pdns_ffi_param* ptr) noexcept
52
  {
65✔
53
    lua_pushlightuserdata(state, ptr);
65✔
54
    return PushedObject{state, 1};
65✔
55
  }
65✔
56
};
57

58
// pdns_postresolve_ffi_handle is a lightuserdata
59
template <>
60
struct LuaContext::Pusher<pdns_postresolve_ffi_handle*>
61
{
62
  static const int minSize = 1;
63
  static const int maxSize = 1;
64

65
  static PushedObject push(lua_State* state, pdns_postresolve_ffi_handle* ptr) noexcept
66
  {
7✔
67
    lua_pushlightuserdata(state, ptr);
7✔
68
    return PushedObject{state, 1};
7✔
69
  }
7✔
70
};
71

72
class RecursorLua4 : public BaseLua4
73
{
74
public:
75
  RecursorLua4(const std::string& includePath = "") :
76
    BaseLua4(includePath)
77
  {
122✔
78
    prepareContext();
122✔
79
  };
122✔
80
  RecursorLua4(const RecursorLua4&) = delete;
81
  RecursorLua4(RecursorLua4&&) = delete;
82
  RecursorLua4& operator=(const RecursorLua4&) = delete;
83
  RecursorLua4& operator=(RecursorLua4&&) = delete;
84
  ~RecursorLua4() override; // this is so unique_ptr works with an incomplete type
85

86
  struct MetaValue
87
  {
88
    std::unordered_set<std::string> stringVal;
89
    std::unordered_set<int64_t> intVal;
90
  };
91
  struct DNSQuestion
92
  {
93
    // NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
94
    DNSQuestion(const ComboAddress& prem, const ComboAddress& ploc, const ComboAddress& rem, const ComboAddress& loc, const DNSName& query, uint16_t type, bool tcp, bool& variable_, bool& wantsRPZ_, bool& logResponse_, bool& addPaddingToResponse_, const struct timeval& queryTime_) :
95
      qname(query), interface_local(ploc), interface_remote(prem), local(loc), remote(rem), variable(variable_), wantsRPZ(wantsRPZ_), logResponse(logResponse_), addPaddingToResponse(addPaddingToResponse_), queryTime(queryTime_), qtype(type), isTcp(tcp)
96
    {
2,391✔
97
    }
2,391✔
98
    const DNSName& qname;
99
    const ComboAddress& interface_local;
100
    const ComboAddress& interface_remote;
101
    const ComboAddress& local;
102
    const ComboAddress& remote;
103
    const ComboAddress* fromAuthIP{nullptr};
104
    const struct dnsheader* dh{nullptr};
105
    const std::vector<pair<uint16_t, string>>* ednsOptions{nullptr};
106
    const uint16_t* ednsFlags{nullptr};
107
    vector<DNSRecord>* currentRecords{nullptr};
108
    DNSFilterEngine::Policy* appliedPolicy{nullptr};
109
    std::unordered_set<std::string>* policyTags{nullptr};
110
    const std::vector<ProxyProtocolValue>* proxyProtocolValues{nullptr};
111
    std::unordered_map<std::string, bool>* discardedPolicies{nullptr};
112
    std::string* extendedErrorExtra{nullptr};
113
    boost::optional<uint16_t>* extendedErrorCode{nullptr};
114
    std::string requestorId;
115
    std::string deviceId;
116
    std::string deviceName;
117
    bool& variable;
118
    bool& wantsRPZ;
119
    bool& logResponse;
120
    bool& addPaddingToResponse;
121
    std::map<std::string, MetaValue> meta;
122
    struct timeval queryTime;
123

124
    vector<DNSRecord> records;
125

126
    string followupFunction;
127
    string followupPrefix;
128

129
    string udpQuery;
130
    string udpAnswer;
131
    string udpCallback;
132

133
    LuaContext::LuaObject data;
134
    DNSName followupName;
135
    ComboAddress udpQueryDest;
136

137
    unsigned int tag{0};
138
    int rcode{0};
139
    const uint16_t qtype;
140
    const bool isTcp;
141
    vState validationState{vState::Indeterminate};
142

143
    void addAnswer(uint16_t type, const std::string& content, boost::optional<int> ttl, boost::optional<string> name);
144
    void addRecord(uint16_t type, const std::string& content, DNSResourceRecord::Place place, boost::optional<int> ttl, boost::optional<string> name);
145
    [[nodiscard]] vector<pair<int, DNSRecord>> getRecords() const;
146
    [[nodiscard]] boost::optional<dnsheader> getDH() const;
147
    [[nodiscard]] vector<pair<uint16_t, string>> getEDNSOptions() const;
148
    [[nodiscard]] boost::optional<string> getEDNSOption(uint16_t code) const;
149
    [[nodiscard]] boost::optional<Netmask> getEDNSSubnet() const;
150
    [[nodiscard]] std::vector<std::pair<int, ProxyProtocolValue>> getProxyProtocolValues() const;
151
    [[nodiscard]] vector<string> getEDNSFlags() const;
152
    [[nodiscard]] bool getEDNSFlag(const string& flag) const;
153
    void setRecords(const vector<pair<int, DNSRecord>>& arg);
154
  };
155

156
  struct PolicyEvent
157
  {
158
    PolicyEvent(const ComboAddress& rem, const DNSName& name, const QType& type, bool tcp) :
159
      qname(name), qtype(type), remote(rem), isTcp(tcp)
160
    {
2✔
161
    }
2✔
162
    const DNSName& qname;
163
    const QType qtype;
164
    const ComboAddress& remote;
165
    const bool isTcp;
166
    DNSFilterEngine::Policy* appliedPolicy{nullptr};
167
    std::unordered_set<std::string>* policyTags{nullptr};
168
    std::unordered_map<std::string, bool>* discardedPolicies{nullptr};
169
  };
170

171
  struct FFIParams
172
  {
173
  public:
174
    // NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
175
    FFIParams(const DNSName& qname_, uint16_t qtype_, const ComboAddress& plocal_, const ComboAddress& premote_, const ComboAddress& local_, const ComboAddress& remote_, const Netmask& ednssubnet_, LuaContext::LuaObject& data_, 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_, boost::optional<uint16_t>& extendedErrorCode_, std::string& extendedErrorExtra_, bool& disablePadding_, std::map<std::string, MetaValue>& meta_) :
176
      data(data_), qname(qname_), interface_local(plocal_), interface_remote(premote_), local(local_), remote(remote_), ednssubnet(ednssubnet_), policyTags(policyTags_), records(records_), ednsOptions(ednsOptions_), proxyProtocolValues(proxyProtocolValues_), requestorId(requestorId_), deviceId(deviceId_), deviceName(deviceName_), routingTag(routingTag_), extendedErrorExtra(extendedErrorExtra_), rcode(rcode_), extendedErrorCode(extendedErrorCode_), ttlCap(ttlCap_), variable(variable_), logQuery(logQuery_), logResponse(logResponse_), followCNAMERecords(followCNAMERecords_), disablePadding(disablePadding_), qtype(qtype_), tcp(tcp_), meta(meta_)
177
    {
65✔
178
    }
65✔
179

180
    LuaContext::LuaObject& data;
181
    const DNSName& qname;
182
    const ComboAddress& interface_local;
183
    const ComboAddress& interface_remote;
184
    const ComboAddress& local;
185
    const ComboAddress& remote;
186
    const Netmask& ednssubnet;
187
    std::unordered_set<std::string>& policyTags;
188
    std::vector<DNSRecord>& records;
189
    const EDNSOptionViewMap& ednsOptions;
190
    const std::vector<ProxyProtocolValue>& proxyProtocolValues;
191
    std::string& requestorId;
192
    std::string& deviceId;
193
    std::string& deviceName;
194
    std::string& routingTag;
195
    std::string& extendedErrorExtra;
196
    boost::optional<int>& rcode;
197
    boost::optional<uint16_t>& extendedErrorCode;
198
    uint32_t& ttlCap;
199
    bool& variable;
200
    bool& logQuery;
201
    bool& logResponse;
202
    bool& followCNAMERecords;
203
    bool& disablePadding;
204

205
    unsigned int tag{0};
206
    uint16_t qtype;
207
    bool tcp;
208

209
    std::map<std::string, MetaValue>& meta;
210
  };
211

212
  unsigned int 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&, bool tcp, std::string& requestorId, std::string& deviceId, std::string& deviceName, std::string& routingTag, const std::vector<ProxyProtocolValue>& proxyProtocolValues) const;
213
  unsigned int gettag_ffi(FFIParams&) const;
214

215
  void maintenance() const;
216
  bool prerpz(DNSQuestion& dnsQuestion, int& ret, RecEventTrace&) const;
217
  bool preresolve(DNSQuestion& dnsQuestion, int& ret, RecEventTrace&) const;
218
  bool nxdomain(DNSQuestion& dnsQuestion, int& ret, RecEventTrace&) const;
219
  bool nodata(DNSQuestion& dnsQuestion, int& ret, RecEventTrace&) const;
220
  bool postresolve(DNSQuestion& dnsQuestion, int& ret, RecEventTrace&) const;
221

222
  bool preoutquery(const ComboAddress& nameserver, const ComboAddress& requestor, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, int& ret, RecEventTrace& eventTrace, const struct timeval& theTime) const;
223
  bool ipfilter(const ComboAddress& remote, const ComboAddress& local, const struct dnsheader&, RecEventTrace&) const;
224

225
  bool policyHitEventFilter(const ComboAddress& remote, const DNSName& qname, const QType& qtype, bool tcp, DNSFilterEngine::Policy& policy, std::unordered_set<std::string>& tags, std::unordered_map<std::string, bool>& discardedPolicies) const;
226

227
  void runStartStopFunction(const std::string& script, bool start, Logr::log_t log);
228

229
  [[nodiscard]] bool needDQ() const
230
  {
×
231
    return (d_prerpz || d_preresolve || d_nxdomain || d_nodata || d_postresolve);
×
232
  }
×
233

234
  struct PostResolveFFIHandle
235
  {
236
    PostResolveFFIHandle(DNSQuestion& dnsQuestion) :
237
      d_dq(dnsQuestion)
238
    {
7✔
239
    }
7✔
240
    DNSQuestion& d_dq;
241
    bool d_ret{false};
242
  };
243
  bool postresolve_ffi(PostResolveFFIHandle&) const;
244

245
  [[nodiscard]] bool hasGettagFunc() const
246
  {
450✔
247
    return static_cast<bool>(d_gettag);
450✔
248
  }
450✔
249
  [[nodiscard]] bool hasGettagFFIFunc() const
250
  {
513✔
251
    return static_cast<bool>(d_gettag_ffi);
513✔
252
  }
513✔
253
  [[nodiscard]] bool hasPostResolveFFIfunc() const
254
  {
319✔
255
    return static_cast<bool>(d_postresolve_ffi);
319✔
256
  }
319✔
257

258
protected:
259
  void postPrepareContext() override;
260
  void postLoad() override;
261
  void getFeatures(Features& features) override;
262

263
private:
264
  using gettag_t = std::function<std::tuple<unsigned int, boost::optional<std::unordered_map<int, string>>, boost::optional<LuaContext::LuaObject>, boost::optional<std::string>, boost::optional<std::string>, boost::optional<std::string>, boost::optional<string>>(ComboAddress, Netmask, ComboAddress, DNSName, uint16_t, const EDNSOptionViewMap&, bool, const std::vector<std::pair<int, const ProxyProtocolValue*>>&)>;
265
  gettag_t d_gettag; // public so you can query if we have this hooked
266

267
  using gettag_ffi_t = std::function<boost::optional<LuaContext::LuaObject>(pdns_ffi_param_t*)>;
268
  gettag_ffi_t d_gettag_ffi;
269

270
  using postresolve_ffi_t = std::function<bool(pdns_postresolve_ffi_handle_t*)>;
271
  postresolve_ffi_t d_postresolve_ffi;
272

273
  using luamaintenance_t = std::function<void()>;
274
  luamaintenance_t d_maintenance;
275

276
  using luacall_t = std::function<bool(DNSQuestion*)>;
277
  luacall_t d_prerpz, d_preresolve, d_nxdomain, d_nodata, d_postresolve, d_preoutquery, d_postoutquery;
278
  bool genhook(const luacall_t& func, DNSQuestion& dnsQuestion, int& ret) const;
279

280
  using ipfilter_t = std::function<bool(ComboAddress, ComboAddress, struct dnsheader)>;
281
  ipfilter_t d_ipfilter;
282

283
  using policyEventFilter_t = std::function<bool(PolicyEvent&)>;
284
  policyEventFilter_t d_policyHitEventFilter;
285
};
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

© 2025 Coveralls, Inc