]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/lua-recursor4.hh
rec: Don't account chained queries more than once
[thirdparty/pdns.git] / pdns / 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 #include <unordered_map>
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include "iputils.hh"
31 #include "dnsname.hh"
32 #include "namespaces.hh"
33 #include "dnsrecords.hh"
34 #include "filterpo.hh"
35 #include "ednsoptions.hh"
36 #include "validate.hh"
37
38 #include "lua-recursor4-ffi.hh"
39
40 string GenUDPQueryResponse(const ComboAddress& dest, const string& query);
41 unsigned int getRecursorThreadId();
42
43 class LuaContext;
44
45 #if defined(HAVE_LUA)
46 #undef L
47 #include "ext/luawrapper/include/LuaContext.hpp"
48 #define L theL()
49 #endif
50
51 // pdns_ffi_param_t is a lightuserdata
52 template<>
53 struct LuaContext::Pusher<pdns_ffi_param*> {
54 static const int minSize = 1;
55 static const int maxSize = 1;
56
57 static PushedObject push(lua_State* state, pdns_ffi_param* ptr) noexcept {
58 lua_pushlightuserdata(state, ptr);
59 return PushedObject{state, 1};
60 }
61 };
62
63 class RecursorLua4 : public boost::noncopyable
64 {
65 private:
66 std::unique_ptr<LuaContext> d_lw; // this is way on top because it must get destroyed _last_
67
68 public:
69 explicit RecursorLua4(const std::string& fname);
70 ~RecursorLua4(); // this is so unique_ptr works with an incomplete type
71
72 struct DNSQuestion
73 {
74 DNSQuestion(const ComboAddress& rem, const ComboAddress& loc, const DNSName& query, uint16_t type, bool tcp, bool& variable_, bool& wantsRPZ_): qname(query), qtype(type), local(loc), remote(rem), isTcp(tcp), variable(variable_), wantsRPZ(wantsRPZ_)
75 {
76 }
77 const DNSName& qname;
78 const uint16_t qtype;
79 const ComboAddress& local;
80 const ComboAddress& remote;
81 const struct dnsheader* dh{nullptr};
82 const bool isTcp;
83 const std::vector<pair<uint16_t, string>>* ednsOptions{nullptr};
84 const uint16_t* ednsFlags{nullptr};
85 vector<DNSRecord>* currentRecords{nullptr};
86 DNSFilterEngine::Policy* appliedPolicy{nullptr};
87 std::vector<std::string>* policyTags{nullptr};
88 std::unordered_map<std::string,bool>* discardedPolicies{nullptr};
89 std::string requestorId;
90 std::string deviceId;
91 vState validationState{Indeterminate};
92 bool& variable;
93 bool& wantsRPZ;
94 unsigned int tag{0};
95
96 void addAnswer(uint16_t type, const std::string& content, boost::optional<int> ttl, boost::optional<string> name);
97 void addRecord(uint16_t type, const std::string& content, DNSResourceRecord::Place place, boost::optional<int> ttl, boost::optional<string> name);
98 vector<pair<int,DNSRecord> > getRecords() const;
99 boost::optional<dnsheader> getDH() const;
100 vector<pair<uint16_t, string> > getEDNSOptions() const;
101 boost::optional<string> getEDNSOption(uint16_t code) const;
102 boost::optional<Netmask> getEDNSSubnet() const;
103 vector<string> getEDNSFlags() const;
104 bool getEDNSFlag(string flag) const;
105 void setRecords(const vector<pair<int,DNSRecord> >& records);
106
107 int rcode{0};
108 // struct dnsheader, packet length would be great
109 vector<DNSRecord> records;
110
111 string followupFunction;
112 string followupPrefix;
113
114 string udpQuery;
115 ComboAddress udpQueryDest;
116 string udpAnswer;
117 string udpCallback;
118
119 LuaContext::LuaObject data;
120 DNSName followupName;
121 };
122
123 unsigned int 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 std::map<uint16_t, EDNSOptionView>&, bool tcp, std::string& requestorId, std::string& deviceId) const;
124 unsigned int 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 std::map<uint16_t, EDNSOptionView>&, bool tcp, std::string& requestorId, std::string& deviceId, uint32_t& ttlCap, bool& variable) const;
125
126 bool prerpz(DNSQuestion& dq, int& ret) const;
127 bool preresolve(DNSQuestion& dq, int& ret) const;
128 bool nxdomain(DNSQuestion& dq, int& ret) const;
129 bool nodata(DNSQuestion& dq, int& ret) const ;
130 bool postresolve(DNSQuestion& dq, int& ret) const;
131
132 bool preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, int& ret) const;
133 bool ipfilter(const ComboAddress& remote, const ComboAddress& local, const struct dnsheader&) const;
134
135 bool needDQ() const
136 {
137 return (d_prerpz ||
138 d_preresolve ||
139 d_nxdomain ||
140 d_nodata ||
141 d_postresolve);
142 }
143
144 typedef 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> >(ComboAddress, Netmask, ComboAddress, DNSName, uint16_t, const std::map<uint16_t, EDNSOptionView>&, bool)> gettag_t;
145 gettag_t d_gettag; // public so you can query if we have this hooked
146
147 typedef std::function<boost::optional<LuaContext::LuaObject>(pdns_ffi_param_t*)> gettag_ffi_t;
148 gettag_ffi_t d_gettag_ffi;
149
150 private:
151 typedef std::function<bool(DNSQuestion*)> luacall_t;
152 luacall_t d_prerpz, d_preresolve, d_nxdomain, d_nodata, d_postresolve, d_preoutquery, d_postoutquery;
153 bool genhook(const luacall_t& func, DNSQuestion& dq, int& ret) const;
154 typedef std::function<bool(ComboAddress,ComboAddress, struct dnsheader)> ipfilter_t;
155 ipfilter_t d_ipfilter;
156 };
157