]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnsdist-lua-bindings-dnsquestion.cc
1b4709cbfccd4e3820be2cc99babd32419421219
[thirdparty/pdns.git] / pdns / dnsdist-lua-bindings-dnsquestion.cc
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 #include "dnsdist.hh"
23 #include "dnsdist-ecs.hh"
24 #include "dnsdist-lua.hh"
25 #include "dnsparser.hh"
26
27 void setupLuaBindingsDNSQuestion()
28 {
29 /* DNSQuestion */
30 /* PowerDNS DNSQuestion compat */
31 g_lua.registerMember<const ComboAddress (DNSQuestion::*)>("localaddr", [](const DNSQuestion& dq) -> const ComboAddress { return *dq.local; }, [](DNSQuestion& dq, const ComboAddress newLocal) { (void) newLocal; });
32 g_lua.registerMember<const DNSName (DNSQuestion::*)>("qname", [](const DNSQuestion& dq) -> const DNSName { return *dq.qname; }, [](DNSQuestion& dq, const DNSName newName) { (void) newName; });
33 g_lua.registerMember<uint16_t (DNSQuestion::*)>("qtype", [](const DNSQuestion& dq) -> uint16_t { return dq.qtype; }, [](DNSQuestion& dq, uint16_t newType) { (void) newType; });
34 g_lua.registerMember<uint16_t (DNSQuestion::*)>("qclass", [](const DNSQuestion& dq) -> uint16_t { return dq.qclass; }, [](DNSQuestion& dq, uint16_t newClass) { (void) newClass; });
35 g_lua.registerMember<int (DNSQuestion::*)>("rcode", [](const DNSQuestion& dq) -> int { return dq.dh->rcode; }, [](DNSQuestion& dq, int newRCode) { dq.dh->rcode = newRCode; });
36 g_lua.registerMember<const ComboAddress (DNSQuestion::*)>("remoteaddr", [](const DNSQuestion& dq) -> const ComboAddress { return *dq.remote; }, [](DNSQuestion& dq, const ComboAddress newRemote) { (void) newRemote; });
37 /* DNSDist DNSQuestion */
38 g_lua.registerMember("dh", &DNSQuestion::dh);
39 g_lua.registerMember<uint16_t (DNSQuestion::*)>("len", [](const DNSQuestion& dq) -> uint16_t { return dq.len; }, [](DNSQuestion& dq, uint16_t newlen) { dq.len = newlen; });
40 g_lua.registerMember<uint8_t (DNSQuestion::*)>("opcode", [](const DNSQuestion& dq) -> uint8_t { return dq.dh->opcode; }, [](DNSQuestion& dq, uint8_t newOpcode) { (void) newOpcode; });
41 g_lua.registerMember<size_t (DNSQuestion::*)>("size", [](const DNSQuestion& dq) -> size_t { return dq.size; }, [](DNSQuestion& dq, size_t newSize) { (void) newSize; });
42 g_lua.registerMember<bool (DNSQuestion::*)>("tcp", [](const DNSQuestion& dq) -> bool { return dq.tcp; }, [](DNSQuestion& dq, bool newTcp) { (void) newTcp; });
43 g_lua.registerMember<bool (DNSQuestion::*)>("skipCache", [](const DNSQuestion& dq) -> bool { return dq.skipCache; }, [](DNSQuestion& dq, bool newSkipCache) { dq.skipCache = newSkipCache; });
44 g_lua.registerMember<bool (DNSQuestion::*)>("useECS", [](const DNSQuestion& dq) -> bool { return dq.useECS; }, [](DNSQuestion& dq, bool useECS) { dq.useECS = useECS; });
45 g_lua.registerMember<bool (DNSQuestion::*)>("ecsOverride", [](const DNSQuestion& dq) -> bool { return dq.ecsOverride; }, [](DNSQuestion& dq, bool ecsOverride) { dq.ecsOverride = ecsOverride; });
46 g_lua.registerMember<uint16_t (DNSQuestion::*)>("ecsPrefixLength", [](const DNSQuestion& dq) -> uint16_t { return dq.ecsPrefixLength; }, [](DNSQuestion& dq, uint16_t newPrefixLength) { dq.ecsPrefixLength = newPrefixLength; });
47 g_lua.registerMember<boost::optional<uint32_t> (DNSQuestion::*)>("tempFailureTTL",
48 [](const DNSQuestion& dq) -> boost::optional<uint32_t> {
49 return dq.tempFailureTTL;
50 },
51 [](DNSQuestion& dq, boost::optional<uint32_t> newValue) {
52 dq.tempFailureTTL = newValue;
53 }
54 );
55 g_lua.registerFunction<bool(DNSQuestion::*)()>("getDO", [](const DNSQuestion& dq) {
56 return getEDNSZ(dq) & EDNS_HEADER_FLAG_DO;
57 });
58
59 g_lua.registerFunction<std::map<uint16_t, EDNSOptionView>(DNSQuestion::*)()>("getEDNSOptions", [](DNSQuestion& dq) {
60 if (dq.ednsOptions == nullptr) {
61 parseEDNSOptions(dq);
62 }
63
64 return *dq.ednsOptions;
65 });
66 g_lua.registerFunction<std::string(DNSQuestion::*)(void)>("getTrailingData", [](const DNSQuestion& dq) {
67 const char* message = reinterpret_cast<const char*>(dq.dh);
68 const uint16_t messageLen = getDNSPacketLength(message, dq.len);
69 const std::string tail = std::string(message + messageLen, dq.len - messageLen);
70 return tail;
71 });
72 g_lua.registerFunction<bool(DNSQuestion::*)(std::string)>("setTrailingData", [](DNSQuestion& dq, const std::string& tail) {
73 char* message = reinterpret_cast<char*>(dq.dh);
74 const uint16_t messageLen = getDNSPacketLength(message, dq.len);
75 const uint16_t tailLen = tail.size();
76 if(tailLen > (dq.size - messageLen)) {
77 return false;
78 }
79
80 /* Update length and copy data from the Lua string. */
81 dq.len = messageLen + tailLen;
82 if(tailLen > 0) {
83 tail.copy(message + messageLen, tailLen);
84 }
85 return true;
86 });
87
88 g_lua.registerFunction<std::string(DNSQuestion::*)()>("getServerNameIndication", [](const DNSQuestion& dq) {
89 return dq.sni;
90 });
91
92 g_lua.registerFunction<void(DNSQuestion::*)(std::string)>("sendTrap", [](const DNSQuestion& dq, boost::optional<std::string> reason) {
93 #ifdef HAVE_NET_SNMP
94 if (g_snmpAgent && g_snmpTrapsEnabled) {
95 g_snmpAgent->sendDNSTrap(dq, reason ? *reason : "");
96 }
97 #endif /* HAVE_NET_SNMP */
98 });
99
100 g_lua.registerFunction<void(DNSQuestion::*)(std::string, std::string)>("setTag", [](DNSQuestion& dq, const std::string& strLabel, const std::string& strValue) {
101 if(dq.qTag == nullptr) {
102 dq.qTag = std::make_shared<QTag>();
103 }
104 dq.qTag->insert({strLabel, strValue});
105 });
106 g_lua.registerFunction<void(DNSQuestion::*)(vector<pair<string, string>>)>("setTagArray", [](DNSQuestion& dq, const vector<pair<string, string>>&tags) {
107 if (!dq.qTag) {
108 dq.qTag = std::make_shared<QTag>();
109 }
110
111 for (const auto& tag : tags) {
112 dq.qTag->insert({tag.first, tag.second});
113 }
114 });
115 g_lua.registerFunction<string(DNSQuestion::*)(std::string)>("getTag", [](const DNSQuestion& dq, const std::string& strLabel) {
116 if (!dq.qTag) {
117 return string();
118 }
119
120 std::string strValue;
121 const auto it = dq.qTag->find(strLabel);
122 if (it == dq.qTag->cend()) {
123 return string();
124 }
125 return it->second;
126 });
127 g_lua.registerFunction<QTag(DNSQuestion::*)(void)>("getTagArray", [](const DNSQuestion& dq) {
128 if (!dq.qTag) {
129 QTag empty;
130 return empty;
131 }
132
133 return *dq.qTag;
134 });
135
136 /* LuaWrapper doesn't support inheritance */
137 g_lua.registerMember<const ComboAddress (DNSResponse::*)>("localaddr", [](const DNSResponse& dq) -> const ComboAddress { return *dq.local; }, [](DNSResponse& dq, const ComboAddress newLocal) { (void) newLocal; });
138 g_lua.registerMember<const DNSName (DNSResponse::*)>("qname", [](const DNSResponse& dq) -> const DNSName { return *dq.qname; }, [](DNSResponse& dq, const DNSName newName) { (void) newName; });
139 g_lua.registerMember<uint16_t (DNSResponse::*)>("qtype", [](const DNSResponse& dq) -> uint16_t { return dq.qtype; }, [](DNSResponse& dq, uint16_t newType) { (void) newType; });
140 g_lua.registerMember<uint16_t (DNSResponse::*)>("qclass", [](const DNSResponse& dq) -> uint16_t { return dq.qclass; }, [](DNSResponse& dq, uint16_t newClass) { (void) newClass; });
141 g_lua.registerMember<int (DNSResponse::*)>("rcode", [](const DNSResponse& dq) -> int { return dq.dh->rcode; }, [](DNSResponse& dq, int newRCode) { dq.dh->rcode = newRCode; });
142 g_lua.registerMember<const ComboAddress (DNSResponse::*)>("remoteaddr", [](const DNSResponse& dq) -> const ComboAddress { return *dq.remote; }, [](DNSResponse& dq, const ComboAddress newRemote) { (void) newRemote; });
143 g_lua.registerMember<dnsheader* (DNSResponse::*)>("dh", [](const DNSResponse& dr) -> dnsheader* { return dr.dh; }, [](DNSResponse& dr, dnsheader * newdh) { dr.dh = newdh; });
144 g_lua.registerMember<uint16_t (DNSResponse::*)>("len", [](const DNSResponse& dq) -> uint16_t { return dq.len; }, [](DNSResponse& dq, uint16_t newlen) { dq.len = newlen; });
145 g_lua.registerMember<uint8_t (DNSResponse::*)>("opcode", [](const DNSResponse& dq) -> uint8_t { return dq.dh->opcode; }, [](DNSResponse& dq, uint8_t newOpcode) { (void) newOpcode; });
146 g_lua.registerMember<size_t (DNSResponse::*)>("size", [](const DNSResponse& dq) -> size_t { return dq.size; }, [](DNSResponse& dq, size_t newSize) { (void) newSize; });
147 g_lua.registerMember<bool (DNSResponse::*)>("tcp", [](const DNSResponse& dq) -> bool { return dq.tcp; }, [](DNSResponse& dq, bool newTcp) { (void) newTcp; });
148 g_lua.registerMember<bool (DNSResponse::*)>("skipCache", [](const DNSResponse& dq) -> bool { return dq.skipCache; }, [](DNSResponse& dq, bool newSkipCache) { dq.skipCache = newSkipCache; });
149 g_lua.registerFunction<void(DNSResponse::*)(std::function<uint32_t(uint8_t section, uint16_t qclass, uint16_t qtype, uint32_t ttl)> editFunc)>("editTTLs", [](const DNSResponse& dr, std::function<uint32_t(uint8_t section, uint16_t qclass, uint16_t qtype, uint32_t ttl)> editFunc) {
150 editDNSPacketTTL((char*) dr.dh, dr.len, editFunc);
151 });
152 g_lua.registerFunction<std::string(DNSResponse::*)(void)>("getTrailingData", [](const DNSResponse& dq) {
153 const char* message = reinterpret_cast<const char*>(dq.dh);
154 const uint16_t messageLen = getDNSPacketLength(message, dq.len);
155 const std::string tail = std::string(message + messageLen, dq.len - messageLen);
156 return tail;
157 });
158 g_lua.registerFunction<bool(DNSResponse::*)(std::string)>("setTrailingData", [](DNSResponse& dq, const std::string& tail) {
159 char* message = reinterpret_cast<char*>(dq.dh);
160 const uint16_t messageLen = getDNSPacketLength(message, dq.len);
161 const uint16_t tailLen = tail.size();
162 if(tailLen > (dq.size - messageLen)) {
163 return false;
164 }
165
166 /* Update length and copy data from the Lua string. */
167 dq.len = messageLen + tailLen;
168 if(tailLen > 0) {
169 tail.copy(message + messageLen, tailLen);
170 }
171 return true;
172 });
173
174 g_lua.registerFunction<void(DNSResponse::*)(std::string, std::string)>("setTag", [](DNSResponse& dr, const std::string& strLabel, const std::string& strValue) {
175 if(dr.qTag == nullptr) {
176 dr.qTag = std::make_shared<QTag>();
177 }
178 dr.qTag->insert({strLabel, strValue});
179 });
180
181 g_lua.registerFunction<void(DNSResponse::*)(vector<pair<string, string>>)>("setTagArray", [](DNSResponse& dr, const vector<pair<string, string>>&tags) {
182 if (!dr.qTag) {
183 dr.qTag = std::make_shared<QTag>();
184 }
185
186 for (const auto& tag : tags) {
187 dr.qTag->insert({tag.first, tag.second});
188 }
189 });
190 g_lua.registerFunction<string(DNSResponse::*)(std::string)>("getTag", [](const DNSResponse& dr, const std::string& strLabel) {
191 if (!dr.qTag) {
192 return string();
193 }
194
195 std::string strValue;
196 const auto it = dr.qTag->find(strLabel);
197 if (it == dr.qTag->cend()) {
198 return string();
199 }
200 return it->second;
201 });
202 g_lua.registerFunction<QTag(DNSResponse::*)(void)>("getTagArray", [](const DNSResponse& dr) {
203 if (!dr.qTag) {
204 QTag empty;
205 return empty;
206 }
207
208 return *dr.qTag;
209 });
210
211 g_lua.registerFunction<void(DNSResponse::*)(std::string)>("sendTrap", [](const DNSResponse& dr, boost::optional<std::string> reason) {
212 #ifdef HAVE_NET_SNMP
213 if (g_snmpAgent && g_snmpTrapsEnabled) {
214 g_snmpAgent->sendDNSTrap(dr, reason ? *reason : "");
215 }
216 #endif /* HAVE_NET_SNMP */
217 });
218
219 #ifdef HAVE_DNS_OVER_HTTPS
220 g_lua.registerFunction<std::string(DNSQuestion::*)(void)>("getHTTPPath", [](const DNSQuestion& dq) {
221 if (dq.du == nullptr) {
222 return std::string();
223 }
224 return dq.du->getHTTPPath();
225 });
226
227 g_lua.registerFunction<std::string(DNSQuestion::*)(void)>("getHTTPQueryString", [](const DNSQuestion& dq) {
228 if (dq.du == nullptr) {
229 return std::string();
230 }
231 return dq.du->getHTTPQueryString();
232 });
233
234 g_lua.registerFunction<std::string(DNSQuestion::*)(void)>("getHTTPHost", [](const DNSQuestion& dq) {
235 if (dq.du == nullptr) {
236 return std::string();
237 }
238 return dq.du->getHTTPHost();
239 });
240
241 g_lua.registerFunction<std::string(DNSQuestion::*)(void)>("getHTTPScheme", [](const DNSQuestion& dq) {
242 if (dq.du == nullptr) {
243 return std::string();
244 }
245 return dq.du->getHTTPScheme();
246 });
247
248 g_lua.registerFunction<std::unordered_map<std::string, std::string>(DNSQuestion::*)(void)>("getHTTPHeaders", [](const DNSQuestion& dq) {
249 if (dq.du == nullptr) {
250 return std::unordered_map<std::string, std::string>();
251 }
252 return dq.du->getHTTPHeaders();
253 });
254
255 g_lua.registerFunction<void(DNSQuestion::*)(uint16_t statusCode, const std::string& body, const boost::optional<std::string> contentType)>("setHTTPResponse", [](DNSQuestion& dq, uint16_t statusCode, const std::string& body, const boost::optional<std::string> contentType) {
256 if (dq.du == nullptr) {
257 return;
258 }
259 dq.du->setHTTPResponse(statusCode, body, contentType ? *contentType : "");
260 });
261 #endif /* HAVE_DNS_OVER_HTTPS */
262 }