]>
Commit | Line | Data |
---|---|---|
6bb38cd6 RG |
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" | |
e7c732b8 | 23 | #include "dnsdist-ecs.hh" |
6bb38cd6 RG |
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; }); | |
29b6a412 CH |
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 | ); | |
6bb38cd6 | 55 | g_lua.registerFunction<bool(DNSQuestion::*)()>("getDO", [](const DNSQuestion& dq) { |
e7c732b8 | 56 | return getEDNSZ(dq) & EDNS_HEADER_FLAG_DO; |
6bb38cd6 | 57 | }); |
cbf4e13a RG |
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 | }); | |
7d243a5e RG |
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); | |
64cda3dd RG |
70 | return tail; |
71 | }); | |
7d243a5e RG |
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(); | |
bf11f6f0 | 76 | if(tailLen > (dq.size - messageLen)) { |
8ca2f50e RG |
77 | return false; |
78 | } | |
79 | ||
7d243a5e RG |
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); | |
8ca2f50e RG |
84 | } |
85 | return true; | |
86 | }); | |
cbf4e13a | 87 | |
15e21d84 RG |
88 | g_lua.registerFunction<std::string(DNSQuestion::*)()>("getServerNameIndication", [](const DNSQuestion& dq) { |
89 | return dq.sni; | |
90 | }); | |
91 | ||
6bb38cd6 RG |
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 | }); | |
acf86c7a | 99 | |
6bb38cd6 | 100 | g_lua.registerFunction<void(DNSQuestion::*)(std::string, std::string)>("setTag", [](DNSQuestion& dq, const std::string& strLabel, const std::string& strValue) { |
6bb38cd6 RG |
101 | if(dq.qTag == nullptr) { |
102 | dq.qTag = std::make_shared<QTag>(); | |
103 | } | |
15fac047 | 104 | dq.qTag->insert({strLabel, strValue}); |
6bb38cd6 RG |
105 | }); |
106 | g_lua.registerFunction<void(DNSQuestion::*)(vector<pair<string, string>>)>("setTagArray", [](DNSQuestion& dq, const vector<pair<string, string>>&tags) { | |
15fac047 | 107 | if (!dq.qTag) { |
6bb38cd6 RG |
108 | dq.qTag = std::make_shared<QTag>(); |
109 | } | |
110 | ||
111 | for (const auto& tag : tags) { | |
15fac047 | 112 | dq.qTag->insert({tag.first, tag.second}); |
6bb38cd6 | 113 | } |
6bb38cd6 RG |
114 | }); |
115 | g_lua.registerFunction<string(DNSQuestion::*)(std::string)>("getTag", [](const DNSQuestion& dq, const std::string& strLabel) { | |
15fac047 CH |
116 | if (!dq.qTag) { |
117 | return string(); | |
118 | } | |
6bb38cd6 RG |
119 | |
120 | std::string strValue; | |
15fac047 CH |
121 | const auto it = dq.qTag->find(strLabel); |
122 | if (it == dq.qTag->cend()) { | |
123 | return string(); | |
6bb38cd6 | 124 | } |
15fac047 | 125 | return it->second; |
6bb38cd6 | 126 | }); |
15fac047 CH |
127 | g_lua.registerFunction<QTag(DNSQuestion::*)(void)>("getTagArray", [](const DNSQuestion& dq) { |
128 | if (!dq.qTag) { | |
129 | QTag empty; | |
130 | return empty; | |
6bb38cd6 | 131 | } |
15fac047 CH |
132 | |
133 | return *dq.qTag; | |
6bb38cd6 RG |
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 | }); | |
7d243a5e RG |
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); | |
06f64918 RG |
156 | return tail; |
157 | }); | |
7d243a5e RG |
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(); | |
bf11f6f0 | 162 | if(tailLen > (dq.size - messageLen)) { |
06f64918 RG |
163 | return false; |
164 | } | |
165 | ||
7d243a5e RG |
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); | |
06f64918 RG |
170 | } |
171 | return true; | |
172 | }); | |
acf86c7a RG |
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 | ||
6bb38cd6 RG |
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 | }); | |
255abac6 RG |
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 | ||
b48db169 | 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) { |
255abac6 RG |
256 | if (dq.du == nullptr) { |
257 | return; | |
258 | } | |
9676d2a9 | 259 | dq.du->setHTTPResponse(statusCode, body, contentType ? *contentType : ""); |
255abac6 RG |
260 | }); |
261 | #endif /* HAVE_DNS_OVER_HTTPS */ | |
af9f750c RG |
262 | |
263 | g_lua.registerFunction<bool(DNSQuestion::*)(bool nxd, const std::string& zone, uint32_t ttl, const std::string& mname, const std::string& rname, uint32_t serial, uint32_t refresh, uint32_t retry, uint32_t expire, uint32_t minimum)>("setNegativeAndAdditionalSOA", [](DNSQuestion& dq, bool nxd, const std::string& zone, uint32_t ttl, const std::string& mname, const std::string& rname, uint32_t serial, uint32_t refresh, uint32_t retry, uint32_t expire, uint32_t minimum) { | |
264 | return setNegativeAndAdditionalSOA(dq, nxd, DNSName(zone), ttl, DNSName(mname), DNSName(rname), serial, refresh, retry, expire, minimum); | |
265 | }); | |
6bb38cd6 | 266 | } |