]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/lua-base4.cc
Merge pull request #8110 from zeha/urls-https
[thirdparty/pdns.git] / pdns / lua-base4.cc
1 #include <fstream>
2 #include <unordered_set>
3 #include <unordered_map>
4 #include <typeinfo>
5 #include "logger.hh"
6 #include "iputils.hh"
7 #include "dnsname.hh"
8 #include "dnsparser.hh"
9 #include "dnspacket.hh"
10 #include "namespaces.hh"
11 #include "ednssubnet.hh"
12 #include "lua-base4.hh"
13 #include "dns_random.hh"
14
15 BaseLua4::BaseLua4() {
16 }
17
18 void BaseLua4::loadFile(const std::string &fname) {
19 std::ifstream ifs(fname);
20 if(!ifs) {
21 g_log<<Logger::Error<<"Unable to read configuration file from '"<<fname<<"': "<<strerror(errno)<<endl;
22 return;
23 }
24 loadStream(ifs);
25 };
26
27 void BaseLua4::loadString(const std::string &script) {
28 std::istringstream iss(script);
29 loadStream(iss);
30 };
31
32 #if !defined(HAVE_LUA)
33
34 void BaseLua4::prepareContext() { return; }
35 void BaseLua4::loadStream(std::istream &is) { return; }
36 BaseLua4::~BaseLua4() { }
37
38 #else
39
40 #include "ext/luawrapper/include/LuaContext.hpp"
41
42 void BaseLua4::prepareContext() {
43 d_lw = std::unique_ptr<LuaContext>(new LuaContext);
44
45 // dnsheader
46 d_lw->registerFunction<int(dnsheader::*)()>("getID", [](dnsheader& dh) { return ntohs(dh.id); });
47 d_lw->registerFunction<bool(dnsheader::*)()>("getCD", [](dnsheader& dh) { return dh.cd; });
48 d_lw->registerFunction<bool(dnsheader::*)()>("getTC", [](dnsheader& dh) { return dh.tc; });
49 d_lw->registerFunction<bool(dnsheader::*)()>("getRA", [](dnsheader& dh) { return dh.ra; });
50 d_lw->registerFunction<bool(dnsheader::*)()>("getAD", [](dnsheader& dh) { return dh.ad; });
51 d_lw->registerFunction<bool(dnsheader::*)()>("getAA", [](dnsheader& dh) { return dh.aa; });
52 d_lw->registerFunction<bool(dnsheader::*)()>("getRD", [](dnsheader& dh) { return dh.rd; });
53 d_lw->registerFunction<int(dnsheader::*)()>("getRCODE", [](dnsheader& dh) { return dh.rcode; });
54 d_lw->registerFunction<int(dnsheader::*)()>("getOPCODE", [](dnsheader& dh) { return dh.opcode; });
55 d_lw->registerFunction<int(dnsheader::*)()>("getQDCOUNT", [](dnsheader& dh) { return ntohs(dh.qdcount); });
56 d_lw->registerFunction<int(dnsheader::*)()>("getANCOUNT", [](dnsheader& dh) { return ntohs(dh.ancount); });
57 d_lw->registerFunction<int(dnsheader::*)()>("getNSCOUNT", [](dnsheader& dh) { return ntohs(dh.nscount); });
58 d_lw->registerFunction<int(dnsheader::*)()>("getARCOUNT", [](dnsheader& dh) { return ntohs(dh.arcount); });
59
60 // DNSName
61 d_lw->writeFunction("newDN", [](const std::string& dom){ return DNSName(dom); });
62 d_lw->registerFunction("__lt", &DNSName::operator<);
63 d_lw->registerFunction("canonCompare", &DNSName::canonCompare);
64 d_lw->registerFunction("makeRelative", &DNSName::makeRelative);
65 d_lw->registerFunction("isPartOf", &DNSName::isPartOf);
66 d_lw->registerFunction("getRawLabels", &DNSName::getRawLabels);
67 d_lw->registerFunction<unsigned int(DNSName::*)()>("countLabels", [](const DNSName& name) { return name.countLabels(); });
68 d_lw->registerFunction<size_t(DNSName::*)()>("wireLength", [](const DNSName& name) { return name.wirelength(); });
69 d_lw->registerFunction<size_t(DNSName::*)()>("wirelength", [](const DNSName& name) { return name.wirelength(); });
70 d_lw->registerFunction<bool(DNSName::*)(const std::string&)>("equal", [](const DNSName& lhs, const std::string& rhs) { return lhs==DNSName(rhs); });
71 d_lw->registerEqFunction(&DNSName::operator==);
72 d_lw->registerToStringFunction<string(DNSName::*)()>([](const DNSName&dn ) { return dn.toString(); });
73 d_lw->registerFunction<string(DNSName::*)()>("toString", [](const DNSName&dn ) { return dn.toString(); });
74 d_lw->registerFunction<string(DNSName::*)()>("toStringNoDot", [](const DNSName&dn ) { return dn.toStringNoDot(); });
75 d_lw->registerFunction<bool(DNSName::*)()>("chopOff", [](DNSName&dn ) { return dn.chopOff(); });
76
77 // DNSResourceRecord
78 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){
79 auto drr = DNSResourceRecord();
80 drr.qname = qname;
81 drr.qtype = qtype;
82 drr.ttl = ttl;
83 drr.setContent(content);
84 if (domain_id)
85 drr.domain_id = *domain_id;
86 if (auth)
87 drr.auth = *auth;
88 return drr;
89 });
90 d_lw->registerEqFunction(&DNSResourceRecord::operator==);
91 d_lw->registerFunction("__lt", &DNSResourceRecord::operator<);
92 d_lw->registerToStringFunction<string(DNSResourceRecord::*)()>([](const DNSResourceRecord& rec) { return rec.getZoneRepresentation(); });
93 d_lw->registerFunction<string(DNSResourceRecord::*)()>("toString", [](const DNSResourceRecord& rec) { return rec.getZoneRepresentation();} );
94 d_lw->registerFunction<DNSName(DNSResourceRecord::*)()>("qname", [](DNSResourceRecord& rec) { return rec.qname; });
95 d_lw->registerFunction<DNSName(DNSResourceRecord::*)()>("wildcardName", [](DNSResourceRecord& rec) { return rec.wildcardname; });
96 d_lw->registerFunction<string(DNSResourceRecord::*)()>("content", [](DNSResourceRecord& rec) { return rec.content; });
97 d_lw->registerFunction<time_t(DNSResourceRecord::*)()>("lastModified", [](DNSResourceRecord& rec) { return rec.last_modified; });
98 d_lw->registerFunction<uint32_t(DNSResourceRecord::*)()>("ttl", [](DNSResourceRecord& rec) { return rec.ttl; });
99 d_lw->registerFunction<uint32_t(DNSResourceRecord::*)()>("signttl", [](DNSResourceRecord& rec) { return rec.signttl; });
100 d_lw->registerFunction<int(DNSResourceRecord::*)()>("domainId", [](DNSResourceRecord& rec) { return rec.domain_id; });
101 d_lw->registerFunction<uint16_t(DNSResourceRecord::*)()>("qtype", [](DNSResourceRecord& rec) { return rec.qtype.getCode(); });
102 d_lw->registerFunction<uint16_t(DNSResourceRecord::*)()>("qclass", [](DNSResourceRecord& rec) { return rec.qclass; });
103 d_lw->registerFunction<uint8_t(DNSResourceRecord::*)()>("scopeMask", [](DNSResourceRecord& rec) { return rec.scopeMask; });
104 d_lw->registerFunction<bool(DNSResourceRecord::*)()>("auth", [](DNSResourceRecord& rec) { return rec.auth; });
105 d_lw->registerFunction<bool(DNSResourceRecord::*)()>("disabled", [](DNSResourceRecord& rec) { return rec.disabled; });
106
107 // ComboAddress
108 d_lw->registerFunction<bool(ComboAddress::*)()>("isIPv4", [](const ComboAddress& ca) { return ca.sin4.sin_family == AF_INET; });
109 d_lw->registerFunction<bool(ComboAddress::*)()>("isIPv6", [](const ComboAddress& ca) { return ca.sin4.sin_family == AF_INET6; });
110 d_lw->registerFunction<uint16_t(ComboAddress::*)()>("getPort", [](const ComboAddress& ca) { return ntohs(ca.sin4.sin_port); } );
111 d_lw->registerFunction<bool(ComboAddress::*)()>("isMappedIPv4", [](const ComboAddress& ca) { return ca.isMappedIPv4(); });
112 d_lw->registerFunction<ComboAddress(ComboAddress::*)()>("mapToIPv4", [](const ComboAddress& ca) { return ca.mapToIPv4(); });
113 d_lw->registerFunction<void(ComboAddress::*)(unsigned int)>("truncate", [](ComboAddress& ca, unsigned int bits) { ca.truncate(bits); });
114 d_lw->registerFunction<string(ComboAddress::*)()>("toString", [](const ComboAddress& ca) { return ca.toString(); });
115 d_lw->registerToStringFunction<string(ComboAddress::*)()>([](const ComboAddress& ca) { return ca.toString(); });
116 d_lw->registerFunction<string(ComboAddress::*)()>("toStringWithPort", [](const ComboAddress& ca) { return ca.toStringWithPort(); });
117 d_lw->registerFunction<string(ComboAddress::*)()>("getRaw", [](const ComboAddress& ca) {
118 if(ca.sin4.sin_family == AF_INET) {
119 auto t=ca.sin4.sin_addr.s_addr; return string((const char*)&t, 4);
120 }
121 else
122 return string((const char*)&ca.sin6.sin6_addr.s6_addr, 16);
123 } );
124
125 d_lw->writeFunction("newCA", [](const std::string& a) { return ComboAddress(a); });
126 typedef std::unordered_set<ComboAddress,ComboAddress::addressOnlyHash,ComboAddress::addressOnlyEqual> cas_t;
127 d_lw->registerFunction<bool(ComboAddress::*)(const ComboAddress&)>("equal", [](const ComboAddress& lhs, const ComboAddress& rhs) { return ComboAddress::addressOnlyEqual()(lhs, rhs); });
128
129 // cas_t
130 d_lw->writeFunction("newCAS", []{ return cas_t(); });
131 d_lw->registerFunction<void(cas_t::*)(boost::variant<string,ComboAddress, vector<pair<unsigned int,string> > >)>("add",
132 [](cas_t& cas, const boost::variant<string,ComboAddress,vector<pair<unsigned int,string> > >& in)
133 {
134 try {
135 if(auto s = boost::get<string>(&in)) {
136 cas.insert(ComboAddress(*s));
137 }
138 else if(auto v = boost::get<vector<pair<unsigned int, string> > >(&in)) {
139 for(const auto& str : *v)
140 cas.insert(ComboAddress(str.second));
141 }
142 else
143 cas.insert(boost::get<ComboAddress>(in));
144 }
145 catch(std::exception& e) { g_log <<Logger::Error<<e.what()<<endl; }
146 });
147 d_lw->registerFunction<bool(cas_t::*)(const ComboAddress&)>("check",[](const cas_t& cas, const ComboAddress&ca) { return cas.count(ca)>0; });
148
149 // QType
150 d_lw->writeFunction("newQType", [](const string& s) { QType q; q = s; return q; });
151 d_lw->registerFunction("getCode", &QType::getCode);
152 d_lw->registerFunction("getName", &QType::getName);
153 d_lw->registerEqFunction<bool(QType::*)(const QType&)>([](const QType& a, const QType& b){ return a == b;}); // operator overloading confuses LuaContext
154 d_lw->registerToStringFunction(&QType::getName);
155
156 // Netmask
157 d_lw->writeFunction("newNetmask", [](const string& s) { return Netmask(s); });
158 d_lw->registerFunction<ComboAddress(Netmask::*)()>("getNetwork", [](const Netmask& nm) { return nm.getNetwork(); } ); // const reference makes this necessary
159 d_lw->registerFunction<ComboAddress(Netmask::*)()>("getMaskedNetwork", [](const Netmask& nm) { return nm.getMaskedNetwork(); } );
160 d_lw->registerFunction("isIpv4", &Netmask::isIpv4);
161 d_lw->registerFunction("isIpv6", &Netmask::isIpv6);
162 d_lw->registerFunction("getBits", &Netmask::getBits);
163 d_lw->registerFunction("toString", &Netmask::toString);
164 d_lw->registerFunction("empty", &Netmask::empty);
165 d_lw->registerFunction("match", (bool (Netmask::*)(const string&) const)&Netmask::match);
166 d_lw->registerEqFunction(&Netmask::operator==);
167 d_lw->registerToStringFunction(&Netmask::toString);
168
169 // NetmaskGroup
170 d_lw->writeFunction("newNMG", []() { return NetmaskGroup(); });
171 d_lw->registerFunction<void(NetmaskGroup::*)(const std::string&mask)>("addMask", [](NetmaskGroup&nmg, const std::string& mask) { nmg.addMask(mask); });
172 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); } });
173 d_lw->registerFunction("match", (bool (NetmaskGroup::*)(const ComboAddress&) const)&NetmaskGroup::match);
174
175 // DNSRecord
176 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.d_content = shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(dr.d_type, 1, content)); dr.d_place = static_cast<DNSResourceRecord::Place>(place); return dr; });
177 d_lw->registerMember("name", &DNSRecord::d_name);
178 d_lw->registerMember("type", &DNSRecord::d_type);
179 d_lw->registerMember("ttl", &DNSRecord::d_ttl);
180 d_lw->registerMember("place", &DNSRecord::d_place);
181 d_lw->registerFunction<string(DNSRecord::*)()>("getContent", [](const DNSRecord& dr) { return dr.d_content->getZoneRepresentation(); });
182 d_lw->registerFunction<boost::optional<ComboAddress>(DNSRecord::*)()>("getCA", [](const DNSRecord& dr) {
183 boost::optional<ComboAddress> ret;
184
185 if(auto arec = std::dynamic_pointer_cast<ARecordContent>(dr.d_content))
186 ret=arec->getCA(53);
187 else if(auto aaaarec = std::dynamic_pointer_cast<AAAARecordContent>(dr.d_content))
188 ret=aaaarec->getCA(53);
189 return ret;
190 });
191 d_lw->registerFunction<void(DNSRecord::*)(const std::string&)>("changeContent", [](DNSRecord& dr, const std::string& newContent) { dr.d_content = shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(dr.d_type, 1, newContent)); });
192
193 // pdnsload
194 d_lw->writeFunction("pdnslog", [](const std::string& msg, boost::optional<int> loglevel) { g_log << (Logger::Urgency)loglevel.get_value_or(Logger::Warning) << msg<<endl; });
195 d_lw->writeFunction("pdnsrandom", [](boost::optional<uint32_t> maximum) { return dns_random(maximum.get_value_or(0xffffffff)); });
196
197 // certain constants
198 d_pd.push_back({"PASS", (int)PolicyDecision::PASS});
199 d_pd.push_back({"DROP", (int)PolicyDecision::DROP});
200 d_pd.push_back({"TRUNCATE", (int)PolicyDecision::TRUNCATE});
201
202 vector<pair<string, int> > rcodes = {{"NOERROR", RCode::NoError },
203 {"FORMERR", RCode::FormErr },
204 {"SERVFAIL", RCode::ServFail },
205 {"NXDOMAIN", RCode::NXDomain },
206 {"NOTIMP", RCode::NotImp },
207 {"REFUSED", RCode::Refused },
208 {"YXDOMAIN", RCode::YXDomain },
209 {"YXRRSET", RCode::YXRRSet },
210 {"NXRRSET", RCode::NXRRSet },
211 {"NOTAUTH", RCode::NotAuth },
212 {"NOTZONE", RCode::NotZone }};
213 for(const auto& rcode : rcodes)
214 d_pd.push_back({rcode.first, rcode.second});
215
216 d_pd.push_back({"place", in_t{
217 {"QUESTION", 0},
218 {"ANSWER", 1},
219 {"AUTHORITY", 2},
220 {"ADDITIONAL", 3}
221 }});
222
223 d_pd.push_back({"loglevels", in_t{
224 {"Alert", LOG_ALERT},
225 {"Critical", LOG_CRIT},
226 {"Debug", LOG_DEBUG},
227 {"Emergency", LOG_EMERG},
228 {"Info", LOG_INFO},
229 {"Notice", LOG_NOTICE},
230 {"Warning", LOG_WARNING},
231 {"Error", LOG_ERR}
232 }});
233
234 for(const auto& n : QType::names)
235 d_pd.push_back({n.first, n.second});
236
237 d_lw->registerMember("tv_sec", &timeval::tv_sec);
238 d_lw->registerMember("tv_usec", &timeval::tv_usec);
239
240 postPrepareContext();
241
242 // so we can let postprepare do changes to this
243 d_lw->writeVariable("pdns", d_pd);
244 }
245
246 void BaseLua4::loadStream(std::istream &is) {
247 d_lw->executeCode(is);
248
249 postLoad();
250 }
251
252 BaseLua4::~BaseLua4() { }
253
254 #endif