--- /dev/null
+ALTER TABLE domains ADD options VARCHAR(64000) DEFAULT NULL AFTER notified_serial;
declare(suffix, "remove-empty-non-terminals-from-zone-query", "remove all empty non-terminals from zone", "delete from records where domain_id=? and type is null");
declare(suffix, "delete-empty-non-terminal-query", "delete empty non-terminal from zone", "delete from records where domain_id=? and name=? and type is null");
- declare(suffix, "info-zone-query", "", "select id,name,master,last_check,notified_serial,type,account from domains where name=?");
+ declare(suffix, "info-zone-query", "", "select id,name,master,last_check,notified_serial,type,options,account from domains where name=?");
declare(suffix, "info-all-slaves-query", "", "select id,name,master,last_check from domains where type='SLAVE'");
declare(suffix, "supermaster-query", "", "select account from supermasters where ip=? and nameserver=?");
declare(suffix, "update-master-query", "", "update domains set master=? where name=?");
declare(suffix, "update-kind-query", "", "update domains set type=? where name=?");
+ declare(suffix, "update-options-query", "", "update domains set options=? where name=?");
declare(suffix, "update-account-query", "", "update domains set account=? where name=?");
declare(suffix, "update-serial-query", "", "update domains set notified_serial=? where id=?");
declare(suffix, "update-lastcheck-query", "", "update domains set last_check=? where id=?");
last_check INT DEFAULT NULL,
type VARCHAR(6) NOT NULL,
notified_serial INT UNSIGNED DEFAULT NULL,
+ options VARCHAR(64000) DEFAULT NULL,
account VARCHAR(40) CHARACTER SET 'utf8' DEFAULT NULL,
PRIMARY KEY (id)
) Engine=InnoDB CHARACTER SET 'latin1';
--- /dev/null
+ALTER TABLE domains ADD COLUMN options VARCHAR(MAX) DEFAULT NULL;
declare(suffix, "remove-empty-non-terminals-from-zone-query", "remove all empty non-terminals from zone", "delete from records where domain_id=? and type is null");
declare(suffix, "delete-empty-non-terminal-query", "delete empty non-terminal from zone", "delete from records where domain_id=? and name=? and type is null");
- declare(suffix, "info-zone-query", "", "select id,name,master,last_check,notified_serial,type,account from domains where name=?");
+ declare(suffix, "info-zone-query", "", "select id,name,master,last_check,notified_serial,type,options,account from domains where name=?");
declare(suffix, "info-all-slaves-query", "", "select id,name,master,last_check from domains where type='SLAVE'");
declare(suffix, "supermaster-query", "", "select account from supermasters where ip=? and nameserver=?");
declare(suffix, "update-master-query", "", "update domains set master=? where name=?");
declare(suffix, "update-kind-query", "", "update domains set type=? where name=?");
+ declare(suffix, "update-options-query", "", "update domains set options=? where name=?");
declare(suffix, "update-account-query", "", "update domains set account=? where name=?");
declare(suffix, "update-serial-query", "", "update domains set notified_serial=? where id=?");
declare(suffix, "update-lastcheck-query", "", "update domains set last_check=? where id=?");
last_check INT DEFAULT NULL,
type VARCHAR(6) NOT NULL,
notified_serial INT DEFAULT NULL,
+ options VARCHAR(MAX) DEFAULT NULL,
account VARCHAR(40) DEFAULT NULL,
PRIMARY KEY (id)
);
--- /dev/null
+BEGIN;
+ ALTER TABLE domains ADD COLUMN options VARCHAR(65535) DEFAULT NULL;
+
+ ALTER TABLE domains ADD COLUMN account_new VARCHAR(40) DEFAULT NULL;
+ UPDATE domains SET account_new = account;
+ ALTER TABLE domains DROP COLUMN account;
+ ALTER TABLE domains RENAME COLUMN account_new TO account;
+COMMIT;
declare(suffix, "remove-empty-non-terminals-from-zone-query", "remove all empty non-terminals from zone", "delete from records where domain_id=$1 and type is null");
declare(suffix, "delete-empty-non-terminal-query", "delete empty non-terminal from zone", "delete from records where domain_id=$1 and name=$2 and type is null");
- declare(suffix, "info-zone-query", "", "select id,name,master,last_check,notified_serial,type,account from domains where name=$1");
+ declare(suffix, "info-zone-query", "", "select id,name,master,last_check,notified_serial,type,options,account from domains where name=$1");
declare(suffix, "info-all-slaves-query", "", "select id,name,master,last_check from domains where type='SLAVE'");
declare(suffix, "supermaster-query", "", "select account from supermasters where ip=$1 and nameserver=$2");
declare(suffix, "update-master-query", "", "update domains set master=$1 where name=$2");
declare(suffix, "update-kind-query", "", "update domains set type=$1 where name=$2");
+ declare(suffix, "update-options-query", "", "update domains set options=$1 where name=$2");
declare(suffix, "update-account-query", "", "update domains set account=$1 where name=$2");
declare(suffix, "update-serial-query", "", "update domains set notified_serial=$1 where id=$2");
declare(suffix, "update-lastcheck-query", "", "update domains set last_check=$1 where id=$2");
last_check INT DEFAULT NULL,
type VARCHAR(6) NOT NULL,
notified_serial BIGINT DEFAULT NULL,
+ options VARCHAR(65535) DEFAULT NULL;
account VARCHAR(40) DEFAULT NULL,
CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT)))
);
--- /dev/null
+PRAGMA foreign_keys = 0;
+
+BEGIN TRANSACTION;
+ CREATE TABLE domains_temp (
+ id INTEGER PRIMARY KEY,
+ name VARCHAR(255) NOT NULL COLLATE NOCASE,
+ master VARCHAR(128) DEFAULT NULL,
+ last_check INTEGER DEFAULT NULL,
+ type VARCHAR(6) NOT NULL,
+ notified_serial INTEGER DEFAULT NULL,
+ options VARCHAR(65535) DEFAULT NULL,
+ account VARCHAR(40) DEFAULT NULL
+ );
+
+ INSERT INTO domains_temp SELECT id,name,master,last_check,type,motified_serial,NULL,account FROM domains;
+ DROP TABLE domains;
+ ALTER TABLE domains_temp RENAME TO domains;
+
+ CREATE UNIQUE INDEX name_index ON domains(name);
+COMMIT;
+
+PRAGMA foreign_keys = 1;
+
+ANALYZE;
declare(suffix, "remove-empty-non-terminals-from-zone-query", "remove all empty non-terminals from zone", "delete from records where domain_id=:domain_id and type is null");
declare(suffix, "delete-empty-non-terminal-query", "delete empty non-terminal from zone", "delete from records where domain_id=:domain_id and name=:qname and type is null");
- declare(suffix, "info-zone-query", "", "select id,name,master,last_check,notified_serial,type,account from domains where name=:domain");
+ declare(suffix, "info-zone-query", "", "select id,name,master,last_check,notified_serial,type,options,account from domains where name=:domain");
declare(suffix, "info-all-slaves-query", "", "select id,name,master,last_check from domains where type='SLAVE'");
declare(suffix, "supermaster-query", "", "select account from supermasters where ip=:ip and nameserver=:nameserver");
declare(suffix, "update-master-query", "", "update domains set master=:master where name=:domain");
declare(suffix, "update-kind-query", "", "update domains set type=:kind where name=:domain");
+ declare(suffix, "update-options-query", "", "update domains set options=:options where name=:domain");
declare(suffix, "update-account-query", "", "update domains set account=:account where name=:domain");
declare(suffix, "update-serial-query", "", "update domains set notified_serial=:serial where id=:domain_id");
declare(suffix, "update-lastcheck-query", "", "update domains set last_check=:last_check where id=:domain_id");
master VARCHAR(128) DEFAULT NULL,
last_check INTEGER DEFAULT NULL,
type VARCHAR(6) NOT NULL,
+ options VARCHAR(65535) DEFAULT NULL,
notified_serial INTEGER DEFAULT NULL,
account VARCHAR(40) DEFAULT NULL
);
// List the class version here. Default is 0
BOOST_CLASS_VERSION(LMDBBackend::KeyDataDB, 1)
+BOOST_CLASS_VERSION(DomainInfo, 1)
static bool s_first = true;
static int s_shards = 0;
}
template <class Archive>
- void serialize(Archive& ar, DomainInfo& g, const unsigned int version)
+ void save(Archive& ar, const DomainInfo& g, const unsigned int version)
{
ar& g.zone;
ar& g.last_check;
ar& g.id;
ar& g.notified_serial;
ar& g.kind;
+ ar& g.options;
+ }
+
+ template <class Archive>
+ void load(Archive& ar, DomainInfo& g, const unsigned int version)
+ {
+ ar& g.zone;
+ ar& g.last_check;
+ ar& g.account;
+ ar& g.masters;
+ ar& g.id;
+ ar& g.notified_serial;
+ ar& g.kind;
+ if (version >= 1) {
+ ar& g.options;
+ }
+ else {
+ g.options.clear();
+ }
}
template <class Archive>
BOOST_SERIALIZATION_SPLIT_FREE(DNSName);
BOOST_SERIALIZATION_SPLIT_FREE(QType);
BOOST_SERIALIZATION_SPLIT_FREE(LMDBBackend::KeyDataDB);
+BOOST_SERIALIZATION_SPLIT_FREE(DomainInfo);
BOOST_IS_BITWISE_SERIALIZABLE(ComboAddress);
template <>
});
}
+bool LMDBBackend::setOptions(const DNSName& domain, const std::string& options)
+{
+ return genChangeDomain(domain, [options](DomainInfo& di) {
+ di.options = options;
+ });
+}
+
bool LMDBBackend::setAccount(const DNSName& domain, const std::string& account)
{
return genChangeDomain(domain, [account](DomainInfo& di) {
void setStale(uint32_t domain_id) override;
void setFresh(uint32_t domain_id) override;
void setNotified(uint32_t id, uint32_t serial) override;
+ bool setOptions(const DNSName& domain, const std::string& options) override;
bool setAccount(const DNSName& domain, const std::string& account) override;
bool deleteDomain(const DNSName& domain) override;
d_UpdateKindOfZoneQuery=getArg("update-kind-query");
d_UpdateSerialOfZoneQuery=getArg("update-serial-query");
d_UpdateLastCheckOfZoneQuery=getArg("update-lastcheck-query");
+ d_UpdateOptionsOfZoneQuery = getArg("update-options-query");
d_UpdateAccountOfZoneQuery=getArg("update-account-query");
d_InfoOfAllMasterDomainsQuery=getArg("info-all-master-query");
d_DeleteDomainQuery=getArg("delete-domain-query");
d_UpdateKindOfZoneQuery_stmt = nullptr;
d_UpdateSerialOfZoneQuery_stmt = nullptr;
d_UpdateLastCheckOfZoneQuery_stmt = nullptr;
+ d_UpdateOptionsOfZoneQuery_stmt = nullptr;
d_UpdateAccountOfZoneQuery_stmt = nullptr;
d_InfoOfAllMasterDomainsQuery_stmt = nullptr;
d_DeleteDomainQuery_stmt = nullptr;
return true;
}
+bool GSQLBackend::setOptions(const DNSName& domain, const string& options)
+{
+ try {
+ reconnectIfNeeded();
+
+ // clang-format off
+ d_UpdateOptionsOfZoneQuery_stmt->
+ bind("options", options)->
+ bind("domain", domain)->
+ execute()->
+ reset();
+ // clang-format on
+ }
+ catch (SSqlException& e) {
+ throw PDNSException("GSQLBackend unable to set options of domain '" + domain.toLogString() + "' to '" + options + "': " + e.txtReason());
+ }
+ return true;
+}
+
bool GSQLBackend::setAccount(const DNSName &domain, const string &account)
{
try {
if(!numanswers)
return false;
- ASSERT_ROW_COLUMNS("info-zone-query", d_result[0], 7);
+ ASSERT_ROW_COLUMNS("info-zone-query", d_result[0], 8);
pdns::checked_stoi_into(di.id, d_result[0][0]);
try {
return false;
}
string type=d_result[0][5];
- di.account=d_result[0][6];
+ di.options = d_result[0][6];
+ di.account = d_result[0][7];
di.kind = DomainInfo::stringToKind(type);
vector<string> masters;
d_InsertEmptyNonTerminalOrderQuery_stmt = d_db->prepare(d_InsertEmptyNonTerminalOrderQuery, 4);
d_UpdateMasterOfZoneQuery_stmt = d_db->prepare(d_UpdateMasterOfZoneQuery, 2);
d_UpdateKindOfZoneQuery_stmt = d_db->prepare(d_UpdateKindOfZoneQuery, 2);
+ d_UpdateOptionsOfZoneQuery_stmt = d_db->prepare(d_UpdateOptionsOfZoneQuery, 2);
d_UpdateAccountOfZoneQuery_stmt = d_db->prepare(d_UpdateAccountOfZoneQuery, 2);
d_UpdateSerialOfZoneQuery_stmt = d_db->prepare(d_UpdateSerialOfZoneQuery, 2);
d_UpdateLastCheckOfZoneQuery_stmt = d_db->prepare(d_UpdateLastCheckOfZoneQuery, 2);
d_InsertEmptyNonTerminalOrderQuery_stmt.reset();
d_UpdateMasterOfZoneQuery_stmt.reset();
d_UpdateKindOfZoneQuery_stmt.reset();
+ d_UpdateOptionsOfZoneQuery_stmt.reset();
d_UpdateAccountOfZoneQuery_stmt.reset();
d_UpdateSerialOfZoneQuery_stmt.reset();
d_UpdateLastCheckOfZoneQuery_stmt.reset();
void setNotified(uint32_t domain_id, uint32_t serial) override;
bool setMasters(const DNSName &domain, const vector<ComboAddress> &masters) override;
bool setKind(const DNSName &domain, const DomainInfo::DomainKind kind) override;
+ bool setOptions(const DNSName& domain, const string& options) override;
bool setAccount(const DNSName &domain, const string &account) override;
bool getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) override;
string d_InsertEmptyNonTerminalOrderQuery;
string d_UpdateMasterOfZoneQuery;
string d_UpdateKindOfZoneQuery;
+ string d_UpdateOptionsOfZoneQuery;
string d_UpdateAccountOfZoneQuery;
string d_UpdateSerialOfZoneQuery;
string d_UpdateLastCheckOfZoneQuery;
unique_ptr<SSqlStatement> d_InsertEmptyNonTerminalOrderQuery_stmt;
unique_ptr<SSqlStatement> d_UpdateMasterOfZoneQuery_stmt;
unique_ptr<SSqlStatement> d_UpdateKindOfZoneQuery_stmt;
+ unique_ptr<SSqlStatement> d_UpdateOptionsOfZoneQuery_stmt;
unique_ptr<SSqlStatement> d_UpdateAccountOfZoneQuery_stmt;
unique_ptr<SSqlStatement> d_UpdateSerialOfZoneQuery_stmt;
unique_ptr<SSqlStatement> d_UpdateLastCheckOfZoneQuery_stmt;
DNSName zone;
time_t last_check;
+ string options;
string account;
vector<ComboAddress> masters;
DNSBackend *backend;
return false;
}
+ //! Called when the options of a domain should be changed
+ virtual bool setOptions(const DNSName& domain, const string& options)
+ {
+ return false;
+ }
+
//! Called when the Account of a domain should be changed
virtual bool setAccount(const DNSName &domain, const string &account)
{
#include <boost/program_options.hpp>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/list_of.hpp>
+#include "json11.hpp"
#include "tsigutils.hh"
#include "dnsbackend.hh"
#include "ueberbackend.hh"
return ret;
}
+static int setZoneOptions(const DNSName& zone, const string& options)
+{
+ UeberBackend B("default");
+ DomainInfo di;
+
+ if (!B.getDomainInfo(zone, di)) {
+ cerr << "No such zone " << zone << " in the database" << endl;
+ return EXIT_FAILURE;
+ }
+ if (!di.backend->setOptions(zone, options)) {
+ cerr << "Could not find backend willing to accept new zone configuration" << endl;
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
+
static int setZoneAccount(const DNSName& zone, const string &account)
{
UeberBackend B("default");
}
}
}
+ if (!di.options.empty()) {
+ cout << "Options:" << endl;
+ cout << di.options << endl;
+ }
return true;
}
cout << "secure-all-zones [increase-serial] Secure all zones without keys" << endl;
cout << "secure-zone ZONE [ZONE ..] Add DNSSEC to zone ZONE" << endl;
cout << "set-kind ZONE KIND Change the kind of ZONE to KIND (primary, secondary, native)" << endl;
+ cout << "set-options ZONE OPTIONS Change the options of ZONE to OPTIONS" << endl;
cout << "set-account ZONE ACCOUNT Change the account (owner) of ZONE to ACCOUNT" << endl;
cout << "set-nsec3 ZONE ['PARAMS' [narrow]] Enable NSEC3 with PARAMS. Optionally narrow" << endl;
cout << "set-presigned ZONE Use presigned RRSIGs from storage" << endl;
auto kind = DomainInfo::stringToKind(cmds.at(2));
return setZoneKind(zone, kind);
}
+ else if (cmds.at(0) == "set-options") {
+ if (cmds.size() != 3) {
+ cerr << "Syntax: pdnsutil set-options ZONE OPTIONS" << endl;
+ return 0;
+ }
+ // Verify json
+ std::string err;
+ json11::Json doc = json11::Json::parse(cmds.at(2), err);
+ if (doc.is_null()) {
+ cerr << "Parsing of JSON document failed:" << err << endl;
+ return EXIT_FAILURE;
+ }
+ DNSName zone(cmds.at(1));
+ return setZoneOptions(zone, cmds.at(2));
+ }
else if (cmds.at(0) == "set-account") {
if(cmds.size() != 3) {
cerr<<"Syntax: pdnsutil set-account ZONE ACCOUNT"<<endl;