]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/lua-base4.cc
3 #include <unordered_set>
4 #include <unordered_map>
10 #include "dnsparser.hh"
11 #include "dnspacket.hh"
12 #include "namespaces.hh"
13 #include "ednssubnet.hh"
14 #include "lua-base4.hh"
15 #include "ext/luawrapper/include/LuaContext.hpp"
16 #include "dns_random.hh"
18 BaseLua4::BaseLua4() = default;
20 void BaseLua4::loadFile(const std::string
& fname
)
22 std::ifstream
ifs(fname
);
25 auto msg
= stringerror(ret
);
26 SLOG(g_log
<< Logger::Error
<< "Unable to read configuration file from '" << fname
<< "': " << msg
<< endl
,
27 g_slog
->withName("lua")->error(Logr::Error
, ret
, "Unable to read configuration file", "file", Logging::Loggable(fname
), "msg", Logging::Loggable(msg
)));
28 throw std::runtime_error(msg
);
33 void BaseLua4::loadString(const std::string
&script
) {
34 std::istringstream
iss(script
);
38 // By default no features
39 void BaseLua4::getFeatures(Features
&) { }
41 void BaseLua4::prepareContext() {
42 d_lw
= std::make_unique
<LuaContext
>();
44 // lua features available
46 getFeatures(features
);
47 d_lw
->writeVariable("pdns_features", features
);
50 d_lw
->registerFunction
<int(dnsheader::*)()>("getID", [](dnsheader
& dh
) { return ntohs(dh
.id
); });
51 d_lw
->registerFunction
<bool(dnsheader::*)()>("getCD", [](dnsheader
& dh
) { return dh
.cd
; });
52 d_lw
->registerFunction
<bool(dnsheader::*)()>("getTC", [](dnsheader
& dh
) { return dh
.tc
; });
53 d_lw
->registerFunction
<bool(dnsheader::*)()>("getRA", [](dnsheader
& dh
) { return dh
.ra
; });
54 d_lw
->registerFunction
<bool(dnsheader::*)()>("getAD", [](dnsheader
& dh
) { return dh
.ad
; });
55 d_lw
->registerFunction
<bool(dnsheader::*)()>("getAA", [](dnsheader
& dh
) { return dh
.aa
; });
56 d_lw
->registerFunction
<bool(dnsheader::*)()>("getRD", [](dnsheader
& dh
) { return dh
.rd
; });
57 d_lw
->registerFunction
<int(dnsheader::*)()>("getRCODE", [](dnsheader
& dh
) { return dh
.rcode
; });
58 d_lw
->registerFunction
<int(dnsheader::*)()>("getOPCODE", [](dnsheader
& dh
) { return dh
.opcode
; });
59 d_lw
->registerFunction
<int(dnsheader::*)()>("getQDCOUNT", [](dnsheader
& dh
) { return ntohs(dh
.qdcount
); });
60 d_lw
->registerFunction
<int(dnsheader::*)()>("getANCOUNT", [](dnsheader
& dh
) { return ntohs(dh
.ancount
); });
61 d_lw
->registerFunction
<int(dnsheader::*)()>("getNSCOUNT", [](dnsheader
& dh
) { return ntohs(dh
.nscount
); });
62 d_lw
->registerFunction
<int(dnsheader::*)()>("getARCOUNT", [](dnsheader
& dh
) { return ntohs(dh
.arcount
); });
65 d_lw
->writeFunction("newDN", [](const std::string
& dom
){ return DNSName(dom
); });
66 d_lw
->registerFunction("__lt", &DNSName::operator<);
67 d_lw
->registerFunction("canonCompare", &DNSName::canonCompare
);
68 d_lw
->registerFunction("makeRelative", &DNSName::makeRelative
);
69 d_lw
->registerFunction("isPartOf", &DNSName::isPartOf
);
70 d_lw
->registerFunction("getRawLabels", &DNSName::getRawLabels
);
71 d_lw
->registerFunction
<unsigned int(DNSName::*)()>("countLabels", [](const DNSName
& name
) { return name
.countLabels(); });
72 d_lw
->registerFunction
<size_t(DNSName::*)()>("wireLength", [](const DNSName
& name
) { return name
.wirelength(); });
73 d_lw
->registerFunction
<size_t(DNSName::*)()>("wirelength", [](const DNSName
& name
) { return name
.wirelength(); });
74 d_lw
->registerFunction
<bool(DNSName::*)(const std::string
&)>("equal", [](const DNSName
& lhs
, const std::string
& rhs
) { return lhs
==DNSName(rhs
); });
75 d_lw
->registerEqFunction(&DNSName::operator==);
76 d_lw
->registerToStringFunction
<string(DNSName::*)()>([](const DNSName
&dn
) { return dn
.toString(); });
77 d_lw
->registerFunction
<string(DNSName::*)()>("toString", [](const DNSName
&dn
) { return dn
.toString(); });
78 d_lw
->registerFunction
<string(DNSName::*)()>("toStringNoDot", [](const DNSName
&dn
) { return dn
.toStringNoDot(); });
79 d_lw
->registerFunction
<bool(DNSName::*)()>("chopOff", [](DNSName
&dn
) { return dn
.chopOff(); });
82 d_lw
->writeFunction("newDRR", [](const DNSName
& qname
, const string
& qtype
, const unsigned int ttl
, const string
& content
, boost::optional
<int> domain_id
, boost::optional
<int> auth
){
83 auto drr
= DNSResourceRecord();
87 drr
.setContent(content
);
89 drr
.domain_id
= *domain_id
;
94 d_lw
->registerEqFunction(&DNSResourceRecord::operator==);
95 d_lw
->registerFunction("__lt", &DNSResourceRecord::operator<);
96 d_lw
->registerToStringFunction
<string(DNSResourceRecord::*)()>([](const DNSResourceRecord
& rec
) { return rec
.getZoneRepresentation(); });
97 d_lw
->registerFunction
<string(DNSResourceRecord::*)()>("toString", [](const DNSResourceRecord
& rec
) { return rec
.getZoneRepresentation();} );
98 d_lw
->registerFunction
<DNSName(DNSResourceRecord::*)()>("qname", [](DNSResourceRecord
& rec
) { return rec
.qname
; });
99 d_lw
->registerFunction
<DNSName(DNSResourceRecord::*)()>("wildcardName", [](DNSResourceRecord
& rec
) { return rec
.wildcardname
; });
100 d_lw
->registerFunction
<string(DNSResourceRecord::*)()>("content", [](DNSResourceRecord
& rec
) { return rec
.content
; });
101 d_lw
->registerFunction
<time_t(DNSResourceRecord::*)()>("lastModified", [](DNSResourceRecord
& rec
) { return rec
.last_modified
; });
102 d_lw
->registerFunction
<uint32_t(DNSResourceRecord::*)()>("ttl", [](DNSResourceRecord
& rec
) { return rec
.ttl
; });
103 d_lw
->registerFunction
<uint32_t(DNSResourceRecord::*)()>("signttl", [](DNSResourceRecord
& rec
) { return rec
.signttl
; });
104 d_lw
->registerFunction
<int(DNSResourceRecord::*)()>("domainId", [](DNSResourceRecord
& rec
) { return rec
.domain_id
; });
105 d_lw
->registerFunction
<uint16_t(DNSResourceRecord::*)()>("qtype", [](DNSResourceRecord
& rec
) { return rec
.qtype
.getCode(); });
106 d_lw
->registerFunction
<uint16_t(DNSResourceRecord::*)()>("qclass", [](DNSResourceRecord
& rec
) { return rec
.qclass
; });
107 d_lw
->registerFunction
<uint8_t(DNSResourceRecord::*)()>("scopeMask", [](DNSResourceRecord
& rec
) { return rec
.scopeMask
; });
108 d_lw
->registerFunction
<bool(DNSResourceRecord::*)()>("auth", [](DNSResourceRecord
& rec
) { return rec
.auth
; });
109 d_lw
->registerFunction
<bool(DNSResourceRecord::*)()>("disabled", [](DNSResourceRecord
& rec
) { return rec
.disabled
; });
112 d_lw
->registerFunction
<bool(ComboAddress::*)()>("isIPv4", [](const ComboAddress
& ca
) { return ca
.sin4
.sin_family
== AF_INET
; });
113 d_lw
->registerFunction
<bool(ComboAddress::*)()>("isIPv6", [](const ComboAddress
& ca
) { return ca
.sin4
.sin_family
== AF_INET6
; });
114 d_lw
->registerFunction
<uint16_t(ComboAddress::*)()>("getPort", [](const ComboAddress
& ca
) { return ntohs(ca
.sin4
.sin_port
); } );
115 d_lw
->registerFunction
<bool(ComboAddress::*)()>("isMappedIPv4", [](const ComboAddress
& ca
) { return ca
.isMappedIPv4(); });
116 d_lw
->registerFunction
<ComboAddress(ComboAddress::*)()>("mapToIPv4", [](const ComboAddress
& ca
) { return ca
.mapToIPv4(); });
117 d_lw
->registerFunction
<void(ComboAddress::*)(unsigned int)>("truncate", [](ComboAddress
& ca
, unsigned int bits
) { ca
.truncate(bits
); });
118 d_lw
->registerFunction
<string(ComboAddress::*)()>("toString", [](const ComboAddress
& ca
) { return ca
.toString(); });
119 d_lw
->registerToStringFunction
<string(ComboAddress::*)()>([](const ComboAddress
& ca
) { return ca
.toString(); });
120 d_lw
->registerFunction
<string(ComboAddress::*)()>("toStringWithPort", [](const ComboAddress
& ca
) { return ca
.toStringWithPort(); });
121 d_lw
->registerFunction
<string(ComboAddress::*)()>("getRaw", [](const ComboAddress
& ca
) {
122 if(ca
.sin4
.sin_family
== AF_INET
) {
123 auto t
=ca
.sin4
.sin_addr
.s_addr
; return string((const char*)&t
, 4);
126 return string((const char*)&ca
.sin6
.sin6_addr
.s6_addr
, 16);
129 d_lw
->writeFunction("newCA", [](const std::string
& a
) { return ComboAddress(a
); });
130 d_lw
->writeFunction("newCAFromRaw", [](const std::string
& raw
, boost::optional
<uint16_t> port
) {
131 if (raw
.size() == 4) {
132 struct sockaddr_in sin4
;
133 memset(&sin4
, 0, sizeof(sin4
));
134 sin4
.sin_family
= AF_INET
;
135 memcpy(&sin4
.sin_addr
.s_addr
, raw
.c_str(), raw
.size());
137 sin4
.sin_port
= htons(*port
);
139 return ComboAddress(&sin4
);
141 else if (raw
.size() == 16) {
142 struct sockaddr_in6 sin6
;
143 memset(&sin6
, 0, sizeof(sin6
));
144 sin6
.sin6_family
= AF_INET6
;
145 memcpy(&sin6
.sin6_addr
.s6_addr
, raw
.c_str(), raw
.size());
147 sin6
.sin6_port
= htons(*port
);
149 return ComboAddress(&sin6
);
151 return ComboAddress();
153 typedef std::unordered_set
<ComboAddress
,ComboAddress::addressOnlyHash
,ComboAddress::addressOnlyEqual
> cas_t
;
154 d_lw
->registerFunction
<bool(ComboAddress::*)(const ComboAddress
&)>("equal", [](const ComboAddress
& lhs
, const ComboAddress
& rhs
) { return ComboAddress::addressOnlyEqual()(lhs
, rhs
); });
157 d_lw
->writeFunction("newCAS", []{ return cas_t(); });
158 d_lw
->registerFunction
<void(cas_t::*)(boost::variant
<string
,ComboAddress
, vector
<pair
<unsigned int,string
> > >)>("add",
159 [](cas_t
& cas
, const boost::variant
<string
,ComboAddress
,vector
<pair
<unsigned int,string
> > >& in
)
162 if(auto s
= boost::get
<string
>(&in
)) {
163 cas
.insert(ComboAddress(*s
));
165 else if(auto v
= boost::get
<vector
<pair
<unsigned int, string
> > >(&in
)) {
166 for(const auto& str
: *v
)
167 cas
.insert(ComboAddress(str
.second
));
170 cas
.insert(boost::get
<ComboAddress
>(in
));
172 catch(std::exception
& e
) {
173 SLOG(g_log
<<Logger::Error
<<e
.what()<<endl
,
174 g_slog
->withName("lua")->error(Logr::Error
, e
.what(), "Exception in newCAS", "exception", Logging::Loggable("std::exception")));
177 d_lw
->registerFunction
<bool(cas_t::*)(const ComboAddress
&)>("check",[](const cas_t
& cas
, const ComboAddress
&ca
) { return cas
.count(ca
)>0; });
180 d_lw
->writeFunction("newQType", [](const string
& s
) { QType q
; q
= s
; return q
; });
181 d_lw
->registerFunction("getCode", &QType::getCode
);
182 d_lw
->registerFunction("getName", &QType::toString
);
183 d_lw
->registerEqFunction
<bool(QType::*)(const QType
&)>([](const QType
& a
, const QType
& b
){ return a
== b
;}); // operator overloading confuses LuaContext
184 d_lw
->registerToStringFunction(&QType::toString
);
187 d_lw
->writeFunction("newNetmask", [](const string
& s
) { return Netmask(s
); });
188 d_lw
->registerFunction
<ComboAddress(Netmask::*)()>("getNetwork", [](const Netmask
& nm
) { return nm
.getNetwork(); } ); // const reference makes this necessary
189 d_lw
->registerFunction
<ComboAddress(Netmask::*)()>("getMaskedNetwork", [](const Netmask
& nm
) { return nm
.getMaskedNetwork(); } );
190 d_lw
->registerFunction("isIpv4", &Netmask::isIPv4
);
191 d_lw
->registerFunction("isIPv4", &Netmask::isIPv4
);
192 d_lw
->registerFunction("isIpv6", &Netmask::isIPv6
);
193 d_lw
->registerFunction("isIPv6", &Netmask::isIPv6
);
194 d_lw
->registerFunction("getBits", &Netmask::getBits
);
195 d_lw
->registerFunction("toString", &Netmask::toString
);
196 d_lw
->registerFunction("empty", &Netmask::empty
);
197 d_lw
->registerFunction("match", (bool (Netmask::*)(const string
&) const)&Netmask::match
);
198 d_lw
->registerEqFunction(&Netmask::operator==);
199 d_lw
->registerToStringFunction(&Netmask::toString
);
202 d_lw
->writeFunction("newNMG", [](boost::optional
<vector
<pair
<unsigned int, std::string
>>> masks
) {
203 auto nmg
= NetmaskGroup();
206 for(const auto& mask
: *masks
) {
207 nmg
.addMask(mask
.second
);
213 // d_lw->writeFunction("newNMG", []() { return NetmaskGroup(); });
214 d_lw
->registerFunction
<void(NetmaskGroup::*)(const std::string
&mask
)>("addMask", [](NetmaskGroup
&nmg
, const std::string
& mask
) { nmg
.addMask(mask
); });
215 d_lw
->registerFunction
<void(NetmaskGroup::*)(const vector
<pair
<unsigned int, std::string
>>&)>("addMasks", [](NetmaskGroup
&nmg
, const vector
<pair
<unsigned int, std::string
>>& masks
) { for(const auto& mask
: masks
) { nmg
.addMask(mask
.second
); } });
216 d_lw
->registerFunction("match", (bool (NetmaskGroup::*)(const ComboAddress
&) const)&NetmaskGroup::match
);
219 d_lw
->writeFunction("newDR", [](const DNSName
& name
, const std::string
& type
, unsigned int ttl
, const std::string
& content
, int place
) { QType qtype
; qtype
= type
; auto dr
= DNSRecord(); dr
.d_name
= name
; dr
.d_type
= qtype
.getCode(); dr
.d_ttl
= ttl
; dr
.setContent(shared_ptr
<DNSRecordContent
>(DNSRecordContent::make(dr
.d_type
, QClass::IN
, content
))); dr
.d_place
= static_cast<DNSResourceRecord::Place
>(place
); return dr
; });
220 d_lw
->registerMember("name", &DNSRecord::d_name
);
221 d_lw
->registerMember("type", &DNSRecord::d_type
);
222 d_lw
->registerMember("ttl", &DNSRecord::d_ttl
);
223 d_lw
->registerMember("place", &DNSRecord::d_place
);
224 d_lw
->registerFunction
<string(DNSRecord::*)()>("getContent", [](const DNSRecord
& dr
) { return dr
.getContent()->getZoneRepresentation(); });
225 d_lw
->registerFunction
<boost::optional
<ComboAddress
>(DNSRecord::*)()>("getCA", [](const DNSRecord
& dr
) {
226 boost::optional
<ComboAddress
> ret
;
228 if(auto arec
= getRR
<ARecordContent
>(dr
))
230 else if(auto aaaarec
= getRR
<AAAARecordContent
>(dr
))
231 ret
=aaaarec
->getCA(53);
234 d_lw
->registerFunction
<void (DNSRecord::*)(const std::string
&)>("changeContent", [](DNSRecord
& dr
, const std::string
& newContent
) { dr
.setContent(shared_ptr
<DNSRecordContent
>(DNSRecordContent::make(dr
.d_type
, 1, newContent
))); });
237 d_lw
->writeFunction("pdnslog", [](const std::string
& msg
, boost::optional
<int> loglevel
) {
238 SLOG(g_log
<< (Logger::Urgency
)loglevel
.get_value_or(Logger::Warning
) << msg
<<endl
,
239 g_slog
->withName("lua")->info(static_cast<Logr::Priority
>(loglevel
.get_value_or(Logr::Warning
)), msg
));
241 d_lw
->writeFunction("pdnsrandom", [](boost::optional
<uint32_t> maximum
) {
242 return maximum
? dns_random(*maximum
) : dns_random_uint32();
247 vector
<pair
<string
, int> > rcodes
= {{"NOERROR", RCode::NoError
},
248 {"FORMERR", RCode::FormErr
},
249 {"SERVFAIL", RCode::ServFail
},
250 {"NXDOMAIN", RCode::NXDomain
},
251 {"NOTIMP", RCode::NotImp
},
252 {"REFUSED", RCode::Refused
},
253 {"YXDOMAIN", RCode::YXDomain
},
254 {"YXRRSET", RCode::YXRRSet
},
255 {"NXRRSET", RCode::NXRRSet
},
256 {"NOTAUTH", RCode::NotAuth
},
257 {"NOTZONE", RCode::NotZone
},
258 {"DROP", -2 }}; // To give backport-incompatibility warning
259 for(const auto& rcode
: rcodes
)
260 d_pd
.push_back({rcode
.first
, rcode
.second
});
262 d_pd
.push_back({"place", in_t
{
269 d_pd
.push_back({"loglevels", in_t
{
270 {"Alert", LOG_ALERT
},
271 {"Critical", LOG_CRIT
},
272 {"Debug", LOG_DEBUG
},
273 {"Emergency", LOG_EMERG
},
275 {"Notice", LOG_NOTICE
},
276 {"Warning", LOG_WARNING
},
280 for(const auto& n
: QType::names
)
281 d_pd
.push_back({n
.first
, n
.second
});
283 d_lw
->registerMember("tv_sec", &timeval::tv_sec
);
284 d_lw
->registerMember("tv_usec", &timeval::tv_usec
);
286 postPrepareContext();
288 // so we can let postprepare do changes to this
289 d_lw
->writeVariable("pdns", d_pd
);
292 void BaseLua4::loadStream(std::istream
&is
) {
293 d_lw
->executeCode(is
);
298 BaseLua4::~BaseLua4() = default;