From: Aki Tuomi Date: Sun, 11 Jun 2017 20:53:12 +0000 (+0300) Subject: lua-base4: Add base lua for auth and recursor X-Git-Tag: dnsdist-1.3.0~186^2~9 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f03de9dcef9d04306a07098d9facea9ca6640b94;p=pdns lua-base4: Add base lua for auth and recursor Allows code sharing between recursor and auth --- diff --git a/pdns/lua-base4.cc b/pdns/lua-base4.cc new file mode 100644 index 000000000..0114cd49e --- /dev/null +++ b/pdns/lua-base4.cc @@ -0,0 +1,214 @@ +#include +#include +#include +#include +#include "logger.hh" +#include "iputils.hh" +#include "dnsname.hh" +#include "dnsparser.hh" +#include "dnspacket.hh" +#include "namespaces.hh" +#include "ednssubnet.hh" +#include "lua-base4.hh" + +#if !defined(HAVE_LUA) + +BaseLua4::BaseLua4(const std::string &fname) { return; } +void BaseLua4::prepareContext() { return; } +BaseLua4::~BaseLua4() { } + +#else + +#undef L +#include "ext/luawrapper/include/LuaContext.hpp" + +BaseLua4::BaseLua4(const std::string &fname) { + prepareContext(); + std::ifstream ifs(fname); + if(!ifs) { + theL()<executeCode(ifs); + postLoad(); +}; + +void BaseLua4::prepareContext() { + d_lw = std::unique_ptr(new LuaContext); + + // dnsheader + d_lw->registerFunction("getID", [](dnsheader& dh) { return dh.id; }); + d_lw->registerFunction("getCD", [](dnsheader& dh) { return dh.cd; }); + d_lw->registerFunction("getTC", [](dnsheader& dh) { return dh.tc; }); + d_lw->registerFunction("getRA", [](dnsheader& dh) { return dh.ra; }); + d_lw->registerFunction("getAD", [](dnsheader& dh) { return dh.ad; }); + d_lw->registerFunction("getAA", [](dnsheader& dh) { return dh.aa; }); + d_lw->registerFunction("getRD", [](dnsheader& dh) { return dh.rd; }); + d_lw->registerFunction("getRCODE", [](dnsheader& dh) { return dh.rcode; }); + d_lw->registerFunction("getOPCODE", [](dnsheader& dh) { return dh.opcode; }); + d_lw->registerFunction("getQDCOUNT", [](dnsheader& dh) { return ntohs(dh.qdcount); }); + d_lw->registerFunction("getANCOUNT", [](dnsheader& dh) { return ntohs(dh.ancount); }); + d_lw->registerFunction("getNSCOUNT", [](dnsheader& dh) { return ntohs(dh.nscount); }); + d_lw->registerFunction("getARCOUNT", [](dnsheader& dh) { return ntohs(dh.arcount); }); + + // DNSName + d_lw->writeFunction("newDN", [](const std::string& dom){ return DNSName(dom); }); + d_lw->registerFunction("isPartOf", &DNSName::isPartOf); + d_lw->registerFunction("countLabels", [](const DNSName& name) { return name.countLabels(); }); + d_lw->registerFunction("wirelength", [](const DNSName& name) { return name.wirelength(); }); + d_lw->registerFunction("equal", [](const DNSName& lhs, const std::string& rhs) { return lhs==DNSName(rhs); }); + d_lw->registerEqFunction(&DNSName::operator==); + + d_lw->registerToStringFunction([](const DNSName&dn ) { return dn.toString(); }); + d_lw->registerFunction("toString", [](const DNSName&dn ) { return dn.toString(); }); + d_lw->registerFunction("toStringNoDot", [](const DNSName&dn ) { return dn.toStringNoDot(); }); + d_lw->registerFunction("chopOff", [](DNSName&dn ) { return dn.chopOff(); }); + + // DNSResourceRecord + d_lw->registerEqFunction(&DNSResourceRecord::operator==); + d_lw->registerFunction("__lt", &DNSResourceRecord::operator<); + d_lw->registerFunction("toString", [](const DNSResourceRecord& rec) { return rec.getZoneRepresentation();} ); + d_lw->registerFunction("qname", [](DNSResourceRecord& rec) { return rec.qname; }); + d_lw->registerFunction("wildcardname", [](DNSResourceRecord& rec) { return rec.wildcardname; }); + d_lw->registerFunction("content", [](DNSResourceRecord& rec) { return rec.content; }); + d_lw->registerFunction("last_modified", [](DNSResourceRecord& rec) { return rec.last_modified; }); + d_lw->registerFunction("ttl", [](DNSResourceRecord& rec) { return rec.ttl; }); + d_lw->registerFunction("signttl", [](DNSResourceRecord& rec) { return rec.signttl; }); + d_lw->registerFunction("domain_id", [](DNSResourceRecord& rec) { return rec.domain_id; }); + d_lw->registerFunction("qtype", [](DNSResourceRecord& rec) { return rec.qtype.getCode(); }); + d_lw->registerFunction("qclass", [](DNSResourceRecord& rec) { return rec.qclass; }); + d_lw->registerFunction("scopeMask", [](DNSResourceRecord& rec) { return rec.scopeMask; }); + d_lw->registerFunction("auth", [](DNSResourceRecord& rec) { return rec.auth; }); + d_lw->registerFunction("disabled", [](DNSResourceRecord& rec) { return rec.disabled; }); + + // ComboAddress + d_lw->registerFunction("isIPv4", [](const ComboAddress& ca) { return ca.sin4.sin_family == AF_INET; }); + d_lw->registerFunction("isIPv6", [](const ComboAddress& ca) { return ca.sin4.sin_family == AF_INET6; }); + d_lw->registerFunction("isMappedIPv4", [](const ComboAddress& ca) { return ca.isMappedIPv4(); }); + d_lw->registerFunction("mapToIPv4", [](const ComboAddress& ca) { return ca.mapToIPv4(); }); + d_lw->registerFunction("truncate", [](ComboAddress& ca, unsigned int bits) { ca.truncate(bits); }); + d_lw->registerFunction("toString", [](const ComboAddress& ca) { return ca.toString(); }); + d_lw->registerToStringFunction([](const ComboAddress& ca) { return ca.toString(); }); + d_lw->registerFunction("toStringWithPort", [](const ComboAddress& ca) { return ca.toStringWithPort(); }); + d_lw->registerFunction("getPort", [](const ComboAddress& ca) { return ntohs(ca.sin4.sin_port); } ); + d_lw->registerFunction("getRaw", [](const ComboAddress& ca) { + if(ca.sin4.sin_family == AF_INET) { + auto t=ca.sin4.sin_addr.s_addr; return string((const char*)&t, 4); + } + else + return string((const char*)&ca.sin6.sin6_addr.s6_addr, 16); + } ); + + d_lw->writeFunction("newCA", [](const std::string& a) { return ComboAddress(a); }); + typedef std::unordered_set cas_t; + d_lw->writeFunction("newCAS", []{ return cas_t(); }); + + // cas_t + d_lw->registerFunction > >)>("add", [](cas_t& cas, const boost::variant > >& in) + { + try { + if(auto s = boost::get(&in)) { + cas.insert(ComboAddress(*s)); + } + else if(auto v = boost::get > >(&in)) { + for(const auto& s : *v) + cas.insert(ComboAddress(s.second)); + } + else + cas.insert(boost::get(in)); + } catch(std::exception& e) { theL() <registerFunction("check",[](const cas_t& cas, const ComboAddress&ca) { return cas.count(ca)>0; }); + d_lw->registerFunction("equal", [](const ComboAddress& lhs, const ComboAddress& rhs) { return ComboAddress::addressOnlyEqual()(lhs, rhs); }); + + // Netmask + d_lw->writeFunction("newNetmask", [](const string& s) { return Netmask(s); }); + d_lw->registerFunction("getNetwork", [](const Netmask& nm) { return nm.getNetwork(); } ); // const reference makes this necessary + d_lw->registerFunction("getMaskedNetwork", [](const Netmask& nm) { return nm.getMaskedNetwork(); } ); + d_lw->registerFunction("isIpv4", &Netmask::isIpv4); + d_lw->registerFunction("isIpv6", &Netmask::isIpv6); + d_lw->registerFunction("getBits", &Netmask::getBits); + d_lw->registerFunction("toString", &Netmask::toString); + d_lw->registerFunction("empty", &Netmask::empty); + d_lw->registerFunction("match", (bool (Netmask::*)(const string&) const)&Netmask::match); + d_lw->registerEqFunction(&Netmask::operator==); + + // NetmaskGroup + d_lw->writeFunction("newNMG", []() { return NetmaskGroup(); }); + d_lw->registerFunction("addMask", [](NetmaskGroup&nmg, const std::string& mask) { nmg.addMask(mask); }); + d_lw->registerFunction>&)>("addMasks", [](NetmaskGroup&nmg, const vector>& masks) { for(const auto& mask: masks) { nmg.addMask(mask.second); } }); + d_lw->registerFunction("match", (bool (NetmaskGroup::*)(const ComboAddress&) const)&NetmaskGroup::match); + + // DNSRecord + 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::mastermake(dr.d_type, 1, content)); dr.d_place = static_cast(place); return dr; }); + d_lw->registerMember("name", &DNSRecord::d_name); + d_lw->registerMember("type", &DNSRecord::d_type); + d_lw->registerMember("ttl", &DNSRecord::d_ttl); + d_lw->registerMember("place", &DNSRecord::d_place); + d_lw->registerFunction("getContent", [](const DNSRecord& dr) { return dr.d_content->getZoneRepresentation(); }); + d_lw->registerFunction(DNSRecord::*)()>("getCA", [](const DNSRecord& dr) { + boost::optional ret; + + if(auto rec = std::dynamic_pointer_cast(dr.d_content)) + ret=rec->getCA(53); + else if(auto rec = std::dynamic_pointer_cast(dr.d_content)) + ret=rec->getCA(53); + return ret; + }); + d_lw->registerFunction("changeContent", [](DNSRecord& dr, const std::string& newContent) { dr.d_content = shared_ptr(DNSRecordContent::mastermake(dr.d_type, 1, newContent)); }); + + // pdnsload + d_lw->writeFunction("pdnslog", [](const std::string& msg, boost::optional loglevel) { theL() << (Logger::Urgency)loglevel.get_value_or(Logger::Warning) << msg< > rcodes = {{"NOERROR", RCode::NoError }, + {"FORMERR", RCode::FormErr }, + {"SERVFAIL", RCode::ServFail }, + {"NXDOMAIN", RCode::NXDomain }, + {"NOTIMP", RCode::NotImp }, + {"REFUSED", RCode::Refused }, + {"YXDOMAIN", RCode::YXDomain }, + {"YXRRSET", RCode::YXRRSet }, + {"NXRRSET", RCode::NXRRSet }, + {"NOTAUTH", RCode::NotAuth }, + {"NOTZONE", RCode::NotZone }}; + for(const auto& rcode : rcodes) + d_pd.push_back({rcode.first, rcode.second}); + + d_pd.push_back({"place", in_t{ + {"QUESTION", 0}, + {"ANSWER", 1}, + {"AUTHORITY", 2}, + {"ADDITIONAL", 3} + }}); + + d_pd.push_back({"loglevels", in_t{ + {"Alert", LOG_ALERT}, + {"Critical", LOG_CRIT}, + {"Debug", LOG_DEBUG}, + {"Emergency", LOG_EMERG}, + {"Info", LOG_INFO}, + {"Notice", LOG_NOTICE}, + {"Warning", LOG_WARNING}, + {"Error", LOG_ERR} + }}); + + for(const auto& n : QType::names) + d_pd.push_back({n.first, n.second}); + + d_lw->registerMember("tv_sec", &timeval::tv_sec); + d_lw->registerMember("tv_usec", &timeval::tv_usec); + + postPrepareContext(); + + // so we can let postprepare do changes to this + d_lw->writeVariable("pdns", d_pd); +} + +BaseLua4::~BaseLua4() { } + +#endif diff --git a/pdns/lua-base4.hh b/pdns/lua-base4.hh new file mode 100644 index 000000000..29c6857c4 --- /dev/null +++ b/pdns/lua-base4.hh @@ -0,0 +1,33 @@ +#pragma once +#include "namespaces.hh" +#include +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +class LuaContext; + +#if defined(HAVE_LUA) +#undef L +#include "ext/luawrapper/include/LuaContext.hpp" +#define L theL() +#endif + +class BaseLua4 : public boost::noncopyable +{ +protected: +#ifdef HAVE_LUA + std::unique_ptr d_lw; // this is way on top because it must get destroyed _last_ +#endif + +public: + explicit BaseLua4(const std::string &fname); + + virtual ~BaseLua4(); // this is so unique_ptr works with an incomplete type +protected: + void prepareContext(); + virtual void postPrepareContext() = 0; + virtual void postLoad() = 0; + typedef vector > in_t; + vector > > d_pd; +};