}
-
bool getEDNSSubnetOptsFromString(const string& options, EDNSSubnetOpts* eso)
+{
+ return getEDNSSubnetOptsFromString(options.c_str(), options.length(), eso);
+}
+bool getEDNSSubnetOptsFromString(const char* options, unsigned int len, EDNSSubnetOpts* eso)
{
//cerr<<"options.size:"<<options.size()<<endl;
- if(options.size() <= 4)
+ if(len <= 4)
return false;
EDNSSubnetOptsWire esow;
- memcpy(&esow, options.c_str(), sizeof(esow));
+ memcpy(&esow, options, sizeof(esow));
esow.family = ntohs(esow.family);
//cerr<<"Family when parsing from string: "<<esow.family<<endl;
ComboAddress address;
unsigned int octetsin = ((esow.sourceMask - 1)>> 3)+1;
//cerr<<"octetsin:"<<octetsin<<endl;
if(esow.family == 1) {
- if(options.size() != 4+octetsin)
+ if(len != 4+octetsin)
return false;
if(octetsin > 4)
return false;
memset(&address, 0, sizeof(address));
address.sin4.sin_family = AF_INET;
- memcpy(&address.sin4.sin_addr.s_addr, options.c_str()+4, octetsin);
+ memcpy(&address.sin4.sin_addr.s_addr, options+4, octetsin);
} else if(esow.family == 2) {
- if(options.size() != 4+octetsin)
+ if(len != 4+octetsin)
return false;
if(octetsin > 16)
return false;
memset(&address, 0, sizeof(address));
address.sin4.sin_family = AF_INET6;
- memcpy(&address.sin6.sin6_addr.s6_addr, options.c_str()+4, octetsin);
+ memcpy(&address.sin6.sin6_addr.s6_addr, options+4, octetsin);
}
else
return false;
/*
PowerDNS Versatile Database Driven Nameserver
- Copyright (C) 2011 Netherlabs Computer Consulting BV
+ Copyright (C) 2011 - 2016 Netherlabs Computer Consulting BV
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
};
bool getEDNSSubnetOptsFromString(const string& options, EDNSSubnetOpts* eso);
+bool getEDNSSubnetOptsFromString(const char* options, unsigned int len, EDNSSubnetOpts* eso);
string makeEDNSSubnetOptsString(const EDNSSubnetOpts& eso);
#endif
return false;
}
-int RecursorLua4::gettag(const ComboAddress& remote, const ComboAddress& local, const DNSName& qname, uint16_t qtype)
+int RecursorLua4::gettag(const ComboAddress& remote, const EDNSSubnet& subnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype)
{
return 0;
}
d_lw->registerFunction<ComboAddress(Netmask::*)()>("getNetwork", [](const Netmask& nm) { return nm.getNetwork(); } ); // const reference makes this necessary
d_lw->registerFunction("toString", &Netmask::toString);
+ d_lw->registerFunction("empty", &Netmask::empty);
d_lw->writeFunction("newNMG", []() { return NetmaskGroup(); });
d_lw->registerFunction<void(NetmaskGroup::*)(const std::string&mask)>("addMask", [](NetmaskGroup&nmg, const std::string& mask)
d_lw->writeFunction("pdnslog", [](const std::string& msg, boost::optional<int> loglevel) {
- theL() << loglevel.get_value_or(Logger::Warning) << msg<<endl;
+ theL() << (Logger::Urgency)loglevel.get_value_or(Logger::Warning) << msg<<endl;
});
typedef vector<pair<string, int> > in_t;
vector<pair<string, boost::variant<int, in_t, struct timeval* > > > pd{
return false; // don't block
}
-int RecursorLua4::gettag(const ComboAddress& remote, const ComboAddress& local, const DNSName& qname, uint16_t qtype)
+int RecursorLua4::gettag(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype)
{
if(d_gettag)
- return d_gettag(remote, local, qname, qtype);
+ return d_gettag(remote, ednssubnet, local, qname, qtype);
return 0;
}
bool preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, vector<DNSRecord>& res, int& ret);
bool ipfilter(const ComboAddress& remote, const ComboAddress& local, const struct dnsheader&);
- int gettag(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, uint16_t qtype);
+ int gettag(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& query, uint16_t qtype);
- typedef std::function<int(ComboAddress,ComboAddress, DNSName, uint16_t)> gettag_t;
+ typedef std::function<int(ComboAddress, Netmask, ComboAddress, DNSName, uint16_t)> gettag_t;
gettag_t d_gettag; // public so you can query if we have this hooked
private:
uint16_t qtype=0;
try {
DNSName qname(question.c_str(), question.length(), sizeof(dnsheader), false, &qtype, 0, &consumed);
- ctag=(*t_pdl)->gettag(fromaddr, destaddr, qname, qtype);
+ Netmask ednssubnet;
+ auto pos= sizeof(dnsheader)+consumed+4;
+ if(dh->arcount && question.length() > pos + 16) { // this code can extract one (1) EDNS Subnet option
+ uint16_t optlen=0x100*question.at(pos+9)+question.at(pos+10);
+ uint16_t optcode=0x100*question.at(pos+11)+question.at(pos+12);
+ if(question.at(pos)==0 && question.at(pos+1)==0 && question.at(pos+2)==QType::OPT && optlen && optcode==8) {
+ EDNSSubnetOpts eso;
+ if(getEDNSSubnetOptsFromString(question.c_str()+pos+15, question.length()-15-pos, &eso)) {
+ ednssubnet=eso.source;
+ }
+ }
+ }
+ ctag=(*t_pdl)->gettag(fromaddr, ednssubnet, destaddr, qname, qtype);
}
catch(std::exception& e)
{