static void patchZone(UeberBackend& B, const DNSName& zonename, DomainInfo& di, HttpRequest* req, HttpResponse* resp);
// QTypes that MUST NOT have multiple records of the same type in a given RRset.
-static const std::set<uint16_t> onlyOneEntryTypes = { QType::CNAME, QType::DNAME, QType::SOA };
+static const std::set<uint16_t> onlyOneEntryTypes = {QType::CNAME, QType::DNAME, QType::SOA};
// QTypes that MUST NOT be used with any other QType on the same name.
-static const std::set<uint16_t> exclusiveEntryTypes = { QType::CNAME };
+static const std::set<uint16_t> exclusiveEntryTypes = {QType::CNAME};
// QTypes that MUST be at apex.
static const std::set<uint16_t> atApexTypes = {QType::SOA, QType::DNSKEY};
// QTypes that are NOT allowed at apex.
void AuthWebServer::go()
{
S.doRings();
- std::thread webT([this](){webThread();});
+ std::thread webT([this]() { webThread(); });
webT.detach();
- std::thread statT([this](){statThread();});
+ std::thread statT([this]() { statThread(); });
statT.detach();
}
{
try {
setThreadName("pdns/statHelper");
- for(;;) {
+ for (;;) {
d_queries.submit(S.read("udp-queries"));
d_cachehits.submit(S.read("packetcache-hit"));
d_cachemisses.submit(S.read("packetcache-miss"));
Utility::sleep(1);
}
}
- catch(...) {
- g_log<<Logger::Error<<"Webserver statThread caught an exception, dying"<<endl;
+ catch (...) {
+ g_log << Logger::Error << "Webserver statThread caught an exception, dying" << endl;
_exit(1);
}
}
-static string htmlescape(const string &s) {
+static string htmlescape(const string& s)
+{
string result;
- for(char it : s) {
+ for (char it : s) {
switch (it) {
case '&':
result += "&";
return result;
}
-static void printtable(ostringstream &ret, const string &ringname, const string &title, int limit=10)
+static void printtable(ostringstream& ret, const string& ringname, const string& title, int limit = 10)
{
- int tot=0;
- int entries=0;
- vector<pair <string,unsigned int> >ring=S.getRing(ringname);
+ int tot = 0;
+ int entries = 0;
+ vector<pair<string, unsigned int>> ring = S.getRing(ringname);
- for(const auto & i : ring) {
- tot+=i.second;
+ for (const auto& i : ring) {
+ tot += i.second;
entries++;
}
- ret<<"<div class=\"panel\">";
- ret<<"<span class=resetring><i></i><a href=\"?resetring="<<htmlescape(ringname)<<"\">Reset</a></span>"<<endl;
- ret<<"<h2>"<<title<<"</h2>"<<endl;
- ret<<"<div class=ringmeta>";
- ret<<"<a class=topXofY href=\"?ring="<<htmlescape(ringname)<<"\">Showing: Top "<<limit<<" of "<<entries<<"</a>"<<endl;
- ret<<"<span class=resizering>Resize: ";
- unsigned int sizes[]={10,100,500,1000,10000,500000,0};
- for(int i=0;sizes[i];++i) {
- if(S.getRingSize(ringname)!=sizes[i])
- ret<<"<a href=\"?resizering="<<htmlescape(ringname)<<"&size="<<sizes[i]<<"\">"<<sizes[i]<<"</a> ";
+ ret << "<div class=\"panel\">";
+ ret << "<span class=resetring><i></i><a href=\"?resetring=" << htmlescape(ringname) << "\">Reset</a></span>" << endl;
+ ret << "<h2>" << title << "</h2>" << endl;
+ ret << "<div class=ringmeta>";
+ ret << "<a class=topXofY href=\"?ring=" << htmlescape(ringname) << "\">Showing: Top " << limit << " of " << entries << "</a>" << endl;
+ ret << "<span class=resizering>Resize: ";
+ unsigned int sizes[] = {10, 100, 500, 1000, 10000, 500000, 0};
+ for (int i = 0; sizes[i]; ++i) {
+ if (S.getRingSize(ringname) != sizes[i])
+ ret << "<a href=\"?resizering=" << htmlescape(ringname) << "&size=" << sizes[i] << "\">" << sizes[i] << "</a> ";
else
- ret<<"("<<sizes[i]<<") ";
+ ret << "(" << sizes[i] << ") ";
}
- ret<<"</span></div>";
+ ret << "</span></div>";
- ret<<"<table class=\"data\">";
- int printed=0;
- int total=max(1,tot);
- for(vector<pair<string,unsigned int> >::const_iterator i=ring.begin();limit && i!=ring.end();++i,--limit) {
- ret<<"<tr><td>"<<htmlescape(i->first)<<"</td><td>"<<i->second<<"</td><td align=right>"<< AuthWebServer::makePercentage(i->second*100.0/total)<<"</td>"<<endl;
- printed+=i->second;
+ ret << "<table class=\"data\">";
+ int printed = 0;
+ int total = max(1, tot);
+ for (vector<pair<string, unsigned int>>::const_iterator i = ring.begin(); limit && i != ring.end(); ++i, --limit) {
+ ret << "<tr><td>" << htmlescape(i->first) << "</td><td>" << i->second << "</td><td align=right>" << AuthWebServer::makePercentage(i->second * 100.0 / total) << "</td>" << endl;
+ printed += i->second;
}
- ret<<"<tr><td colspan=3></td></tr>"<<endl;
- if(printed!=tot)
- ret<<"<tr><td><b>Rest:</b></td><td><b>"<<tot-printed<<"</b></td><td align=right><b>"<< AuthWebServer::makePercentage((tot-printed)*100.0/total)<<"</b></td>"<<endl;
+ ret << "<tr><td colspan=3></td></tr>" << endl;
+ if (printed != tot)
+ ret << "<tr><td><b>Rest:</b></td><td><b>" << tot - printed << "</b></td><td align=right><b>" << AuthWebServer::makePercentage((tot - printed) * 100.0 / total) << "</b></td>" << endl;
- ret<<"<tr><td><b>Total:</b></td><td><b>"<<tot<<"</b></td><td align=right><b>100%</b></td>";
- ret<<"</table></div>"<<endl;
+ ret << "<tr><td><b>Total:</b></td><td><b>" << tot << "</b></td><td align=right><b>100%</b></td>";
+ ret << "</table></div>" << endl;
}
-void AuthWebServer::printvars(ostringstream &ret)
+void AuthWebServer::printvars(ostringstream& ret)
{
- ret<<"<div class=panel><h2>Variables</h2><table class=\"data\">"<<endl;
+ ret << "<div class=panel><h2>Variables</h2><table class=\"data\">" << endl;
- vector<string>entries=S.getEntries();
- for(const auto & entry : entries) {
- ret<<"<tr><td>"<<entry<<"</td><td>"<<S.read(entry)<<"</td><td>"<<S.getDescrip(entry)<<"</td>"<<endl;
+ vector<string> entries = S.getEntries();
+ for (const auto& entry : entries) {
+ ret << "<tr><td>" << entry << "</td><td>" << S.read(entry) << "</td><td>" << S.getDescrip(entry) << "</td>" << endl;
}
- ret<<"</table></div>"<<endl;
+ ret << "</table></div>" << endl;
}
-void AuthWebServer::printargs(ostringstream &ret)
+void AuthWebServer::printargs(ostringstream& ret)
{
- ret<<R"(<table border=1><tr><td colspan=3 bgcolor="#0000ff"><font color="#ffffff">Arguments</font></td>)"<<endl;
+ ret << R"(<table border=1><tr><td colspan=3 bgcolor="#0000ff"><font color="#ffffff">Arguments</font></td>)" << endl;
- vector<string>entries=arg().list();
- for(const auto & entry : entries) {
- ret<<"<tr><td>"<<entry<<"</td><td>"<<arg()[entry]<<"</td><td>"<<arg().getHelp(entry)<<"</td>"<<endl;
+ vector<string> entries = arg().list();
+ for (const auto& entry : entries) {
+ ret << "<tr><td>" << entry << "</td><td>" << arg()[entry] << "</td><td>" << arg().getHelp(entry) << "</td>" << endl;
}
}
void AuthWebServer::indexfunction(HttpRequest* req, HttpResponse* resp)
{
- if(!req->getvars["resetring"].empty()) {
+ if (!req->getvars["resetring"].empty()) {
if (S.ringExists(req->getvars["resetring"]))
S.resetRing(req->getvars["resetring"]);
resp->status = 302;
resp->headers["Location"] = req->url.path;
return;
}
- if(!req->getvars["resizering"].empty()){
- int size=std::stoi(req->getvars["size"]);
+ if (!req->getvars["resizering"].empty()) {
+ int size = std::stoi(req->getvars["size"]);
if (S.ringExists(req->getvars["resizering"]) && size > 0 && size <= 500000)
S.resizeRing(req->getvars["resizering"], std::stoi(req->getvars["size"]));
resp->status = 302;
ostringstream ret;
- ret<<"<!DOCTYPE html>"<<endl;
- ret<<"<html><head>"<<endl;
- ret<<"<title>PowerDNS Authoritative Server Monitor</title>"<<endl;
- ret<<R"(<link rel="stylesheet" href="style.css"/>)"<<endl;
- ret<<"</head><body>"<<endl;
-
- ret<<"<div class=\"row\">"<<endl;
- ret<<"<div class=\"headl columns\">";
- ret<<R"(<a href="/" id="appname">PowerDNS )"<<htmlescape(VERSION);
- if(!arg()["config-name"].empty()) {
- ret<<" ["<<htmlescape(arg()["config-name"])<<"]";
- }
- ret<<"</a></div>"<<endl;
- ret<<"<div class=\"header columns\"></div></div>";
- ret<<R"(<div class="row"><div class="all columns">)";
-
- time_t passed=time(nullptr)-g_starttime;
-
- ret<<"<p>Uptime: "<<
- humanDuration(passed)<<
- "<br>"<<endl;
-
- ret<<"Queries/second, 1, 5, 10 minute averages: "<<std::setprecision(3)<<
- (int)d_queries.get1()<<", "<<
- (int)d_queries.get5()<<", "<<
- (int)d_queries.get10()<<". Max queries/second: "<<(int)d_queries.getMax()<<
- "<br>"<<endl;
-
- if(d_cachemisses.get10()+d_cachehits.get10()>0)
- ret<<"Cache hitrate, 1, 5, 10 minute averages: "<<
- makePercentage((d_cachehits.get1()*100.0)/((d_cachehits.get1())+(d_cachemisses.get1())))<<", "<<
- makePercentage((d_cachehits.get5()*100.0)/((d_cachehits.get5())+(d_cachemisses.get5())))<<", "<<
- makePercentage((d_cachehits.get10()*100.0)/((d_cachehits.get10())+(d_cachemisses.get10())))<<
- "<br>"<<endl;
-
- if(d_qcachemisses.get10()+d_qcachehits.get10()>0)
- ret<<"Backend query cache hitrate, 1, 5, 10 minute averages: "<<std::setprecision(2)<<
- makePercentage((d_qcachehits.get1()*100.0)/((d_qcachehits.get1())+(d_qcachemisses.get1())))<<", "<<
- makePercentage((d_qcachehits.get5()*100.0)/((d_qcachehits.get5())+(d_qcachemisses.get5())))<<", "<<
- makePercentage((d_qcachehits.get10()*100.0)/((d_qcachehits.get10())+(d_qcachemisses.get10())))<<
- "<br>"<<endl;
-
- ret<<"Backend query load, 1, 5, 10 minute averages: "<<std::setprecision(3)<<
- (int)d_qcachemisses.get1()<<", "<<
- (int)d_qcachemisses.get5()<<", "<<
- (int)d_qcachemisses.get10()<<". Max queries/second: "<<(int)d_qcachemisses.getMax()<<
- "<br>"<<endl;
-
- ret<<"Total queries: "<<S.read("udp-queries")<<". Question/answer latency: "<<S.read("latency")/1000.0<<"ms</p><br>"<<endl;
- if(req->getvars["ring"].empty()) {
+ ret << "<!DOCTYPE html>" << endl;
+ ret << "<html><head>" << endl;
+ ret << "<title>PowerDNS Authoritative Server Monitor</title>" << endl;
+ ret << R"(<link rel="stylesheet" href="style.css"/>)" << endl;
+ ret << "</head><body>" << endl;
+
+ ret << "<div class=\"row\">" << endl;
+ ret << "<div class=\"headl columns\">";
+ ret << R"(<a href="/" id="appname">PowerDNS )" << htmlescape(VERSION);
+ if (!arg()["config-name"].empty()) {
+ ret << " [" << htmlescape(arg()["config-name"]) << "]";
+ }
+ ret << "</a></div>" << endl;
+ ret << "<div class=\"header columns\"></div></div>";
+ ret << R"(<div class="row"><div class="all columns">)";
+
+ time_t passed = time(nullptr) - g_starttime;
+
+ ret << "<p>Uptime: " << humanDuration(passed) << "<br>" << endl;
+
+ ret << "Queries/second, 1, 5, 10 minute averages: " << std::setprecision(3) << (int)d_queries.get1() << ", " << (int)d_queries.get5() << ", " << (int)d_queries.get10() << ". Max queries/second: " << (int)d_queries.getMax() << "<br>" << endl;
+
+ if (d_cachemisses.get10() + d_cachehits.get10() > 0)
+ ret << "Cache hitrate, 1, 5, 10 minute averages: " << makePercentage((d_cachehits.get1() * 100.0) / ((d_cachehits.get1()) + (d_cachemisses.get1()))) << ", " << makePercentage((d_cachehits.get5() * 100.0) / ((d_cachehits.get5()) + (d_cachemisses.get5()))) << ", " << makePercentage((d_cachehits.get10() * 100.0) / ((d_cachehits.get10()) + (d_cachemisses.get10()))) << "<br>" << endl;
+
+ if (d_qcachemisses.get10() + d_qcachehits.get10() > 0)
+ ret << "Backend query cache hitrate, 1, 5, 10 minute averages: " << std::setprecision(2) << makePercentage((d_qcachehits.get1() * 100.0) / ((d_qcachehits.get1()) + (d_qcachemisses.get1()))) << ", " << makePercentage((d_qcachehits.get5() * 100.0) / ((d_qcachehits.get5()) + (d_qcachemisses.get5()))) << ", " << makePercentage((d_qcachehits.get10() * 100.0) / ((d_qcachehits.get10()) + (d_qcachemisses.get10()))) << "<br>" << endl;
+
+ ret << "Backend query load, 1, 5, 10 minute averages: " << std::setprecision(3) << (int)d_qcachemisses.get1() << ", " << (int)d_qcachemisses.get5() << ", " << (int)d_qcachemisses.get10() << ". Max queries/second: " << (int)d_qcachemisses.getMax() << "<br>" << endl;
+
+ ret << "Total queries: " << S.read("udp-queries") << ". Question/answer latency: " << S.read("latency") / 1000.0 << "ms</p><br>" << endl;
+ if (req->getvars["ring"].empty()) {
auto entries = S.listRings();
- for(const auto &i: entries) {
+ for (const auto& i : entries) {
printtable(ret, i, S.getRingTitle(i));
}
printvars(ret);
- if(arg().mustDo("webserver-print-arguments"))
+ if (arg().mustDo("webserver-print-arguments"))
printargs(ret);
}
- else if(S.ringExists(req->getvars["ring"]))
- printtable(ret,req->getvars["ring"],S.getRingTitle(req->getvars["ring"]),100);
+ else if (S.ringExists(req->getvars["ring"]))
+ printtable(ret, req->getvars["ring"], S.getRingTitle(req->getvars["ring"]), 100);
- ret<<"</div></div>"<<endl;
- ret<<"<footer class=\"row\">"<<fullVersionString()<<"<br>© <a href=\"https://www.powerdns.com/\">PowerDNS.COM BV</a>.</footer>"<<endl;
- ret<<"</body></html>"<<endl;
+ ret << "</div></div>" << endl;
+ ret << "<footer class=\"row\">" << fullVersionString() << "<br>© <a href=\"https://www.powerdns.com/\">PowerDNS.COM BV</a>.</footer>" << endl;
+ ret << "</body></html>" << endl;
resp->body = ret.str();
resp->status = 200;
}
/** Helper to build a record content as needed. */
-static inline string makeRecordContent(const QType& qtype, const string& content, bool noDot) {
+static inline string makeRecordContent(const QType& qtype, const string& content, bool noDot)
+{
// noDot: for backend storage, pass true. for API users, pass false.
auto drc = DNSRecordContent::make(qtype.getCode(), QClass::IN, content);
return drc->getZoneRepresentation(noDot);
}
/** "Normalize" record content for API consumers. */
-static inline string makeApiRecordContent(const QType& qtype, const string& content) {
+static inline string makeApiRecordContent(const QType& qtype, const string& content)
+{
return makeRecordContent(qtype, content, false);
}
/** "Normalize" record content for backend storage. */
-static inline string makeBackendRecordContent(const QType& qtype, const string& content) {
+static inline string makeBackendRecordContent(const QType& qtype, const string& content)
+{
return makeRecordContent(qtype, content, true);
}
-static Json::object getZoneInfo(const DomainInfo& di, DNSSECKeeper* dk) {
+static Json::object getZoneInfo(const DomainInfo& di, DNSSECKeeper* dk)
+{
string zoneId = apiZoneNameToId(di.zone);
vector<string> primaries;
primaries.reserve(di.primaries.size());
return obj;
}
-static bool shouldDoRRSets(HttpRequest* req) {
+static bool shouldDoRRSets(HttpRequest* req)
+{
if (req->getvars.count("rrsets") == 0 || req->getvars["rrsets"] == "true")
return true;
if (req->getvars["rrsets"] == "false")
return false;
- throw ApiException("'rrsets' request parameter value '"+req->getvars["rrsets"]+"' is not supported");
+ throw ApiException("'rrsets' request parameter value '" + req->getvars["rrsets"] + "' is not supported");
}
-static void fillZone(UeberBackend& B, const DNSName& zonename, HttpResponse* resp, HttpRequest* req) {
+static void fillZone(UeberBackend& B, const DNSName& zonename, HttpResponse* resp, HttpRequest* req)
+{
DomainInfo di;
- if(!B.getDomainInfo(zonename, di)) {
+ if (!B.getDomainInfo(zonename, di)) {
throw HttpNotFoundException();
}
DNSResourceRecord rr;
if (req->getvars.count("rrset_name") == 0) {
di.backend->list(zonename, di.id, true); // incl. disabled
- } else {
+ }
+ else {
QType qt;
if (req->getvars.count("rrset_type") == 0) {
qt = QType::ANY;
- } else {
+ }
+ else {
qt = req->getvars["rrset_type"];
}
di.backend->lookup(qt, DNSName(req->getvars["rrset_name"]), di.id);
}
- while(di.backend->get(rr)) {
+ while (di.backend->get(rr)) {
if (!rr.qtype.getCode())
continue; // skip empty non-terminals
records.push_back(rr);
}
sort(records.begin(), records.end(), [](const DNSResourceRecord& a, const DNSResourceRecord& b) {
- /* if you ever want to update this comparison function,
- please be aware that you will also need to update the conditions in the code merging
- the records and comments below */
- if (a.qname == b.qname) {
- return b.qtype < a.qtype;
- }
- return b.qname < a.qname;
- });
+ /* if you ever want to update this comparison function,
+ please be aware that you will also need to update the conditions in the code merging
+ the records and comments below */
+ if (a.qname == b.qname) {
+ return b.qtype < a.qtype;
+ }
+ return b.qname < a.qname;
+ });
}
// load all comments + sort
{
Comment comment;
di.backend->listComments(di.id);
- while(di.backend->getComment(comment)) {
+ while (di.backend->getComment(comment)) {
comments.push_back(comment);
}
sort(comments.begin(), comments.end(), [](const Comment& a, const Comment& b) {
- /* if you ever want to update this comparison function,
- please be aware that you will also need to update the conditions in the code merging
- the records and comments below */
- if (a.qname == b.qname) {
- return b.qtype < a.qtype;
- }
- return b.qname < a.qname;
- });
+ /* if you ever want to update this comparison function,
+ please be aware that you will also need to update the conditions in the code merging
+ the records and comments below */
+ if (a.qname == b.qname) {
+ return b.qtype < a.qtype;
+ }
+ return b.qname < a.qname;
+ });
}
Json::array rrsets;
current_qname = rit->qname;
current_qtype = rit->qtype;
ttl = rit->ttl;
- } else {
+ }
+ else {
current_qname = cit->qname;
current_qtype = cit->qtype;
ttl = 0;
}
- while(rit != records.end() && rit->qname == current_qname && rit->qtype == current_qtype) {
+ while (rit != records.end() && rit->qname == current_qname && rit->qtype == current_qtype) {
ttl = min(ttl, rit->ttl);
- rrset_records.push_back(Json::object {
- { "disabled", rit->disabled },
- { "content", makeApiRecordContent(rit->qtype, rit->content) }
- });
+ rrset_records.push_back(Json::object{
+ {"disabled", rit->disabled},
+ {"content", makeApiRecordContent(rit->qtype, rit->content)}});
rit++;
}
while (cit != comments.end() && cit->qname == current_qname && cit->qtype == current_qtype) {
- rrset_comments.push_back(Json::object {
- { "modified_at", (double)cit->modified_at },
- { "account", cit->account },
- { "content", cit->content }
- });
+ rrset_comments.push_back(Json::object{
+ {"modified_at", (double)cit->modified_at},
+ {"account", cit->account},
+ {"content", cit->content}});
cit++;
}
resp->setJsonBody(doc);
}
-void productServerStatisticsFetch(map<string,string>& out)
+void productServerStatisticsFetch(map<string, string>& out)
{
vector<string> items = S.getEntries();
- for(const string& item : items) {
+ for (const string& item : items) {
out[item] = std::to_string(S.read(item));
}
}
}
-static void validateGatheredRRType(const DNSResourceRecord& rr) {
+static void validateGatheredRRType(const DNSResourceRecord& rr)
+{
if (rr.qtype.getCode() == QType::OPT || rr.qtype.getCode() == QType::TSIG) {
- throw ApiException("RRset "+rr.qname.toString()+" IN "+rr.qtype.toString()+": invalid type given");
+ throw ApiException("RRset " + rr.qname.toString() + " IN " + rr.qtype.toString() + ": invalid type given");
}
}
-static void gatherRecords(const Json& container, const DNSName& qname, const QType& qtype, const uint32_t ttl, vector<DNSResourceRecord>& new_records) {
+static void gatherRecords(const Json& container, const DNSName& qname, const QType& qtype, const uint32_t ttl, vector<DNSResourceRecord>& new_records)
+{
DNSResourceRecord rr;
rr.qname = qname;
rr.qtype = qtype;
validateGatheredRRType(rr);
const auto& items = container["records"].array_items();
- for(const auto& record : items) {
+ for (const auto& record : items) {
string content = stringFromJson(record, "content");
rr.disabled = false;
- if(!record["disabled"].is_null()) {
+ if (!record["disabled"].is_null()) {
rr.disabled = boolFromJson(record, "disabled");
}
if (rr.qtype.getCode() != QType::AAAA) {
string tmp = makeApiRecordContent(rr.qtype, content);
if (!pdns_iequals(tmp, content)) {
- throw std::runtime_error("Not in expected format (parsed as '"+tmp+"')");
+ throw std::runtime_error("Not in expected format (parsed as '" + tmp + "')");
}
- } else {
+ }
+ else {
struct in6_addr tmpbuf;
if (inet_pton(AF_INET6, content.c_str(), &tmpbuf) != 1 || content.find('.') != string::npos) {
throw std::runtime_error("Invalid IPv6 address");
}
rr.content = makeBackendRecordContent(rr.qtype, content);
}
- catch(std::exception& e)
- {
- throw ApiException("Record "+rr.qname.toString()+"/"+rr.qtype.toString()+" '"+content+"': "+e.what());
+ catch (std::exception& e) {
+ throw ApiException("Record " + rr.qname.toString() + "/" + rr.qtype.toString() + " '" + content + "': " + e.what());
}
new_records.push_back(rr);
}
}
-static void gatherComments(const Json& container, const DNSName& qname, const QType& qtype, vector<Comment>& new_comments) {
+static void gatherComments(const Json& container, const DNSName& qname, const QType& qtype, vector<Comment>& new_comments)
+{
Comment c;
c.qname = qname;
c.qtype = qtype;
}
}
-static void checkDefaultDNSSECAlgos() {
+static void checkDefaultDNSSECAlgos()
+{
int k_algo = DNSSECKeeper::shorthand2algorithm(::arg()["default-ksk-algorithm"]);
int z_algo = DNSSECKeeper::shorthand2algorithm(::arg()["default-zsk-algorithm"]);
int k_size = arg().asNum("default-ksk-size");
if (k_algo == -1)
throw ApiException("default-ksk-algorithm setting is set to unknown algorithm: " + ::arg()["default-ksk-algorithm"]);
else if (k_algo <= 10 && k_size == 0)
- throw ApiException("default-ksk-algorithm is set to an algorithm("+::arg()["default-ksk-algorithm"]+") that requires a non-zero default-ksk-size!");
+ throw ApiException("default-ksk-algorithm is set to an algorithm(" + ::arg()["default-ksk-algorithm"] + ") that requires a non-zero default-ksk-size!");
}
if (::arg()["default-zsk-algorithm"] != "") {
if (z_algo == -1)
throw ApiException("default-zsk-algorithm setting is set to unknown algorithm: " + ::arg()["default-zsk-algorithm"]);
else if (z_algo <= 10 && z_size == 0)
- throw ApiException("default-zsk-algorithm is set to an algorithm("+::arg()["default-zsk-algorithm"]+") that requires a non-zero default-zsk-size!");
+ throw ApiException("default-zsk-algorithm is set to an algorithm(" + ::arg()["default-zsk-algorithm"] + ") that requires a non-zero default-zsk-size!");
}
}
-static void throwUnableToSecure(const DNSName& zonename) {
+static void throwUnableToSecure(const DNSName& zonename)
+{
throw ApiException("No backend was able to secure '" + zonename.toString() + "', most likely because no DNSSEC"
- + "capable backends are loaded, or because the backends have DNSSEC disabled. Check your configuration.");
+ + "capable backends are loaded, or because the backends have DNSSEC disabled. Check your configuration.");
}
/*
* Add KSK and ZSK to an existing zone. Algorithms and sizes will be chosen per configuration.
-*/
-static void addDefaultDNSSECKeys(DNSSECKeeper& dk, const DNSName& zonename) {
+ */
+static void addDefaultDNSSECKeys(DNSSECKeeper& dk, const DNSName& zonename)
+{
checkDefaultDNSSECAlgos();
int k_algo = DNSSECKeeper::shorthand2algorithm(::arg()["default-ksk-algorithm"]);
int z_algo = DNSSECKeeper::shorthand2algorithm(::arg()["default-zsk-algorithm"]);
}
}
-static bool isZoneApiRectifyEnabled(const DomainInfo& di) {
+static bool isZoneApiRectifyEnabled(const DomainInfo& di)
+{
string api_rectify;
di.backend->getDomainMetadataOne(di.zone, "API-RECTIFY", api_rectify);
if (api_rectify.empty() && ::arg().mustDo("default-api-rectify")) {
{
if (document["kind"].is_string()) {
kind = DomainInfo::stringToKind(stringFromJson(document, "kind"));
- } else {
+ }
+ else {
kind = boost::none;
}
if (document["masters"].is_array()) {
primaries = vector<ComboAddress>();
- for(const auto& value : document["masters"].array_items()) {
+ for (const auto& value : document["masters"].array_items()) {
string primary = value.string_value();
if (primary.empty())
throw ApiException("Primary can not be an empty string");
try {
primaries->emplace_back(primary, 53);
- } catch (const PDNSException &e) {
+ }
+ catch (const PDNSException& e) {
throw ApiException("Primary (" + primary + ") is not an IP address: " + e.reason);
}
}
- } else {
+ }
+ else {
primaries = boost::none;
}
if (document["account"].is_string()) {
account = document["account"].string_value();
- } else {
+ }
+ else {
account = boost::none;
}
}
* Build vector of TSIG Key ids from domain update document.
* jsonArray: JSON array element to extract TSIG key ids from.
* metadata: returned list of domain key ids for setDomainMetadata
-*/
-static void extractJsonTSIGKeyIds(UeberBackend& B, const Json& jsonArray, vector<string>& metadata) {
- for(const auto& value : jsonArray.array_items()) {
+ */
+static void extractJsonTSIGKeyIds(UeberBackend& B, const Json& jsonArray, vector<string>& metadata)
+{
+ for (const auto& value : jsonArray.array_items()) {
auto keyname(apiZoneIdToName(value.string_value()));
DNSName keyAlgo;
string keyContent;
if (!B.getTSIGKey(keyname, keyAlgo, keyContent)) {
- throw ApiException("A TSIG key with the name '"+keyname.toLogString()+"' does not exist");
+ throw ApiException("A TSIG key with the name '" + keyname.toLogString() + "' does not exist");
}
metadata.push_back(keyname.toString());
}
}
// Must be called within backend transaction.
-static void updateDomainSettingsFromDocument(UeberBackend& B, DomainInfo& di, const DNSName& zonename, const Json& document, bool zoneWasModified) {
+static void updateDomainSettingsFromDocument(UeberBackend& B, DomainInfo& di, const DNSName& zonename, const Json& document, bool zoneWasModified)
+{
boost::optional<DomainInfo::DomainKind> kind;
boost::optional<vector<ComboAddress>> primaries;
boost::optional<DNSName> catalog;
bool api_rectify = boolFromJson(document, "api_rectify");
di.backend->setDomainMetadataOne(zonename, "API-RECTIFY", api_rectify ? "1" : "0");
}
- catch (const JsonException&) {}
-
+ catch (const JsonException&) {
+ }
DNSSECKeeper dk(&B);
bool shouldRectify = zoneWasModified;
dnssecDocVal = boolFromJson(document, "dnssec");
dnssecInJSON = true;
}
- catch (const JsonException&) {}
+ catch (const JsonException&) {
+ }
try {
nsec3paramDocVal = stringFromJson(document, "nsec3param");
nsec3paramInJSON = true;
}
- catch (const JsonException&) {}
-
+ catch (const JsonException&) {
+ }
bool isDNSSECZone = dk.isSecuredZone(zonename);
bool isPresigned = dk.isPresigned(zonename);
shouldRectify = true;
updateNsec3Param = true;
}
- } else {
+ }
+ else {
// "dnssec": false in json
if (isDNSSECZone) {
string info, error;
if (!dk.unSecureZone(zonename, error)) {
- throw ApiException("Error while un-securing zone '"+ zonename.toString()+"': " + error);
+ throw ApiException("Error while un-securing zone '" + zonename.toString() + "': " + error);
}
isDNSSECZone = dk.isSecuredZone(zonename, false);
if (isDNSSECZone) {
- throw ApiException("Unable to un-secure zone '"+ zonename.toString()+"'");
+ throw ApiException("Unable to un-secure zone '" + zonename.toString() + "'");
}
shouldRectify = true;
updateNsec3Param = true;
NSEC3PARAMRecordContent ns3pr(nsec3paramDocVal);
string error_msg = "";
if (!dk.checkNSEC3PARAM(ns3pr, error_msg)) {
- throw ApiException("NSEC3PARAMs provided for zone '"+zonename.toString()+"' are invalid. " + error_msg);
+ throw ApiException("NSEC3PARAMs provided for zone '" + zonename.toString() + "' are invalid. " + error_msg);
}
if (!dk.setNSEC3PARAM(zonename, ns3pr, boolFromJson(document, "nsec3narrow", false))) {
- throw ApiException("NSEC3PARAMs provided for zone '" + zonename.toString() +
- "' passed our basic sanity checks, but cannot be used with the current backend.");
+ throw ApiException("NSEC3PARAMs provided for zone '" + zonename.toString() + "' passed our basic sanity checks, but cannot be used with the current backend.");
}
}
}
}
}
-static bool isValidMetadataKind(const string& kind, bool readonly) {
- static vector<string> builtinOptions {
+static bool isValidMetadataKind(const string& kind, bool readonly)
+{
+ static vector<string> builtinOptions{
"ALLOW-AXFR-FROM",
"AXFR-SOURCE",
"ALLOW-DNSUPDATE-FROM",
"SLAVE-RENOTIFY",
"SOA-EDIT",
"TSIG-ALLOW-AXFR",
- "TSIG-ALLOW-DNSUPDATE"
- };
+ "TSIG-ALLOW-DNSUPDATE"};
// the following options do not allow modifications via API
- static vector<string> protectedOptions {
+ static vector<string> protectedOptions{
"API-RECTIFY",
"AXFR-MASTER-TSIG",
"NSEC3NARROW",
"NSEC3PARAM",
"PRESIGNED",
"LUA-AXFR-SCRIPT",
- "TSIG-ALLOW-AXFR"
- };
+ "TSIG-ALLOW-AXFR"};
if (kind.find("X-") == 0)
return true;
// this is easier as macro since we need UeberBackend instance in most places
// NOLINTBEGIN(cppcoreguidelines-macro-usage, readability-identifier-length)
-#define zoneFromId(req) \
- DNSName zonename = apiZoneIdToName((req)->parameters["id"]); \
- UeberBackend B; \
- DNSSECKeeper dk(&B); \
- DomainInfo di; \
- try { \
- if (!B.getDomainInfo(zonename, di)) { \
- throw HttpNotFoundException(); \
- } \
- } catch(const PDNSException &e) { \
+#define zoneFromId(req) \
+ DNSName zonename = apiZoneIdToName((req)->parameters["id"]); \
+ UeberBackend B; \
+ DNSSECKeeper dk(&B); \
+ DomainInfo di; \
+ try { \
+ if (!B.getDomainInfo(zonename, di)) { \
+ throw HttpNotFoundException(); \
+ } \
+ } \
+ catch (const PDNSException& e) { \
throw HttpInternalServerErrorException("Could not retrieve Domain Info: " + e.reason); \
}
// NOLINTEND(cppcoreguidelines-macro-usage, readability-identifier-length)
*/
#include "apidocfiles.h"
-void apiDocs(HttpRequest* req, HttpResponse* resp) {
+void apiDocs(HttpRequest* req, HttpResponse* resp)
+{
if (req->accept_yaml) {
resp->setYamlBody(g_api_swagger_yaml);
- } else if (req->accept_json) {
+ }
+ else if (req->accept_json) {
resp->setJsonBody(g_api_swagger_json);
- } else {
+ }
+ else {
resp->setPlainBody(g_api_swagger_yaml);
}
}
-static void apiZoneMetadataGET(HttpRequest* req, HttpResponse *resp) {
+static void apiZoneMetadataGET(HttpRequest* req, HttpResponse* resp)
+{
zoneFromId(req);
- map<string, vector<string> > metas;
+ map<string, vector<string>> metas;
Json::array document;
if (!B.getAllDomainMetadata(zonename, metas)) {
entries.push_back(value);
}
- Json::object key {
- { "type", "Metadata" },
- { "kind", meta.first },
- { "metadata", entries }
- };
+ Json::object key{
+ {"type", "Metadata"},
+ {"kind", meta.first},
+ {"metadata", entries}};
document.push_back(key);
}
resp->setJsonBody(document);
}
-static void apiZoneMetadataPOST(HttpRequest* req, HttpResponse *resp) {
+static void apiZoneMetadataPOST(HttpRequest* req, HttpResponse* resp)
+{
zoneFromId(req);
const auto& document = req->json();
try {
kind = stringFromJson(document, "kind");
- } catch (const JsonException&) {
- throw ApiException("kind is not specified or not a string");
+ }
+ catch (const JsonException&) {
+ throw ApiException("kind is not specified or not a string");
}
if (!isValidMetadataKind(kind, false)) {
vector<string> vecMetadata;
if (!B.getDomainMetadata(zonename, kind, vecMetadata)) {
- throw ApiException("Could not retrieve metadata entries for domain '" +
- zonename.toString() + "'");
+ throw ApiException("Could not retrieve metadata entries for domain '" + zonename.toString() + "'");
}
const auto& metadata = document["metadata"];
throw ApiException("metadata must be strings");
}
if (std::find(vecMetadata.cbegin(),
- vecMetadata.cend(),
- value.string_value()) == vecMetadata.cend()) {
+ vecMetadata.cend(),
+ value.string_value())
+ == vecMetadata.cend()) {
vecMetadata.push_back(value.string_value());
}
}
if (!B.setDomainMetadata(zonename, kind, vecMetadata)) {
- throw ApiException("Could not update metadata entries for domain '" +
- zonename.toString() + "'");
+ throw ApiException("Could not update metadata entries for domain '" + zonename.toString() + "'");
}
DNSSECKeeper::clearMetaCache(zonename);
respMetadata.push_back(value);
}
- Json::object key {
- { "type", "Metadata" },
- { "kind", document["kind"] },
- { "metadata", respMetadata }
- };
+ Json::object key{
+ {"type", "Metadata"},
+ {"kind", document["kind"]},
+ {"metadata", respMetadata}};
resp->status = 201;
resp->setJsonBody(key);
}
-static void apiZoneMetadataKindGET(HttpRequest* req, HttpResponse* resp) {
+static void apiZoneMetadataKindGET(HttpRequest* req, HttpResponse* resp)
+{
zoneFromId(req);
string kind = req->parameters["kind"];
resp->setJsonBody(document);
}
-static void apiZoneMetadataKindPUT(HttpRequest* req, HttpResponse* resp) {
+static void apiZoneMetadataKindPUT(HttpRequest* req, HttpResponse* resp)
+{
zoneFromId(req);
string kind = req->parameters["kind"];
DNSSECKeeper::clearMetaCache(zonename);
- Json::object key {
- { "type", "Metadata" },
- { "kind", kind },
- { "metadata", metadata }
- };
+ Json::object key{
+ {"type", "Metadata"},
+ {"kind", kind},
+ {"metadata", metadata}};
resp->setJsonBody(key);
}
-static void apiZoneMetadataKindDELETE(HttpRequest* req, HttpResponse* resp) {
+static void apiZoneMetadataKindDELETE(HttpRequest* req, HttpResponse* resp)
+{
zoneFromId(req);
const string& kind = req->parameters["kind"];
throw ApiException("Unsupported metadata kind '" + kind + "'");
}
- vector<string> metadata; // an empty vector will do it
+ vector<string> metadata; // an empty vector will do it
if (!B.setDomainMetadata(zonename, kind, metadata)) {
throw ApiException("Could not delete metadata for domain '" + zonename.toString() + "' (" + kind + ")");
}
}
// Throws 404 if the key with inquireKeyId does not exist
-static void apiZoneCryptoKeysCheckKeyExists(const DNSName& zonename, int inquireKeyId, DNSSECKeeper *dk) {
- DNSSECKeeper::keyset_t keyset=dk->getKeys(zonename, false);
+static void apiZoneCryptoKeysCheckKeyExists(const DNSName& zonename, int inquireKeyId, DNSSECKeeper* dk)
+{
+ DNSSECKeeper::keyset_t keyset = dk->getKeys(zonename, false);
bool found = false;
- for(const auto& value : keyset) {
- if (value.second.id == (unsigned) inquireKeyId) {
+ for (const auto& value : keyset) {
+ if (value.second.id == (unsigned)inquireKeyId) {
found = true;
break;
}
}
}
-static inline int getInquireKeyId(HttpRequest *req, const DNSName& zonename, DNSSECKeeper *dnsseckeeper) {
+static inline int getInquireKeyId(HttpRequest* req, const DNSName& zonename, DNSSECKeeper* dnsseckeeper)
+{
int inquireKeyId = -1;
if (req->parameters.count("key_id") == 1) {
inquireKeyId = std::stoi(req->parameters["key_id"]);
return inquireKeyId;
}
-static void apiZoneCryptokeysExport(const DNSName& zonename, int64_t inquireKeyId, HttpResponse *resp, DNSSECKeeper *dnssec_dk) {
- DNSSECKeeper::keyset_t keyset=dnssec_dk->getKeys(zonename, false);
+static void apiZoneCryptokeysExport(const DNSName& zonename, int64_t inquireKeyId, HttpResponse* resp, DNSSECKeeper* dnssec_dk)
+{
+ DNSSECKeeper::keyset_t keyset = dnssec_dk->getKeys(zonename, false);
bool inquireSingleKey = inquireKeyId >= 0;
Json::array doc;
- for(const auto& value : keyset) {
+ for (const auto& value : keyset) {
if (inquireSingleKey && (unsigned)inquireKeyId != value.second.id) {
continue;
}
string keyType;
switch (value.second.keyType) {
- case DNSSECKeeper::KSK: keyType="ksk"; break;
- case DNSSECKeeper::ZSK: keyType="zsk"; break;
- case DNSSECKeeper::CSK: keyType="csk"; break;
- }
-
- Json::object key {
- { "type", "Cryptokey" },
- { "id", static_cast<int>(value.second.id) },
- { "active", value.second.active },
- { "published", value.second.published },
- { "keytype", keyType },
- { "flags", static_cast<uint16_t>(value.first.getFlags()) },
- { "dnskey", value.first.getDNSKEY().getZoneRepresentation() },
- { "algorithm", DNSSECKeeper::algorithm2name(value.first.getAlgorithm()) },
- { "bits", value.first.getKey()->getBits() }
- };
+ case DNSSECKeeper::KSK:
+ keyType = "ksk";
+ break;
+ case DNSSECKeeper::ZSK:
+ keyType = "zsk";
+ break;
+ case DNSSECKeeper::CSK:
+ keyType = "csk";
+ break;
+ }
+
+ Json::object key{
+ {"type", "Cryptokey"},
+ {"id", static_cast<int>(value.second.id)},
+ {"active", value.second.active},
+ {"published", value.second.published},
+ {"keytype", keyType},
+ {"flags", static_cast<uint16_t>(value.first.getFlags())},
+ {"dnskey", value.first.getDNSKEY().getZoneRepresentation()},
+ {"algorithm", DNSSECKeeper::algorithm2name(value.first.getAlgorithm())},
+ {"bits", value.first.getKey()->getBits()}};
string publishCDS;
dnssec_dk->getPublishCDS(zonename, publishCDS);
stringtok(digestAlgos, publishCDS, ", ");
std::set<unsigned int> CDSalgos;
- for(auto const &digestAlgo : digestAlgos) {
+ for (auto const& digestAlgo : digestAlgos) {
CDSalgos.insert(pdns::checked_stoi<unsigned int>(digestAlgo));
}
if (value.second.keyType == DNSSECKeeper::KSK || value.second.keyType == DNSSECKeeper::CSK) {
Json::array cdses;
Json::array dses;
- for(const uint8_t keyid : { DNSSECKeeper::DIGEST_SHA1, DNSSECKeeper::DIGEST_SHA256, DNSSECKeeper::DIGEST_GOST, DNSSECKeeper::DIGEST_SHA384 })
+ for (const uint8_t keyid : {DNSSECKeeper::DIGEST_SHA1, DNSSECKeeper::DIGEST_SHA256, DNSSECKeeper::DIGEST_GOST, DNSSECKeeper::DIGEST_SHA384})
try {
string ds = makeDSFromDNSKey(zonename, value.first.getDNSKEY(), keyid).getZoneRepresentation();
dses.push_back(ds);
- if (CDSalgos.count(keyid)) { cdses.push_back(ds); }
- } catch (...) {}
+ if (CDSalgos.count(keyid)) {
+ cdses.push_back(ds);
+ }
+ }
+ catch (...) {
+ }
key["ds"] = dses;
resp->setJsonBody(doc);
}
-static void apiZoneCryptokeysGET(HttpRequest *req, HttpResponse *resp) {
+static void apiZoneCryptokeysGET(HttpRequest* req, HttpResponse* resp)
+{
zoneFromId(req);
const auto inquireKeyId = getInquireKeyId(req, zonename, &dk);
* Case 3: the key or zone does not exist.
* The server returns 404 Not Found
* */
-static void apiZoneCryptokeysDELETE(HttpRequest *req, HttpResponse *resp) {
+static void apiZoneCryptokeysDELETE(HttpRequest* req, HttpResponse* resp)
+{
zoneFromId(req);
const auto inquireKeyId = getInquireKeyId(req, zonename, &dk);
if (inquireKeyId == -1) {
- throw HttpBadRequestException();
+ throw HttpBadRequestException();
}
if (dk.removeKey(zonename, inquireKeyId)) {
resp->body = "";
resp->status = 204;
- } else {
+ }
+ else {
resp->setErrorResult("Could not DELETE " + req->parameters["key_id"], 422);
}
}
* The server returns 201 Created and all public data about the added cryptokey
*/
-static void apiZoneCryptokeysPOST(HttpRequest *req, HttpResponse *resp) {
+static void apiZoneCryptokeysPOST(HttpRequest* req, HttpResponse* resp)
+{
zoneFromId(req);
const auto& document = req->json();
if (stringFromJson(document, "keytype") == "ksk" || stringFromJson(document, "keytype") == "csk") {
keyOrZone = true;
- } else if (stringFromJson(document, "keytype") == "zsk") {
+ }
+ else if (stringFromJson(document, "keytype") == "zsk") {
keyOrZone = false;
- } else {
+ }
+ else {
throw ApiException("Invalid keytype " + stringFromJson(document, "keytype"));
}
if (!docbits.is_null()) {
if (!docbits.is_number() || (fmod(docbits.number_value(), 1.0) != 0) || docbits.int_value() < 0) {
throw ApiException("'bits' must be a positive integer value");
- } else {
+ }
+ else {
bits = docbits.int_value();
}
}
if (algorithm == -1) {
throw ApiException("Unknown algorithm: " + providedAlgo.string_value());
}
- } else if (providedAlgo.is_number()) {
+ }
+ else if (providedAlgo.is_number()) {
algorithm = providedAlgo.int_value();
- } else if (!providedAlgo.is_null()) {
+ }
+ else if (!providedAlgo.is_null()) {
throw ApiException("Unknown algorithm: " + providedAlgo.string_value());
}
if (!dk.addKey(zonename, keyOrZone, algorithm, insertedId, bits, active, published)) {
throw ApiException("Adding key failed, perhaps DNSSEC not enabled in configuration?");
}
- } catch (std::runtime_error& error) {
+ }
+ catch (std::runtime_error& error) {
throw ApiException(error.what());
}
if (insertedId < 0)
throw ApiException("Adding key failed, perhaps DNSSEC not enabled in configuration?");
- } else if (document["bits"].is_null() && document["algorithm"].is_null()) {
+ }
+ else if (document["bits"].is_null() && document["algorithm"].is_null()) {
const auto& keyData = stringFromJson(document, privatekey_fieldname);
DNSKEYRecordContent dkrc;
DNSSECPrivateKey dpk;
}
catch (std::runtime_error& error) {
throw ApiException("Key could not be parsed. Make sure your key format is correct.");
- } try {
+ }
+ try {
if (!dk.addKey(zonename, dpk, insertedId, active, published)) {
throw ApiException("Adding key failed, perhaps DNSSEC not enabled in configuration?");
}
- } catch (std::runtime_error& error) {
+ }
+ catch (std::runtime_error& error) {
throw ApiException(error.what());
}
if (insertedId < 0) {
throw ApiException("Adding key failed, perhaps DNSSEC not enabled in configuration?");
}
- } else {
+ }
+ else {
throw ApiException("Either you submit just the 'privatekey' field or you leave 'privatekey' empty and submit the other fields.");
}
apiZoneCryptokeysExport(zonename, insertedId, resp, &dk);
* Case 3: the backend returns false on de/activation. An error occurred.
* The sever returns 422 Unprocessable Entity with message "Could not de/activate Key: :cryptokey_id in Zone: :zone_name"
* */
-static void apiZoneCryptokeysPUT(HttpRequest *req, HttpResponse *resp) {
+static void apiZoneCryptokeysPUT(HttpRequest* req, HttpResponse* resp)
+{
zoneFromId(req);
const auto inquireKeyId = getInquireKeyId(req, zonename, &dk);
if (inquireKeyId == -1) {
throw HttpBadRequestException();
}
- //throws an exception if the Body is empty
+ // throws an exception if the Body is empty
const auto& document = req->json();
- //throws an exception if the key does not exist or is not a bool
+ // throws an exception if the key does not exist or is not a bool
bool active = boolFromJson(document, "active");
bool published = boolFromJson(document, "published", true);
if (active) {
resp->setErrorResult("Could not activate Key: " + req->parameters["key_id"] + " in Zone: " + zonename.toString(), 422);
return;
}
- } else {
+ }
+ else {
if (!dk.deactivateKey(zonename, inquireKeyId)) {
resp->setErrorResult("Could not deactivate Key: " + req->parameters["key_id"] + " in Zone: " + zonename.toString(), 422);
return;
resp->setErrorResult("Could not publish Key: " + req->parameters["key_id"] + " in Zone: " + zonename.toString(), 422);
return;
}
- } else {
+ }
+ else {
if (!dk.unpublishKey(zonename, inquireKeyId)) {
resp->setErrorResult("Could not unpublish Key: " + req->parameters["key_id"] + " in Zone: " + zonename.toString(), 422);
return;
return;
}
-static void gatherRecordsFromZone(const std::string& zonestring, vector<DNSResourceRecord>& new_records, const DNSName& zonename) {
+static void gatherRecordsFromZone(const std::string& zonestring, vector<DNSResourceRecord>& new_records, const DNSName& zonename)
+{
DNSResourceRecord rr;
vector<string> zonedata;
stringtok(zonedata, zonestring, "\r\n");
zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps"));
zpt.setMaxIncludes(::arg().asNum("max-include-depth"));
- bool seenSOA=false;
+ bool seenSOA = false;
string comment = "Imported via the API";
try {
- while(zpt.get(rr, &comment)) {
- if(seenSOA && rr.qtype.getCode() == QType::SOA)
+ while (zpt.get(rr, &comment)) {
+ if (seenSOA && rr.qtype.getCode() == QType::SOA)
continue;
- if(rr.qtype.getCode() == QType::SOA)
- seenSOA=true;
+ if (rr.qtype.getCode() == QType::SOA)
+ seenSOA = true;
validateGatheredRRType(rr);
new_records.push_back(rr);
}
}
- catch(std::exception& ae) {
- throw ApiException("An error occurred while parsing the zonedata: "+string(ae.what()));
+ catch (std::exception& ae) {
+ throw ApiException("An error occurred while parsing the zonedata: " + string(ae.what()));
}
}
static void checkNewRecords(vector<DNSResourceRecord>& records, const DNSName& zone)
{
sort(records.begin(), records.end(),
- [](const DNSResourceRecord& rec_a, const DNSResourceRecord& rec_b) -> bool {
- /* we need _strict_ weak ordering */
- return std::tie(rec_a.qname, rec_a.qtype, rec_a.content) < std::tie(rec_b.qname, rec_b.qtype, rec_b.content);
- }
- );
+ [](const DNSResourceRecord& rec_a, const DNSResourceRecord& rec_b) -> bool {
+ /* we need _strict_ weak ordering */
+ return std::tie(rec_a.qname, rec_a.qtype, rec_a.content) < std::tie(rec_b.qname, rec_b.qtype, rec_b.content);
+ });
DNSResourceRecord previous;
- for(const auto& rec : records) {
+ for (const auto& rec : records) {
if (previous.qname == rec.qname) {
if (previous.qtype == rec.qtype) {
if (onlyOneEntryTypes.count(rec.qtype.getCode()) != 0) {
- throw ApiException("RRset "+rec.qname.toString()+" IN "+rec.qtype.toString()+" has more than one record");
+ throw ApiException("RRset " + rec.qname.toString() + " IN " + rec.qtype.toString() + " has more than one record");
}
if (previous.content == rec.content) {
throw ApiException("Duplicate record in RRset " + rec.qname.toString() + " IN " + rec.qtype.toString() + " with content \"" + rec.content + "\"");
}
- } else if (exclusiveEntryTypes.count(rec.qtype.getCode()) != 0 || exclusiveEntryTypes.count(previous.qtype.getCode()) != 0) {
- throw ApiException("RRset "+rec.qname.toString()+" IN "+rec.qtype.toString()+": Conflicts with another RRset");
+ }
+ else if (exclusiveEntryTypes.count(rec.qtype.getCode()) != 0 || exclusiveEntryTypes.count(previous.qtype.getCode()) != 0) {
+ throw ApiException("RRset " + rec.qname.toString() + " IN " + rec.qtype.toString() + ": Conflicts with another RRset");
}
}
// Check if the DNSNames that should be hostnames, are hostnames
try {
checkHostnameCorrectness(rec);
- } catch (const std::exception& e) {
- throw ApiException("RRset "+rec.qname.toString()+" IN "+rec.qtype.toString() + ": " + e.what());
+ }
+ catch (const std::exception& e) {
+ throw ApiException("RRset " + rec.qname.toString() + " IN " + rec.qtype.toString() + ": " + e.what());
}
previous = rec;
}
}
-static void checkTSIGKey(UeberBackend& B, const DNSName& keyname, const DNSName& algo, const string& content) {
+static void checkTSIGKey(UeberBackend& B, const DNSName& keyname, const DNSName& algo, const string& content)
+{
DNSName algoFromDB;
string contentFromDB;
if (B.getTSIGKey(keyname, algoFromDB, contentFromDB)) {
- throw HttpConflictException("A TSIG key with the name '"+keyname.toLogString()+"' already exists");
+ throw HttpConflictException("A TSIG key with the name '" + keyname.toLogString() + "' already exists");
}
TSIGHashEnum the;
}
}
-static Json::object makeJSONTSIGKey(const DNSName& keyname, const DNSName& algo, const string& content) {
+static Json::object makeJSONTSIGKey(const DNSName& keyname, const DNSName& algo, const string& content)
+{
Json::object tsigkey = {
- { "name", keyname.toStringNoDot() },
- { "id", apiZoneNameToId(keyname) },
- { "algorithm", algo.toStringNoDot() },
- { "key", content },
- { "type", "TSIGKey" }
- };
+ {"name", keyname.toStringNoDot()},
+ {"id", apiZoneNameToId(keyname)},
+ {"algorithm", algo.toStringNoDot()},
+ {"key", content},
+ {"type", "TSIGKey"}};
return tsigkey;
}
-static Json::object makeJSONTSIGKey(const struct TSIGKey& key, bool doContent=true) {
+static Json::object makeJSONTSIGKey(const struct TSIGKey& key, bool doContent = true)
+{
return makeJSONTSIGKey(key.name, key.algorithm, doContent ? key.key : "");
}
-static void apiServerTSIGKeysGET(HttpRequest* /* req */, HttpResponse* resp) {
+static void apiServerTSIGKeysGET(HttpRequest* /* req */, HttpResponse* resp)
+{
UeberBackend B; // NOLINT(readability-identifier-length)
vector<struct TSIGKey> keys;
Json::array doc;
- for(const auto &key : keys) {
+ for (const auto& key : keys) {
doc.push_back(makeJSONTSIGKey(key, false));
}
resp->setJsonBody(doc);
}
-static void apiServerTSIGKeysPOST(HttpRequest* req, HttpResponse* resp) {
+static void apiServerTSIGKeysPOST(HttpRequest* req, HttpResponse* resp)
+{
UeberBackend B; // NOLINT(readability-identifier-length)
const auto& document = req->json();
DNSName keyname(stringFromJson(document, "name"));
if (content.empty()) {
try {
content = makeTSIGKey(algo);
- } catch (const PDNSException& exc) {
+ }
+ catch (const PDNSException& exc) {
throw HttpBadRequestException(exc.reason);
}
}
// Will throw an ApiException or HttpConflictException on error
checkTSIGKey(B, keyname, algo, content);
- if(!B.setTSIGKey(keyname, algo, content)) {
+ if (!B.setTSIGKey(keyname, algo, content)) {
throw HttpInternalServerErrorException("Unable to add TSIG key");
}
}
// NOLINTBEGIN(cppcoreguidelines-macro-usage, readability-identifier-length)
-#define TSIGKeyFromId(req) \
- UeberBackend B; \
- DNSName keyname = apiZoneIdToName((req)->parameters["id"]); \
- DNSName algo; \
- string content; \
- try { \
- if (!B.getTSIGKey(keyname, algo, content)) { \
- throw HttpNotFoundException("TSIG key with name '"+keyname.toLogString()+"' not found"); \
- } \
- } catch(const PDNSException &e) { \
- throw HttpInternalServerErrorException("Could not retrieve Domain Info: " + e.reason); \
- } \
- struct TSIGKey tsk; \
- tsk.name = keyname; \
- tsk.algorithm = algo; \
+#define TSIGKeyFromId(req) \
+ UeberBackend B; \
+ DNSName keyname = apiZoneIdToName((req)->parameters["id"]); \
+ DNSName algo; \
+ string content; \
+ try { \
+ if (!B.getTSIGKey(keyname, algo, content)) { \
+ throw HttpNotFoundException("TSIG key with name '" + keyname.toLogString() + "' not found"); \
+ } \
+ } \
+ catch (const PDNSException& e) { \
+ throw HttpInternalServerErrorException("Could not retrieve Domain Info: " + e.reason); \
+ } \
+ struct TSIGKey tsk; \
+ tsk.name = keyname; \
+ tsk.algorithm = algo; \
tsk.key = std::move(content);
// NOLINTEND(cppcoreguidelines-macro-usage, readability-identifier-length)
-static void apiServerTSIGKeyDetailGET(HttpRequest* req, HttpResponse* resp) {
+static void apiServerTSIGKeyDetailGET(HttpRequest* req, HttpResponse* resp)
+{
TSIGKeyFromId(req);
resp->setJsonBody(makeJSONTSIGKey(tsk));
}
-static void apiServerTSIGKeyDetailPUT(HttpRequest* req, HttpResponse* resp) {
+static void apiServerTSIGKeyDetailPUT(HttpRequest* req, HttpResponse* resp)
+{
TSIGKeyFromId(req);
const auto& document = req->json();
resp->setJsonBody(makeJSONTSIGKey(tsk));
}
-static void apiServerTSIGKeyDetailDELETE(HttpRequest* req, HttpResponse* resp) {
+static void apiServerTSIGKeyDetailDELETE(HttpRequest* req, HttpResponse* resp)
+{
TSIGKeyFromId(req);
if (!B.deleteTSIGKey(keyname)) {
throw HttpInternalServerErrorException("Unable to remove TSIG key '" + keyname.toStringNoDot() + "'");
resp->status = 204;
}
-static void apiServerAutoprimaryDetailDELETE(HttpRequest* req, HttpResponse* resp) {
+static void apiServerAutoprimaryDetailDELETE(HttpRequest* req, HttpResponse* resp)
+{
UeberBackend B; // NOLINT(readability-identifier-length)
const AutoPrimary& primary{req->parameters["ip"], req->parameters["nameserver"], ""};
if (!B.autoPrimaryRemove(primary)) {
- throw HttpInternalServerErrorException("Cannot find backend with autoprimary feature");
+ throw HttpInternalServerErrorException("Cannot find backend with autoprimary feature");
}
resp->body = "";
resp->status = 204;
}
-static void apiServerAutoprimariesGET(HttpRequest* /* req */, HttpResponse* resp) {
+static void apiServerAutoprimariesGET(HttpRequest* /* req */, HttpResponse* resp)
+{
UeberBackend B; // NOLINT(readability-identifier-length)
std::vector<AutoPrimary> primaries;
throw HttpInternalServerErrorException("Unable to retrieve autoprimaries");
}
Json::array doc;
- for (const auto& primary: primaries) {
+ for (const auto& primary : primaries) {
const Json::object obj = {
- { "ip", primary.ip },
- { "nameserver", primary.nameserver },
- { "account", primary.account }
- };
+ {"ip", primary.ip},
+ {"nameserver", primary.nameserver},
+ {"account", primary.account}};
doc.push_back(obj);
}
resp->setJsonBody(doc);
}
-static void apiServerAutoprimariesPOST(HttpRequest* req, HttpResponse* resp) {
+static void apiServerAutoprimariesPOST(HttpRequest* req, HttpResponse* resp)
+{
UeberBackend B; // NOLINT(readability-identifier-length)
const auto& document = req->json();
}
// create new zone
-static void apiServerZonesPOST(HttpRequest* req, HttpResponse* resp) {
+static void apiServerZonesPOST(HttpRequest* req, HttpResponse* resp)
+{
UeberBackend B; // NOLINT(readability-identifier-length)
DNSSECKeeper dk(&B); // NOLINT(readability-identifier-length)
DomainInfo di; // NOLINT(readability-identifier-length)
QType qtype;
qtype = stringFromJson(rrset, "type");
if (qtype.getCode() == 0) {
- throw ApiException("RRset "+qname.toString()+" IN "+stringFromJson(rrset, "type")+": unknown type given");
+ throw ApiException("RRset " + qname.toString() + " IN " + stringFromJson(rrset, "type") + ": unknown type given");
}
if (rrset["records"].is_array()) {
uint32_t ttl = uintFromJson(rrset, "ttl");
gatherComments(rrset, qname, qtype, new_comments);
}
}
- } else if (!zonestring.empty()) {
+ }
+ else if (!zonestring.empty()) {
gatherRecordsFromZone(zonestring, new_records, zonename);
}
}
throw ApiException("Zone data MUST NOT be given for Consumer zones");
}
- for(auto& rr : new_records) { // NOLINT(readability-identifier-length)
+ for (auto& rr : new_records) { // NOLINT(readability-identifier-length)
rr.qname.makeUsLowerCase();
if (!rr.qname.isPartOf(zonename) && rr.qname != zonename) {
- throw ApiException("RRset "+rr.qname.toString()+" IN "+rr.qtype.toString()+": Name is out of zone");
+ throw ApiException("RRset " + rr.qname.toString() + " IN " + rr.qtype.toString() + ": Name is out of zone");
}
apiCheckQNameAllowedCharacters(rr.qname.toString());
boost::replace_all(soa, "@", zonename.toStringNoDot());
SOAData sd; // NOLINT(readability-identifier-length)
fillSOAData(soa, sd);
- sd.serial=document["serial"].int_value();
+ sd.serial = document["serial"].int_value();
autorr.qtype = QType::SOA;
autorr.content = makeSOAContent(sd)->getZoneRepresentation(true);
// updateDomainSettingsFromDocument will apply SOA-EDIT-API as needed
try {
// ensure the name parses
autorr.content = DNSName(nameserver).toStringRootDot();
- } catch (...) {
+ }
+ catch (...) {
throw ApiException("Unable to parse DNS Name for NS '" + nameserver + "'");
}
autorr.qtype = QType::NS;
if (boolFromJson(document, "dnssec", false)) {
checkDefaultDNSSECAlgos();
- if(document["nsec3param"].string_value().length() > 0) {
+ if (document["nsec3param"].string_value().length() > 0) {
NSEC3PARAMRecordContent ns3pr(document["nsec3param"].string_value());
string error_msg;
if (!dk.checkNSEC3PARAM(ns3pr, error_msg)) {
- throw ApiException("NSEC3PARAMs provided for zone '"+zonename.toString()+"' are invalid. " + error_msg);
+ throw ApiException("NSEC3PARAMs provided for zone '" + zonename.toString() + "' are invalid. " + error_msg);
}
}
}
// no going back after this
if (!B.createDomain(zonename, kind.get_value_or(DomainInfo::Native), primaries.get_value_or(vector<ComboAddress>()), account.get_value_or(""))) {
- throw ApiException("Creating domain '"+zonename.toString()+"' failed: backend refused");
+ throw ApiException("Creating domain '" + zonename.toString() + "' failed: backend refused");
}
- if(!B.getDomainInfo(zonename, di)) {
- throw ApiException("Creating domain '"+zonename.toString()+"' failed: lookup of domain ID failed");
+ if (!B.getDomainInfo(zonename, di)) {
+ throw ApiException("Creating domain '" + zonename.toString() + "' failed: lookup of domain ID failed");
}
di.backend->startTransaction(zonename, static_cast<int>(di.id));
// will be overridden by updateDomainSettingsFromDocument, if given in document.
di.backend->setDomainMetadataOne(zonename, "SOA-EDIT-API", "DEFAULT");
- for(auto& rr : new_records) { // NOLINT(readability-identifier-length)
+ for (auto& rr : new_records) { // NOLINT(readability-identifier-length)
rr.domain_id = static_cast<int>(di.id);
di.backend->feedRecord(rr, DNSName());
}
- for(Comment& comment : new_comments) {
+ for (Comment& comment : new_comments) {
comment.domain_id = static_cast<int>(di.id);
if (!di.backend->feedComment(comment)) {
throw ApiException("Hosting backend does not support editing comments.");
}
// list known zones
-static void apiServerZonesGET(HttpRequest* req, HttpResponse* resp) {
+static void apiServerZonesGET(HttpRequest* req, HttpResponse* resp)
+{
UeberBackend B; // NOLINT(readability-identifier-length)
DNSSECKeeper dk(&B); // NOLINT(readability-identifier-length)
vector<DomainInfo> domains;
if (B.getDomainInfo(zonename, di)) {
domains.push_back(di);
}
- } else {
+ }
+ else {
try {
B.getAllDomains(&domains, true, true); // incl. serial and disabled
- } catch(const PDNSException &e) { // NOLINT(readability-identifier-length)
+ }
+ catch (const PDNSException& e) { // NOLINT(readability-identifier-length)
throw HttpInternalServerErrorException("Could not retrieve all domain information: " + e.reason);
}
}
Json::array doc;
doc.reserve(domains.size());
- for(const DomainInfo& di : domains) {
+ for (const DomainInfo& di : domains) {
doc.push_back(getZoneInfo(di, with_dnssec ? &dk : nullptr));
}
resp->setJsonBody(doc);
}
-static void apiServerZoneDetailPUT(HttpRequest* req, HttpResponse* resp) {
+static void apiServerZoneDetailPUT(HttpRequest* req, HttpResponse* resp)
+{
zoneFromId(req);
// update domain contents and/or settings
QType qtype;
qtype = stringFromJson(rrset, "type");
if (qtype.getCode() == 0) {
- throw ApiException("RRset "+qname.toString()+" IN "+stringFromJson(rrset, "type")+": unknown type given");
+ throw ApiException("RRset " + qname.toString() + " IN " + stringFromJson(rrset, "type") + ": unknown type given");
}
if (rrset["records"].is_array()) {
uint32_t ttl = uintFromJson(rrset, "ttl");
throw ApiException("New RRsets are invalid: " + string(exc.what()));
}
- for(auto& rr : new_records) { // NOLINT(readability-identifier-length)
+ for (auto& rr : new_records) { // NOLINT(readability-identifier-length)
rr.qname.makeUsLowerCase();
if (!rr.qname.isPartOf(zonename) && rr.qname != zonename) {
- throw ApiException("RRset "+rr.qname.toString()+" IN "+rr.qtype.toString()+": Name is out of zone");
+ throw ApiException("RRset " + rr.qname.toString() + " IN " + rr.qtype.toString() + ": Name is out of zone");
}
apiCheckQNameAllowedCharacters(rr.qname.toString());
checkNewRecords(new_records, zonename);
di.backend->startTransaction(zonename, static_cast<int>(di.id));
- for(auto& rr : new_records) { // NOLINT(readability-identifier-length)
+ for (auto& rr : new_records) { // NOLINT(readability-identifier-length)
rr.domain_id = static_cast<int>(di.id);
di.backend->feedRecord(rr, DNSName());
}
- for(Comment& comment : new_comments) {
+ for (Comment& comment : new_comments) {
comment.domain_id = static_cast<int>(di.id);
di.backend->feedComment(comment);
}
if (!haveSoa && (newKind == DomainInfo::Secondary || newKind == DomainInfo::Consumer)) {
di.backend->setStale(di.id);
}
- } else {
+ }
+ else {
// avoid deleting current zone contents
di.backend->startTransaction(zonename, -1);
}
resp->status = 204; // No Content, but indicate success
}
-static void apiServerZoneDetailDELETE(HttpRequest* req, HttpResponse* resp) {
+static void apiServerZoneDetailDELETE(HttpRequest* req, HttpResponse* resp)
+{
zoneFromId(req);
// delete domain
di.backend->startTransaction(zonename, -1);
try {
- if(!di.backend->deleteDomain(zonename)) {
- throw ApiException("Deleting domain '"+zonename.toString()+"' failed: backend delete failed/unsupported");
+ if (!di.backend->deleteDomain(zonename)) {
+ throw ApiException("Deleting domain '" + zonename.toString() + "' failed: backend delete failed/unsupported");
}
di.backend->commitTransaction();
g_zoneCache.remove(zonename);
- } catch (...) {
+ }
+ catch (...) {
di.backend->abortTransaction();
throw;
}
resp->status = 204; // No Content: declare that the zone is gone now
}
-static void apiServerZoneDetailPATCH(HttpRequest* req, HttpResponse* resp) {
+static void apiServerZoneDetailPATCH(HttpRequest* req, HttpResponse* resp)
+{
zoneFromId(req);
patchZone(B, zonename, di, req, resp);
}
-static void apiServerZoneDetailGET(HttpRequest* req, HttpResponse* resp) {
+static void apiServerZoneDetailGET(HttpRequest* req, HttpResponse* resp)
+{
zoneFromId(req);
fillZone(B, zonename, resp, req);
}
-static void apiServerZoneExport(HttpRequest* req, HttpResponse* resp) {
+static void apiServerZoneExport(HttpRequest* req, HttpResponse* resp)
+{
zoneFromId(req);
ostringstream ss;
DNSResourceRecord rr;
SOAData sd;
di.backend->list(zonename, di.id);
- while(di.backend->get(rr)) {
+ while (di.backend->get(rr)) {
if (!rr.qtype.getCode())
continue; // skip empty non-terminals
- ss <<
- rr.qname.toString() << "\t" <<
- rr.ttl << "\t" <<
- "IN" << "\t" <<
- rr.qtype.toString() << "\t" <<
- makeApiRecordContent(rr.qtype, rr.content) <<
- endl;
+ ss << rr.qname.toString() << "\t" << rr.ttl << "\t"
+ << "IN"
+ << "\t" << rr.qtype.toString() << "\t" << makeApiRecordContent(rr.qtype, rr.content) << endl;
}
if (req->accept_json) {
- resp->setJsonBody(Json::object { { "zone", ss.str() } });
- } else {
+ resp->setJsonBody(Json::object{{"zone", ss.str()}});
+ }
+ else {
resp->headers["Content-Type"] = "text/plain; charset=us-ascii";
resp->body = ss.str();
}
}
-static void apiServerZoneAxfrRetrieve(HttpRequest* req, HttpResponse* resp) {
+static void apiServerZoneAxfrRetrieve(HttpRequest* req, HttpResponse* resp)
+{
zoneFromId(req);
if (di.primaries.empty())
resp->setSuccessResult("Added retrieval request for '" + zonename.toString() + "' from primary " + di.primaries.front().toLogString());
}
-static void apiServerZoneNotify(HttpRequest* req, HttpResponse* resp) {
+static void apiServerZoneNotify(HttpRequest* req, HttpResponse* resp)
+{
zoneFromId(req);
- if(!Communicator.notifyDomain(zonename, &B))
+ if (!Communicator.notifyDomain(zonename, &B))
throw ApiException("Failed to add to the queue - see server log");
resp->setSuccessResult("Notification queued");
}
-static void apiServerZoneRectify(HttpRequest* req, HttpResponse* resp) {
+static void apiServerZoneRectify(HttpRequest* req, HttpResponse* resp)
+{
zoneFromId(req);
if (dk.isPresigned(zonename))
QType qtype;
qtype = stringFromJson(rrset, "type");
if (qtype.getCode() == 0) {
- throw ApiException("RRset "+qname.toString()+" IN "+stringFromJson(rrset, "type")+": unknown type given");
+ throw ApiException("RRset " + qname.toString() + " IN " + stringFromJson(rrset, "type") + ": unknown type given");
}
- if(seen.count({qname, qtype, changetype}))
- {
- throw ApiException("Duplicate RRset "+qname.toString()+" IN "+qtype.toString()+" with changetype: "+changetype);
+ if (seen.count({qname, qtype, changetype})) {
+ throw ApiException("Duplicate RRset " + qname.toString() + " IN " + qtype.toString() + " with changetype: " + changetype);
}
seen.insert({qname, qtype, changetype});
else if (changetype == "REPLACE") {
// we only validate for REPLACE, as DELETE can be used to "fix" out of zone records.
if (!qname.isPartOf(zonename) && qname != zonename)
- throw ApiException("RRset "+qname.toString()+" IN "+qtype.toString()+": Name is out of zone");
+ throw ApiException("RRset " + qname.toString() + " IN " + qtype.toString() + ": Name is out of zone");
bool replace_records = rrset["records"].is_array();
bool replace_comments = rrset["comments"].is_array();
uint32_t ttl = uintFromJson(rrset, "ttl");
gatherRecords(rrset, qname, qtype, ttl, new_records);
- for(DNSResourceRecord& rr : new_records) {
+ for (DNSResourceRecord& rr : new_records) {
rr.domain_id = static_cast<int>(di.id);
if (rr.qtype.getCode() == QType::SOA && rr.qname == zonename) {
soa_edit_done = increaseSOARecord(rr, soa_edit_api_kind, soa_edit_kind);
if (replace_comments) {
gatherComments(rrset, qname, qtype, new_comments);
- for(Comment& c : new_comments) {
+ for (Comment& c : new_comments) {
c.domain_id = static_cast<int>(di.id);
}
}
if (qtype == QType::NS || rr.qtype == QType::NS)
ns_seen = true;
if (qtype.getCode() != rr.qtype.getCode()
- && (exclusiveEntryTypes.count(qtype.getCode()) != 0
- || exclusiveEntryTypes.count(rr.qtype.getCode()) != 0)) {
+ && (exclusiveEntryTypes.count(qtype.getCode()) != 0
+ || exclusiveEntryTypes.count(rr.qtype.getCode()) != 0)) {
// leave database handle in a consistent state
while (di.backend->get(rr))
;
- throw ApiException("RRset "+qname.toString()+" IN "+qtype.toString()+": Conflicts with pre-existing RRset");
+ throw ApiException("RRset " + qname.toString() + " IN " + qtype.toString() + ": Conflicts with pre-existing RRset");
}
}
if (dname_seen && ns_seen && qname != zonename) {
- throw ApiException("RRset "+qname.toString()+" IN "+qtype.toString()+": Cannot have both NS and DNAME except in zone apex");
+ throw ApiException("RRset " + qname.toString() + " IN " + qtype.toString() + ": Cannot have both NS and DNAME except in zone apex");
}
if (!new_records.empty() && di.kind == DomainInfo::Consumer) {
// Allow deleting all RRsets, just not modifying them.
fillSOAData(rr.content, sd);
resp->headers["X-PDNS-New-Serial"] = std::to_string(sd.serial);
}
-
- } catch(...) {
+ }
+ catch (...) {
di.backend->abortTransaction();
throw;
}
return;
}
-static void apiServerSearchData(HttpRequest* req, HttpResponse* resp) {
+static void apiServerSearchData(HttpRequest* req, HttpResponse* resp)
+{
string q = req->getvars["q"];
string sMax = req->getvars["max"];
string sObjectType = req->getvars["object_type"];
else
throw ApiException("object_type must be one of the following options: all, zone, record, comment");
- SimpleMatch sm(q,true);
+ SimpleMatch sm(q, true);
UeberBackend B;
vector<DomainInfo> domains;
vector<DNSResourceRecord> result_rr;
vector<Comment> result_c;
- map<int,DomainInfo> zoneIdZone;
- map<int,DomainInfo>::iterator val;
+ map<int, DomainInfo> zoneIdZone;
+ map<int, DomainInfo>::iterator val;
Json::array doc;
B.getAllDomains(&domains, false, true);
- for(const DomainInfo& di: domains)
- {
+ for (const DomainInfo& di : domains) {
if ((objectType == ObjectType::ALL || objectType == ObjectType::ZONE) && ents < maxEnts && sm.match(di.zone)) {
- doc.push_back(Json::object {
- { "object_type", "zone" },
- { "zone_id", apiZoneNameToId(di.zone) },
- { "name", di.zone.toString() }
- });
+ doc.push_back(Json::object{
+ {"object_type", "zone"},
+ {"zone_id", apiZoneNameToId(di.zone)},
+ {"name", di.zone.toString()}});
ents++;
}
zoneIdZone[di.id] = di; // populate cache
}
- if ((objectType == ObjectType::ALL || objectType == ObjectType::RECORD) && B.searchRecords(q, maxEnts, result_rr))
- {
- for(const DNSResourceRecord& rr: result_rr)
- {
+ if ((objectType == ObjectType::ALL || objectType == ObjectType::RECORD) && B.searchRecords(q, maxEnts, result_rr)) {
+ for (const DNSResourceRecord& rr : result_rr) {
if (!rr.qtype.getCode())
continue; // skip empty non-terminals
- auto object = Json::object {
- { "object_type", "record" },
- { "name", rr.qname.toString() },
- { "type", rr.qtype.toString() },
- { "ttl", (double)rr.ttl },
- { "disabled", rr.disabled },
- { "content", makeApiRecordContent(rr.qtype, rr.content) }
- };
+ auto object = Json::object{
+ {"object_type", "record"},
+ {"name", rr.qname.toString()},
+ {"type", rr.qtype.toString()},
+ {"ttl", (double)rr.ttl},
+ {"disabled", rr.disabled},
+ {"content", makeApiRecordContent(rr.qtype, rr.content)}};
if ((val = zoneIdZone.find(rr.domain_id)) != zoneIdZone.end()) {
object["zone_id"] = apiZoneNameToId(val->second.zone);
object["zone"] = val->second.zone.toString();
}
}
- if ((objectType == ObjectType::ALL || objectType == ObjectType::COMMENT) && B.searchComments(q, maxEnts, result_c))
- {
- for(const Comment &c: result_c)
- {
- auto object = Json::object {
- { "object_type", "comment" },
- { "name", c.qname.toString() },
- { "type", c.qtype.toString() },
- { "content", c.content }
- };
+ if ((objectType == ObjectType::ALL || objectType == ObjectType::COMMENT) && B.searchComments(q, maxEnts, result_c)) {
+ for (const Comment& c : result_c) {
+ auto object = Json::object{
+ {"object_type", "comment"},
+ {"name", c.qname.toString()},
+ {"type", c.qtype.toString()},
+ {"content", c.content}};
if ((val = zoneIdZone.find(c.domain_id)) != zoneIdZone.end()) {
object["zone_id"] = apiZoneNameToId(val->second.zone);
object["zone"] = val->second.zone.toString();
resp->setJsonBody(doc);
}
-static void apiServerCacheFlush(HttpRequest* req, HttpResponse* resp) {
+static void apiServerCacheFlush(HttpRequest* req, HttpResponse* resp)
+{
DNSName canon = apiNameToDNSName(req->getvars["domain"]);
if (g_zoneCache.isEnabled()) {
DNSSECKeeper::clearCaches(canon);
// purge entire zone from cache, not just zone-level records.
uint64_t count = purgeAuthCaches(canon.toString() + "$");
- resp->setJsonBody(Json::object {
- { "count", (int) count },
- { "result", "Flushed cache." }
- });
+ resp->setJsonBody(Json::object{
+ {"count", (int)count},
+ {"result", "Flushed cache."}});
}
static std::ostream& operator<<(std::ostream& os, StatType statType)
{
- switch (statType)
- {
- case StatType::counter: return os << "counter";
- case StatType::gauge: return os << "gauge";
+ switch (statType) {
+ case StatType::counter:
+ return os << "counter";
+ case StatType::gauge:
+ return os << "gauge";
};
return os << static_cast<uint16_t>(statType);
}
-static void prometheusMetrics(HttpRequest* /* req */, HttpResponse* resp) {
+static void prometheusMetrics(HttpRequest* /* req */, HttpResponse* resp)
+{
std::ostringstream output;
- for (const auto &metricName : S.getEntries()) {
+ for (const auto& metricName : S.getEntries()) {
// Prometheus suggest using '_' instead of '-'
std::string prometheusMetricName = "pdns_auth_" + boost::replace_all_copy(metricName, "-", "_");
output << prometheusMetricName << " " << S.read(metricName) << "\n";
}
- output << "# HELP pdns_auth_info " << "Info from PowerDNS, value is always 1" << "\n";
- output << "# TYPE pdns_auth_info " << "gauge" << "\n";
- output << "pdns_auth_info{version=\"" << VERSION << "\"} " << "1" << "\n";
+ output << "# HELP pdns_auth_info "
+ << "Info from PowerDNS, value is always 1"
+ << "\n";
+ output << "# TYPE pdns_auth_info "
+ << "gauge"
+ << "\n";
+ output << "pdns_auth_info{version=\"" << VERSION << "\"} "
+ << "1"
+ << "\n";
resp->body = output.str();
resp->headers["Content-Type"] = "text/plain";
resp->headers["Content-Type"] = "text/css";
ostringstream ret;
- ret<<"* { box-sizing: border-box; margin: 0; padding: 0; }"<<endl;
- ret<<"body { color: black; background: white; margin-top: 1em; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 10pt; position: relative; }"<<endl;
- ret<<"a { color: #0959c2; }"<<endl;
- ret<<"a:hover { color: #3B8EC8; }"<<endl;
- ret<<".row { width: 940px; max-width: 100%; min-width: 768px; margin: 0 auto; }"<<endl;
- ret<<".row:before, .row:after { display: table; content:\" \"; }"<<endl;
- ret<<".row:after { clear: both; }"<<endl;
- ret<<".columns { position: relative; min-height: 1px; float: left; }"<<endl;
- ret<<".all { width: 100%; }"<<endl;
- ret<<".headl { width: 60%; }"<<endl;
- ret<<".header { width: 39.5%; float: right; background-repeat: no-repeat; margin-top: 7px; ";
- ret<<"background-image: url(data:image/png;base64,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);";
- ret<<" width: 154px; height: 20px; }"<<endl;
- ret<<"a#appname { margin: 0; font-size: 27px; color: #666; text-decoration: none; font-weight: bold; display: block; }"<<endl;
- ret<<"footer { border-top: 1px solid #ddd; padding-top: 4px; font-size: 12px; }"<<endl;
- ret<<"footer.row { margin-top: 1em; margin-bottom: 1em; }"<<endl;
- ret<<".panel { background: #f2f2f2; border: 1px solid #e6e6e6; margin: 0 0 22px 0; padding: 20px; }"<<endl;
- ret<<"table.data { width: 100%; border-spacing: 0; border-top: 1px solid #333; }"<<endl;
- ret<<"table.data td { border-bottom: 1px solid #333; padding: 2px; }"<<endl;
- ret<<"table.data tr:nth-child(2n) { background: #e2e2e2; }"<<endl;
- ret<<"table.data tr:hover { background: white; }"<<endl;
- ret<<".ringmeta { margin-bottom: 5px; }"<<endl;
- ret<<".resetring {float: right; }"<<endl;
- ret<<".resetring i { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAA/klEQVQY01XPP04UUBgE8N/33vd2XZUWEuzYuMZEG4KFCQn2NhA4AIewAOMBPIG2xhNYeAcKGqkNCdmYlVBZGBIT4FHsbuE0U8xk/kAbqm9TOfI/nicfhmwgDNhvylUT58kxCp4l31L8SfH9IetJ2ev6PwyIwyZWsdb11/gbTK55Co+r8rmJaRPTFJcpZil+pTit7C5awMpA+Zpi1sRFE9MqflYOloYCjY2uP8EdYiGU4CVGUBubxKfOOLjrtOBmzvEilbVb/aQWvhRl0unBZVXe4XdnK+bprwqnhoyTsyZ+JG8Wk0apfExxlcp7PFruXH8gdxamWB4cyW2sIO4BG3czIp78jUIAAAAASUVORK5CYII=); width: 10px; height: 10px; margin-right: 2px; display: inline-block; background-repeat: no-repeat; }"<<endl;
- ret<<".resetring:hover i { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAA2ElEQVQY013PMUoDcRDF4c+kEzxCsNNCrBQvIGhnlcYm11EkBxAraw8gglgIoiJpAoKIYlBcgrgopsma3c3fwt1k9cHA480M8xvQp/nMjorOWY5ov7IAYlpjQk7aYxcuWBpwFQgJnUcaYk7GhEDIGL5w+MVpKLIRyR2b4JOjvGhUKzHTv2W7iuSN479Dvu9plf1awbQ6y3x1sU5tjpVJcMbakF6Ycoas8Dl5xEHJ160wRdfqzXfa6XQ4PLDlicWUjxHxZfndL/N+RhiwNzl/Q6PDhn/qsl76H7prcApk2B1aAAAAAElFTkSuQmCC);}"<<endl;
- ret<<".resizering {float: right;}"<<endl;
+ ret << "* { box-sizing: border-box; margin: 0; padding: 0; }" << endl;
+ ret << "body { color: black; background: white; margin-top: 1em; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 10pt; position: relative; }" << endl;
+ ret << "a { color: #0959c2; }" << endl;
+ ret << "a:hover { color: #3B8EC8; }" << endl;
+ ret << ".row { width: 940px; max-width: 100%; min-width: 768px; margin: 0 auto; }" << endl;
+ ret << ".row:before, .row:after { display: table; content:\" \"; }" << endl;
+ ret << ".row:after { clear: both; }" << endl;
+ ret << ".columns { position: relative; min-height: 1px; float: left; }" << endl;
+ ret << ".all { width: 100%; }" << endl;
+ ret << ".headl { width: 60%; }" << endl;
+ ret << ".header { width: 39.5%; float: right; background-repeat: no-repeat; margin-top: 7px; ";
+ ret << "background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJoAAAAUCAYAAAB1RSS/AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAACtgAAArYBAHIqtQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAABBTSURBVGiBtVp7cFRVmv9u3763b7/f9It00iFACBohgCEyQYgKI49CLV3cWaoEZBcfo2shu7KOtZbjrqOuVQtVWFuOrPqPRU3NgOIDlkgyJEYJwUAqjzEJedFJupN0p9/v+9o/mtve7r790HF+VbeSPue7555zz+98z4ucOXNmgWVZBH4AK5PJGIPBQBqNxpTNZkthGMZCCUxMTBCDg4PyiYkJWTQaRc1mc7Kuri7a1NQU4ssxDAOffPKJAQCynvnII494ESTddO3aNaXT6SS4TplMRj/44IM+7ndXV5dqfn5ewh9306ZNQZqmobu7W11qri0tLX6tVkv19vYqpqampPw+BEFYtVpNGQwG0mKxpJYsWUIKjTE6OiodGBhQ8NcgkUgYjUZDORyOhM1mSxV6fjAYFF+6dEnLb9NoNOR9990X4H53dHSovV4vzpfZvn27T6FQ0Py2sbExorOzU+N2uwmWZUGv15N33nlnuLGxMZy7byyVQEJ//nd9Yuz/lJR/HBdrHSlJ9baIuuV1L4LJ8/Y49pc/KcJX39WRC4MEgskY3Lourmn5rQdbckfe2ijfOBZo+40xNXtNysR9KLZkdVK+9oBf0fBkCABA3NraamTZwjxSKpXUAw884G1paQkUIty5c+f0Fy5cWMIfx+l0Snt6ejTt7e26AwcOuKxWawoAQCQSQW9vr3pxcTHrJTY3Nwe5Tb18+bJ2bGxMzvWhKMpu27bNj6IoCwDQ1tamd7lcRM79genpaaK1tdVQcDG3sXbt2rBWq6X6+/sV3d3d2mKyy5cvj+7cudO7atWqGL99bGxMWuxZOp0utX37du+9994b5A4Qh2AwiObei6Ioe/fdd4eVSiUNAHD16lX1+Pi4nC+zadOmIJ9oZ8+eNeTu3/T0tLSvr0/V3d0dPXr0qJNrZ+KL6MKpjZWUbyxzQMmFIYJcGCISw5+qjE9+M4UqLJmx/RdeWBK+elKfGTjuR+OhWSxx86JS/9D/zsrufDzMdSXGv5J5/vBYBZuKiLi25HS3LDndLUuMX1IYHjvtynQUQjgcFp89e9b8zjvv2BmGyepjWRbeffdd2/nz55cUIqvT6ZSeOHHC7vf7xVyb3W6P58rNzc1liOfxeLJISNM04na7Me63z+fD+P1SqZQupHn+Wty8eVN+4sSJyv7+fnlp6R/g8/nw06dPW0+ePLmUJEmklDxN08iVK1dU5Y7f0dGhvnjxYkElQVFU1jP9Xz5j4pMsSzYwifvPPWnhfsdHPpdnkYwHlk4ivi9/baFDM2IAACYZEi1++qSVTzI+YkN/VEe++726JNE4TE1Nyc6cOWPkt3322Wf6/v7+ki8nEAhgH3zwQWYhDoejINGSyaQoFAphuf2zs7MSAIBIJIImEgmU32ez2RLlruOngGVZ+Oijj6w+n09cWjobg4ODyg8//NBSWhLgu+++K4toJEkin376qancObBkFIl/f7bo2ImxC0om5kUBACK9pzTFZJlEAI0O/kEJABAf+UJOh115+8VH5MZHGkGimc3mRK66BwBoa2szBAIBMUB6w1tbW415QgUwOjqqGB4elgIA1NTU5BGN02IulwsXOqUul0sCADA/P5+3qIqKip+NaARBMBiGMbnt0Wg0z68qF729vepr164pS8k5nU7ZwsJC0U0DAOjp6VHGYjE0t10kEgmqt5TrOwIYqqRWTbmuSQAASM9fiFKy5Fx/Wnaur7Ss53tC8IQ+/fTTM/F4HH3rrbcc/E1nWRYmJyeJtWvXRr7++mt1rnoGANi6devipk2bgsePH7dHIpGs8Ts7O7W1tbXxqqqqJIZhLN+keDweDADA7XbjuWPebpcAACwsLOT1V1VVFSSayWRKvvLKK5P8tmLBTVNTk//hhx/2vv/++5aBgYEsLeB0OqWF7gMAsFqtiYqKivj169c1ueaytbVVv2HDhnChewHS7/fKlSuqPXv2LBaTyw1gAABqa2sjhw4dck1PT0vOnz9v4O+NWFNdlluBqispAABUYSEp/6TgPmRkVba0rGppybFRpZksaDodDkeioqIiT/M4nU4JAMDIyEiez1JTUxN9/PHHFyoqKpJbtmzx5faPj4/LANKOr9VqzRqbi7D4vhof8/PzOMAPhMyZa948OSAIAjiOs/xLSFvzIZFImO3bt+fNn9OqhaDRaMiDBw/Obd26NY8oTqdTWmhtfPT29paMmkOhUJ6CkEgkjFKppOvq6mIvvviis76+PkNqVF1BiQ21yWJjoiobiRlWpQAACMeWaKk5EMu2RQEAiOr7YyBCi2YliMrN0aI+Wjwez+vn/KOZmZk8lbl69eoI97+QeQwEAhgXFFRVVWX1+/1+nGVZyE1bcPB6vRKWZSE35JdKpbTJZCp4qiiKQmZmZnDuEiKqEITWTtN0SfMDALBjx45FiUSSZ35HRkaKakQAgPn5ecnU1FRRQuv1+rz0Qn9/v+ry5ctqgPTh2rFjR9ZB0e78Hzcgedb2NhDQ7vq9C24fQNXm3/gww8qCxJTX/4OfcGyJAwBgS+pSqo3/XFADo0oLqdn2lkeQaAzDIB0dHWqPx5O3YK1WSzIMA7lmEQDAaDSSQv/zEQwGUQCA6urqLKJRFIV4PB6MH3GqVCqS3z83N4cvLi5mEaVUIOD1evHXX399GXedOnXKWkweIJ3r++abb/IcYqPRWDA3xodUKmWEyMCZ/1IolQvMfXcAabN7+vRp68cff2wS8nElVVvihl99cQtV27PmhapspOHvzzmJ5Tsy6RtELGGX7G+7JV2xIysHiqAYq/rFv3h0e96f57drHnjTo2n57TwiJrIOl6SyOWo6cPmWiNAwgj7am2++6Ugmk4IkrK2tjUWjUVRoMXK5PJOHkclkdJ4AAESjURQAYPny5YKRJ59odXV1EX6ea2ZmRpKbf/s5AwEAgO+//17+8ssv1/j9/jzNt3HjxmC542g0GjI318etXQgoirKcxrx+/brKYDAUJPW6desiFy5ciM/MzORpyM7OTl04HEYPHz7synURiJpfxizPj4+T8/0S0jOEiw2rUrh5TRJE+TRAFWba+KvPZung9Hxy9iohwpUMvnRjQkSo8zQ1ICJQbX7Zp2h8LpCa7ZEwUY8Yt21IiHXLMopCkEyFSFZZWRmz2+0FVSqXUL39v6AM5yTr9XpKrVZnab2RkRFZKpXKPHvlypUxvuM+PT0tCQaDWW+lWCDwUzA3N0cIkay2tjbS0tLiL3ccoYNWzPRWVVXFcBxnAACCwSAmRCIOCILA/v373QqFghLqv3Hjhrq9vb1gioIFBNLFoLI8gbKBILdHRNi8ocvOC6nVavLw4cOzAAAKhYJGEARytRo/5A6Hw4JMk8lkmRNht9vjAwMDmU0dGhril3TAbDanDAZD0u12EwAAw8PDCoZhspZQLBD4KRBa17Zt27wPPfSQVyQqO+0IQumHQloeIB0Jr169Onzjxg01QOHDzqGioiJ55MiRW8ePH68UCg6+/PJLY0tLS4Cv1RJjF2W+z5+2UEFnxiqgKhup2/muW7pyV1YAQEfmUN9n/2SOj57PRN4IirHKphe86q2vLSIozktHMBDq+p0u3PkfRpZKZOYtqWyOavd86BZrlxWOOjMTQVH2jjvuCL/wwgtOvV5PAaQ3QyqV5r20SCSSebmhUEiQaCqVKnNfLkk4QnEwmUyk2WzOaNDp6emsU14qEABIO87Hjh2b5K79+/e7i8kLVS0UCgXF19blINfEAwCoVCpBDcShsbExVKw/FzabLXXs2LFJIT81Go2K+YFPYqpDuvDx7ko+yQAA6NAs5jn9sD1+84KMa2OpJLLw0X2VfJIBALA0iYS6/svoO/ePWcni4KWXjKH2V0x8kgEAJG99Lfd8uLmSSfiFj+j999/v3bt3r/vgwYMzb7zxxthzzz03w9UqOVit1rzFjY6OZiY7NDSUl/4gCIIxmUyZcZYtW1ZQG0mlUloul9Nmszkjn1sCK6cigGEY63A4EtxlsViKOvQOhyOm0WiyyNve3q4vN+IESKeAhKJnISeej/r6+ijfzy2Evr4+Oad19Xo9dejQoVkhbev1ejNE83/xjAXYfPcqDRZ8nz9lhdtjhjr/U0d6RwoGLtH+j7WJyctSAADSM4SHu/9bsFwFAECHXVjwq381ChKtubk50NLSEmhsbAxrNBrBU7hixYq8XMvg4KByamqKmJubw7799ts8H6GqqirGV+XV1dWJQppCq9WSAABWq7WgT/hzBwIAaW3d0NCQpVkCgQDW1dVVVnnI5XLhp06dsuW24zjO1NTUFJ0viqJsfX19Sa3W09Ojfu+996xcCkapVNIoiuaxyGAwkAAAdHBaXIw4AGnNRnqHcQCAxOTlknXdxHirHAAgOXFJBkzxQ5ic6pD/6Nodh9uRT1YxPRaLoW+//XaVWCxmhXyMe+65J8D/jeM4a7FYEkKOL5ceWLp0aUGiVVZWliSax+PBX3rppRp+27PPPjtdLKhpamoKtre3Z53Sr776yrB58+a8LzH4GB4eVr722muCpaaGhoYgQRCFVEoGGzduDF65cqVkqevGjRvqgYEBld1uj8/NzUlIMtsNwnGc4VJMlH+yrNwhFbglxoyrUnTEXVKeDs2K039nSstG5rDyvdscLF26NNnQ0JAX7tM0jQiRzGQyJdevXx/Jba+srBQ0J3q9ngRIBwRisVhQ65UTCNA0jQQCAYx/CZXO+LDb7UmLxZJFYo/Hg1+9erVovTLXtHMgCILevXt30bISh5UrV8ZzTXchUBSFTExMyIQCj7q6ugh3KHDbugSIhN8hHxLb+iQAAGasK+2SmOvTsuY1pWWNqxI/mWgAAI8++uiCTqcrmcTEMIzZt2+fW8hMFvJbuNMoEokEM+FSqZQ2m81/k0+DAADWr1+fZ8IuXrxY8lu3XKAoyu7bt8/NmbFSEDLdPxYSiYTZu3dvJqmKYHJWturhomNKa34ZFskMNACAYt2hQDFZEaGh5XfsDQMAECt2R1Glreja5GsOBP4qoul0Ouro0aO3TCZTQTOkUqnII0eO3FqxYoUgoYRKVQAA/ISl0Ph/60+Dmpqa8syky+Ui+vr6yv4uTavVks8///ytUsV0oWf/GHk+pFIp/cQTT8zqdLos31q36+S8WFcjuE9iTVVK99CpTDQuXbk7qmz8taAGRlAJq9t50o2qllIAACKJitHu+cCF4ApBdS5d/XdB+fqnguLq6upobm4Kx/GyQ3m9Xk+9+uqrk21tbZquri6t1+vFWZYFi8WSdDgcsV27di1qtdqCYb3ZbCZra2sjueaW/yl0XV1dNBwOZ/mT/KIxB6VSSTkcjlhuey44X8lkMqVy5TmC6/V6qrGx0Z8bPY6OjsrWrFkT1el0ec9CUZRVqVSUWq2mqqur4xs2bAgL+XQSiYTJvZcf9Njt9uRdd90Vys2PcQnd5ubmAMMwcPPmTXk0GhUDpCsRVVVVsccee2yBS0PxIZLqacszfZPBP7+qj4+1Kilf+lNuYtkDEU3La3mfcmsfPL4gqfxFrJxPuYll22Kmp/omgpf+zZia7ZEyCT+KGVcn5WsP+uUNh0IAAP8PaQRnE4MgdzkAAAAASUVORK5CYII=);";
+ ret << " width: 154px; height: 20px; }" << endl;
+ ret << "a#appname { margin: 0; font-size: 27px; color: #666; text-decoration: none; font-weight: bold; display: block; }" << endl;
+ ret << "footer { border-top: 1px solid #ddd; padding-top: 4px; font-size: 12px; }" << endl;
+ ret << "footer.row { margin-top: 1em; margin-bottom: 1em; }" << endl;
+ ret << ".panel { background: #f2f2f2; border: 1px solid #e6e6e6; margin: 0 0 22px 0; padding: 20px; }" << endl;
+ ret << "table.data { width: 100%; border-spacing: 0; border-top: 1px solid #333; }" << endl;
+ ret << "table.data td { border-bottom: 1px solid #333; padding: 2px; }" << endl;
+ ret << "table.data tr:nth-child(2n) { background: #e2e2e2; }" << endl;
+ ret << "table.data tr:hover { background: white; }" << endl;
+ ret << ".ringmeta { margin-bottom: 5px; }" << endl;
+ ret << ".resetring {float: right; }" << endl;
+ ret << ".resetring i { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAA/klEQVQY01XPP04UUBgE8N/33vd2XZUWEuzYuMZEG4KFCQn2NhA4AIewAOMBPIG2xhNYeAcKGqkNCdmYlVBZGBIT4FHsbuE0U8xk/kAbqm9TOfI/nicfhmwgDNhvylUT58kxCp4l31L8SfH9IetJ2ev6PwyIwyZWsdb11/gbTK55Co+r8rmJaRPTFJcpZil+pTit7C5awMpA+Zpi1sRFE9MqflYOloYCjY2uP8EdYiGU4CVGUBubxKfOOLjrtOBmzvEilbVb/aQWvhRl0unBZVXe4XdnK+bprwqnhoyTsyZ+JG8Wk0apfExxlcp7PFruXH8gdxamWB4cyW2sIO4BG3czIp78jUIAAAAASUVORK5CYII=); width: 10px; height: 10px; margin-right: 2px; display: inline-block; background-repeat: no-repeat; }" << endl;
+ ret << ".resetring:hover i { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAA2ElEQVQY013PMUoDcRDF4c+kEzxCsNNCrBQvIGhnlcYm11EkBxAraw8gglgIoiJpAoKIYlBcgrgopsma3c3fwt1k9cHA480M8xvQp/nMjorOWY5ov7IAYlpjQk7aYxcuWBpwFQgJnUcaYk7GhEDIGL5w+MVpKLIRyR2b4JOjvGhUKzHTv2W7iuSN479Dvu9plf1awbQ6y3x1sU5tjpVJcMbakF6Ycoas8Dl5xEHJ160wRdfqzXfa6XQ4PLDlicWUjxHxZfndL/N+RhiwNzl/Q6PDhn/qsl76H7prcApk2B1aAAAAAElFTkSuQmCC);}" << endl;
+ ret << ".resizering {float: right;}" << endl;
resp->body = ret.str();
resp->status = 200;
}
{
try {
setThreadName("pdns/webserver");
- if(::arg().mustDo("api")) {
+ if (::arg().mustDo("api")) {
d_ws->registerApiHandler("/api/v1/servers/localhost/cache/flush", apiServerCacheFlush, "PUT");
d_ws->registerApiHandler("/api/v1/servers/localhost/config", apiServerConfig, "GET");
d_ws->registerApiHandler("/api/v1/servers/localhost/search-data", apiServerSearchData, "GET");
d_ws->registerApiHandler("/api", apiDiscovery, "GET");
}
if (::arg().mustDo("webserver")) {
- d_ws->registerWebHandler("/style.css", [this](HttpRequest *req, HttpResponse *resp){cssfunction(req, resp);}, "GET");
- d_ws->registerWebHandler("/", [this](HttpRequest *req, HttpResponse *resp){indexfunction(req, resp);}, "GET");
+ d_ws->registerWebHandler(
+ "/style.css", [this](HttpRequest* req, HttpResponse* resp) { cssfunction(req, resp); }, "GET");
+ d_ws->registerWebHandler(
+ "/", [this](HttpRequest* req, HttpResponse* resp) { indexfunction(req, resp); }, "GET");
d_ws->registerWebHandler("/metrics", prometheusMetrics, "GET");
}
d_ws->go();
}
- catch(...) {
- g_log<<Logger::Error<<"AuthWebServer thread caught an exception, dying"<<endl;
+ catch (...) {
+ g_log << Logger::Error << "AuthWebServer thread caught an exception, dying" << endl;
_exit(1);
}
}