// Copyright (c) 2011, Outercurve Foundation.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// - Neither the name of the Outercurve Foundation nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using MySql.Data.MySqlClient;
using WebsitePanel.Server.Utils;
using WebsitePanel.Providers.Utils;
using System.IO;
using System.Reflection;
namespace WebsitePanel.Providers.DNS
{
public class PowerDNS : HostingServiceProviderBase, IDnsServer
{
#region Constants
//pdns mysql db settings
const string PDNSDbServer = "PDNSDbServer";
const string PDNSDbPort = "PDNSDbPort";
const string PDNSDbName = "PDNSDbName";
const string PDNSDbUser = "PDNSDbUser";
const string PDNSDbPassword = "PDNSDbPassword";
//soa record settings
const string ResponsiblePerson = "ResponsiblePerson";
const string RefreshInterval = "RefreshInterval";
const string RetryDelay = "RetryDelay";
const string ExpireLimit = "ExpireLimit";
const string MinimumTTL = "MinimumTTL";
//name servers
const string NameServers = "NameServers";
#endregion
#region Static ctor
static PowerDNS()
{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}
static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
//
if (!args.Name.Contains("MySql.Data"))
return null;
//
string connectorKeyName = "SOFTWARE\\MySQL AB\\MySQL Connector/Net";
string connectorLocation = String.Empty;
string connectorVersion = String.Empty;
//
if (PInvoke.RegistryHive.HKLM.SubKeyExists_x86(connectorKeyName))
{
connectorLocation = PInvoke.RegistryHive.HKLM.GetSubKeyValue_x86(connectorKeyName, "Location");
connectorVersion = PInvoke.RegistryHive.HKLM.GetSubKeyValue_x86(connectorKeyName, "Version");
}
//
if (String.IsNullOrEmpty(connectorLocation))
{
Log.WriteInfo("Connector location is either null or empty");
return null;
}
//
string assemblyFile = String.Empty;
// Versions 5.x.x compatibility
if (connectorVersion.StartsWith("5."))
assemblyFile = Path.Combine(connectorLocation, @"Binaries\.NET 2.0\" + args.Name.Split(',')[0] + ".dll");
// Newest versions compatibility
else
assemblyFile = Path.Combine(connectorLocation, @"Assemblies\" + args.Name.Split(',')[0] + ".dll");
//
Log.WriteInfo(assemblyFile);
//
if (!File.Exists(assemblyFile))
{
Log.WriteInfo("Connector assembly could not be found or does not exist");
return null;
}
//
return Assembly.LoadFrom(assemblyFile);
}
#endregion
#region Provider Properties
public string SOARefreshInterval
{
get { return ProviderSettings[RefreshInterval]; }
}
public string SOARetryDelay
{
get { return ProviderSettings[RetryDelay]; }
}
public string SOAExpireLimit
{
get { return ProviderSettings[ExpireLimit]; }
}
public string SOAMinimumTTL
{
get { return ProviderSettings[MinimumTTL]; }
}
public string DNSNameServers
{
get { return ProviderSettings[NameServers]; }
}
public string DbServer
{
get { return ProviderSettings[PDNSDbServer]; }
}
public string DbPort
{
get { return ProviderSettings[PDNSDbPort]; }
}
public string DbName
{
get { return ProviderSettings[PDNSDbName]; }
}
public string DbUser
{
get { return ProviderSettings[PDNSDbUser]; }
}
public string DbPassword
{
get { return ProviderSettings[PDNSDbPassword]; }
}
#endregion
#region IDnsServer Members
///
/// Used to check whether the particular zone exits.
/// Return true if yes and false otherwise.
///
/// Name of zone to be found.
/// Bollean value. True if zone exists and false otherwise.
public bool ZoneExists(string zoneName)
{
bool result = false;
try
{
MySqlParameter ZoneName = new MySqlParameter("?ZoneName", MySqlDbType.VarString);
ZoneName.Value = zoneName;
IDataReader reader = ExecuteReader(
"SELECT name FROM domains WHERE name = ?ZoneName LIMIT 1"
, ZoneName
);
if (reader.Read())
{
result = true;
}
reader.Close();
}
catch (Exception ex)
{
Log.WriteError(String.Format("Error locating '{0}' Power DNS zone", zoneName), ex);
}
return result;
}
///
/// Returns the list of zones from Power DNS.
///
/// Array of zone names
public string[] GetZones()
{
List zones = new List();
try
{
IDataReader reader = ExecuteReader(
"SELECT name FROM domains"
);
while (reader.Read())
{
zones.Add(
reader["name"].ToString()
);
}
reader.Close();
}
catch (Exception ex)
{
Log.WriteError("Error getting the list of Power DNS zones.", ex);
}
return zones.ToArray();
}
///
/// This method is being called when Power DNS server is a primary DNS server.
/// By primary we mean that Power DNS is the only DNS server, or it is primary (can have secondary)
/// server for this zone.
///
/// Domain name in the Power DNS database.
/// IP Addresses of servers bound to Power DNS server
public void AddPrimaryZone(string zoneName, string[] secondaryServers)
{
PDNSAddZone(zoneName, "NATIVE", secondaryServers);
}
///
/// This methodis is being called when Power DNS server is a secondary DNS server for some other DNS server.
/// So, firstly, AddPrimaryZone is callled for those DNS server to which Power DNS is bound and only then,
/// this method is called to write zone data to Power DNS.
///
/// Domain name in Power DNS database.
/// Primary DNS for current Power DNS instance.
public void AddSecondaryZone(string zoneName, string[] masterServers)
{
PDNSAddZone(zoneName, "SLAVE", masterServers);
}
///
/// Removes zone from Power DNS database by name.
///
///
public void DeleteZone(string zoneName)
{
try
{
string domainId = GetDomainId(zoneName);
if (string.IsNullOrEmpty(domainId))
return;
MySqlParameter DomainId = new MySqlParameter("?DomainId", MySqlDbType.Int32);
DomainId.Value = domainId;
//clear records table
ExecuteNonQuery(
"DELETE FROM records WHERE domain_id = ?DomainId"
, DomainId
);
//clear domains table
ExecuteNonQuery(
"DELETE FROM domains WHERE id = ?DomainId"
, DomainId
);
}
catch (Exception ex)
{
Log.WriteError(String.Format("Error deleting '{0}' Power DNS zone", zoneName), ex);
}
}
//partially tested
public void UpdateSoaRecord(string zoneName, string host, string primaryNsServer, string primaryPerson)
{
string recordId = string.Empty;
string recordContent = string.Empty;
try
{
MySqlParameter ZoneName = new MySqlParameter("?Name", MySqlDbType.VarString);
ZoneName.Value = zoneName;
MySqlParameter RecordType = new MySqlParameter("?Type", MySqlDbType.VarString);
RecordType.Value = ConvertDnsRecordTypeToString(DnsRecordType.SOA);
IDataReader reader = ExecuteReader(
"SELECT id, content FROM records WHERE name = ?Name AND type = ?Type LIMIT 1"
, ZoneName
, RecordType
);
if (reader.Read())
{
recordId = reader["id"].ToString();
recordContent = reader["content"].ToString();
}
reader.Close();
if (string.IsNullOrEmpty(recordId))
throw new ArgumentOutOfRangeException(string.Format("Not SOA record for Power DNS zone '{0}'", zoneName));
PowerDnsSOARecordData soaData = PowerDnsSOARecordData.FromString(recordContent);
soaData.PrimaryNameServer = primaryNsServer;
soaData.HostMaster = primaryPerson;
soaData.Refresh = SOARefreshInterval;
soaData.Retry = SOARetryDelay;
soaData.DefaultTTL = SOAMinimumTTL;
soaData.Expire = SOAExpireLimit;
soaData.IncrementSerial(
GetDomainNotifiedSerial(zoneName)
);
UpdateRecord(recordId, soaData.ToString());
}
catch (Exception ex)
{
Log.WriteError(String.Format("Error updating SOA record for '{0}' Power DNS zone", zoneName), ex);
}
}
//TESTED: partially
///
/// The caller of this method is not waiting for SOA records. Assuming this, one should return all records except SOA.
///
/// Corresponds to the Domain name in the Power DNS domains table.
/// All DnsRecords except of SOA type.
public DnsRecord[] GetZoneRecords(string zoneName)
{
List records = new List();
try
{
string domainId = GetDomainId(zoneName);
if (string.IsNullOrEmpty(domainId))
throw new ArgumentOutOfRangeException("Power DNS zone '{0}' does not exist.");
MySqlParameter DomainId = new MySqlParameter("?DomainId", MySqlDbType.Int32);
DomainId.Value = domainId;
IDataReader reader = ExecuteReader(
"SELECT * FROM records WHERE domain_id = ?DomainId AND type != 'SOA'"
, DomainId
);
while (reader.Read())
{
DnsRecord record = new DnsRecord();
record.RecordData = reader["content"].ToString();
record.RecordName = CorrectHost(zoneName, reader["name"].ToString());
record.RecordType = ConvertStringToDnsRecordType(reader["type"].ToString());
int mxPriority = 0;
if (!string.IsNullOrEmpty(reader["prio"].ToString()))
if (Int32.TryParse(reader["prio"].ToString(), out mxPriority))
{
record.MxPriority = mxPriority;
}
records.Add(record);
}
reader.Close();
}
catch (Exception ex)
{
Log.WriteError(String.Format("Error getting records for '{0}' Power DNS zone", zoneName), ex);
}
return records.ToArray();
}
///
/// Adds zone record into Power DNS database
///
/// Domain name in Power DNS database.
/// Record in Power DNS database
public void AddZoneRecord(string zoneName, DnsRecord record)
{
PDNSAddZoneRecord(zoneName, record, true);
}
public void AddZoneRecords(string zoneName, DnsRecord[] records)
{
foreach (DnsRecord record in records)
{
PDNSAddZoneRecord(zoneName, record, false);
}
PDNSUpdateSoaRecord(zoneName);
}
///
/// Delete zone record from Power DNS database.
///
/// Domain name from Power DNS database
/// Record from Power DNS database
public void DeleteZoneRecord(string zoneName, DnsRecord record)
{
PDNSDeleteZoneRecord(zoneName, record, true);
}
public void DeleteZoneRecords(string zoneName, DnsRecord[] records)
{
foreach (DnsRecord record in records)
{
PDNSDeleteZoneRecord(zoneName, record, false);
}
PDNSUpdateSoaRecord(zoneName);
}
#endregion
#region Zone
///
/// Adds zone in Power DNS domains table and creates a SOA record for it.
///
/// Domain name in Power DNS database.
///
///
protected void PDNSAddZone(string zoneName, string zoneType, string[] nameServers)
{
string domainId = AddDomainAndReturnDomainId(zoneName, zoneType);
if (string.IsNullOrEmpty(domainId))
throw new ArgumentOutOfRangeException(string.Format("Unable to add Power DNS zone '{0}'.", zoneName));
//create SOA record
PowerDnsSOARecordData data = new PowerDnsSOARecordData();
data.DefaultTTL = SOAMinimumTTL;
data.Expire = SOAExpireLimit;
data.Refresh = SOARefreshInterval;
data.Retry = SOARetryDelay;
data.Serial = DateTime.Now.ToString("yyyyMMdd") + "01";
//add SOA record
AddRecord(
domainId
, zoneName
, data.ToString()
, ConvertDnsRecordTypeToString(DnsRecordType.SOA)
, GetDefaultRecordTTL(DnsRecordType.SOA)
, "0"
);
//add NS records for secondary servers
foreach (string server in nameServers)
{
AddRecord(
domainId
, zoneName
, server
, ConvertDnsRecordTypeToString(DnsRecordType.NS)
, GetDefaultRecordTTL(DnsRecordType.NS)
, "0"
);
}
}
#endregion
#region Zone Record
protected void PDNSAddZoneRecord(string zoneName, DnsRecord record, bool isNeedToUpdateSOA)
{
string domainId = GetDomainId(zoneName);
if (domainId == string.Empty)
throw new ArgumentOutOfRangeException("DomainId not found. Zone does not exist.");
string recordType = ConvertDnsRecordTypeToString(record.RecordType);
string ttl = GetDefaultRecordTTL(record.RecordType);
//NS record
if (record.RecordType == DnsRecordType.NS)
{
if (string.IsNullOrEmpty(record.RecordName))
record.RecordName = zoneName;
}
//widen record name for Power DNS
if (!string.IsNullOrEmpty(record.RecordName))
{
if (!record.RecordName.Contains(zoneName))
{
record.RecordName = string.Format("{0}.{1}", record.RecordName, zoneName);
}
}
else
{
record.RecordName = zoneName;
}
AddRecord(
domainId
, record.RecordName
, record.RecordData
, recordType
, ttl
, record.MxPriority.ToString()
);
if (isNeedToUpdateSOA)
{
PDNSUpdateSoaRecord(zoneName);
}
}
protected void PDNSDeleteZoneRecord(string zoneName, DnsRecord record, bool isNeedToUpdateSOA)
{
string recordName = zoneName;
if (!String.IsNullOrEmpty(record.RecordName))
{
recordName = string.Format("{0}.{1}", record.RecordName, recordName);
}
RemoveRecord(
recordName
, ConvertDnsRecordTypeToString(record.RecordType)
, record.RecordData
, record.MxPriority
);
if (isNeedToUpdateSOA)
{
PDNSUpdateSoaRecord(zoneName);
}
}
#endregion
#region SOA Record
///
/// Updates SOA record of the corresponding zone
///
/// Domain name in Power DNS database
protected void PDNSUpdateSoaRecord(string zoneName)
{
try
{
string domainId = GetDomainId(zoneName);
if (string.IsNullOrEmpty(domainId))
throw new ArgumentOutOfRangeException(string.Format("Power DNS zone '{0}' does not exist.", domainId));
MySqlParameter DomainId = new MySqlParameter("?DomainId", MySqlDbType.Int32);
DomainId.Value = domainId;
IDataReader reader = ExecuteReader(
"SELECT id, content FROM records WHERE domain_id = ?DomainId AND type='SOA' LIMIT 1"
, DomainId
);
string
recordId = string.Empty,
recordContent = string.Empty;
if (reader.Read())
{
recordId = reader["id"].ToString();
recordContent = reader["content"].ToString();
}
if (string.IsNullOrEmpty(recordId))
throw new ArgumentOutOfRangeException(string.Format("SOA record for Power DNS zone '{0}' not found", zoneName));
PowerDnsSOARecordData data = PowerDnsSOARecordData.FromString(recordContent);
data.Refresh = SOARefreshInterval;
data.Retry = SOARetryDelay;
data.DefaultTTL = SOAMinimumTTL;
data.Expire = SOAExpireLimit;
data.IncrementSerial(GetDomainNotifiedSerial(zoneName));
UpdateRecord(recordId, data.ToString());
}
catch (Exception ex)
{
Log.WriteError(String.Format("Error updating SOA record for '{0}' Power DNS zone", zoneName), ex);
}
}
#endregion
#region Database Helper Methods
protected string GetConnectionString()
{
return string.Format(
"server={0};port={1};database={2};uid={3};password={4}"
, DbServer
, DbPort
, DbName
, DbUser
, DbPassword
);
}
public IDataReader ExecuteReader(string mySqlStatement, params MySqlParameter[] parameters)
{
MySqlConnection mysqlConnection = new MySqlConnection(GetConnectionString());
mysqlConnection.Open();
MySqlCommand command = new MySqlCommand(
mySqlStatement
, mysqlConnection
);
foreach (MySqlParameter param in parameters)
{
command.Parameters.Add(param);
}
return command.ExecuteReader(CommandBehavior.CloseConnection);
}
public int ExecuteNonQuery(string mySqlStatement, params MySqlParameter[] parameters)
{
MySqlConnection mysqlConnection = new MySqlConnection(GetConnectionString());
mysqlConnection.Open();
MySqlCommand command = new MySqlCommand(
mySqlStatement
, mysqlConnection
);
foreach (MySqlParameter param in parameters)
{
command.Parameters.Add(param);
}
int returnValue = command.ExecuteNonQuery();
mysqlConnection.Close();
return returnValue;
}
#endregion
#region Record Helper Methods
///
/// Removes record by it's name and type.
///
///
///
void RemoveRecord(string name, string type, string content, int mxPriority)
{
try
{
MySqlParameter RecordName = new MySqlParameter("?RecordName", MySqlDbType.VarString);
RecordName.Value = name;
MySqlParameter RecordType = new MySqlParameter("?RecordType", MySqlDbType.VarString);
RecordType.Value = type;
MySqlParameter RecordContent = new MySqlParameter("?RecordContent", MySqlDbType.VarString);
RecordContent.Value = "%" + content.Trim() + "%";
MySqlParameter RecordPriority = new MySqlParameter("?RecordPriority", MySqlDbType.Int32);
RecordPriority.Value = mxPriority;
ExecuteNonQuery(
"DELETE FROM records WHERE name = ?RecordName AND type = ?RecordType AND prio = ?RecordPriority AND content like ?RecordContent "
, RecordName
, RecordType
, RecordContent
, RecordPriority
);
}
catch (Exception ex)
{
Log.WriteError(String.Format("Error removing record '{0}' of type '{1}' from Power DNS", name, type), ex);
}
}
///
/// Add record to Power DNS database
///
///
///
///
///
///
///
protected void AddRecord(string domainId, string name, string content, string type, string ttl, string prio)
{
try
{
MySqlParameter DomainId = new MySqlParameter("?DomainId", MySqlDbType.Int32);
DomainId.Value = domainId;
MySqlParameter RecordName = new MySqlParameter("?RecordName", MySqlDbType.VarString);
RecordName.Value = name;
MySqlParameter RecordContent = new MySqlParameter("?RecordContent", MySqlDbType.VarString);
RecordContent.Value = content;
MySqlParameter RecordType = new MySqlParameter("?RecordType", MySqlDbType.VarString);
RecordType.Value = type;
MySqlParameter RecordTtl = new MySqlParameter("?RecordTtl", MySqlDbType.Int32);
RecordTtl.Value = ttl;
MySqlParameter RecordPriority = new MySqlParameter("?RecordPriority", MySqlDbType.Int32);
RecordPriority.Value = prio;
ExecuteNonQuery(
"INSERT INTO records (domain_id, name, content, type, ttl, prio) " +
"VALUES (?DomainId, ?RecordName, ?RecordContent, ?RecordType, ?RecordTtl, ?RecordPriority)"
, DomainId
, RecordName
, RecordContent
, RecordType
, RecordTtl
, RecordPriority
);
}
catch (Exception ex)
{
Log.WriteError(String.Format("Error adding record '{0}' of type '{1}' in Power DNS", name, type), ex);
}
}
///
/// Updates record's content field
///
///
///
protected void UpdateRecord(string recordId, string content)
{
try
{
MySqlParameter RecordContent = new MySqlParameter("?RecordContent", MySqlDbType.VarString);
RecordContent.Value = content;
MySqlParameter RecordId = new MySqlParameter("?RecordId", MySqlDbType.Int32);
RecordId.Value = recordId;
ExecuteNonQuery(
"UPDATE records SET content = ?RecordContent " +
"WHERE id = ?RecordId LIMIT 1"
, RecordContent
, RecordId
);
}
catch (Exception ex)
{
Log.WriteError(String.Format("Error updating record with id '{0}' in Power DNS", recordId), ex);
}
}
///
/// Provides a default TTLs for records.
///
///
///
public string GetDefaultRecordTTL(DnsRecordType recordType)
{
string ttl = string.Empty;
switch (recordType)
{
case DnsRecordType.SOA:
ttl = SOAMinimumTTL;
break;
case DnsRecordType.NS:
ttl = "3600";
break;
default:
ttl = "120";
break;
}
return ttl;
}
///
/// Represents SOA record contents in Power DNS database.
/// Allows to perform Increment operation.
///
internal class PowerDnsSOARecordData
{
public string PrimaryNameServer = "localhost";
public string HostMaster = "hostmaster.yourdomain.com";
public string Serial = "1";
public string Refresh = "10800";
public string Retry = "3600";
public string Expire = "84600";
public string DefaultTTL = "3600";
///
/// Converts class instance to string representation.
///
/// SOA record content according to the Power DNS SOA record content format
public override string ToString()
{
return string.Format(
"{0} {1} {2} {3} {4} {5} {6}"
, PrimaryNameServer
, HostMaster
, Serial
, Refresh
, Retry
, Expire
, DefaultTTL
).Trim();
}
///
/// Creates class instance from string.
///
/// Record content from Power DNS database.
/// Instance of class.
public static PowerDnsSOARecordData FromString(string content)
{
PowerDnsSOARecordData data = new PowerDnsSOARecordData();
string[] contentParts = content
.Trim()
.Split(' ');
for (int i = 0; i < contentParts.Length; i++)
{
data.UpdateProperty(i, contentParts[i]);
}
return data;
}
///
/// Increments Serial number of SOA record according to RFC for DNS format.
///
/// Is a serial number of SOA record notified by primary server.
public void IncrementSerial(string notifiedSerial)
{
string todayDate = DateTime.Now.ToString("yyyyMMdd");
if (notifiedSerial.Contains(todayDate))
{
Serial = notifiedSerial;
}
if (Serial.Length < 10 || !Serial.StartsWith(todayDate))
{
Serial = todayDate + "01";
}
else
{
Serial = (UInt32.Parse(Serial) + 1).ToString();
}
}
private void UpdateProperty(int index, string data)
{
switch (index)
{
case 0:
PrimaryNameServer = data;
break;
case 1:
HostMaster = data;
break;
case 2:
Serial = data;
break;
case 3:
Refresh = data;
break;
case 4:
Retry = data;
break;
case 5:
Expire = data;
break;
case 6:
DefaultTTL = data;
break;
default:
throw new ArgumentOutOfRangeException("Unknown index.");
}
}
}
#endregion
#region Domain Record Helpers
///
/// Determines domain id by its name.
///
/// Domain name in Power DNS database.
/// Domain Id
protected string GetDomainId(string domainName)
{
string domainId = string.Empty;
try
{
MySqlParameter DomainName = new MySqlParameter("?DomainName", MySqlDbType.VarString);
DomainName.Value = domainName;
IDataReader reader = ExecuteReader(
"SELECT id FROM domains WHERE name = ?DomainName LIMIT 1"
, DomainName
);
if (reader.Read())
{
domainId = reader["id"].ToString();
}
reader.Close();
}
catch (Exception ex)
{
Log.WriteError(String.Format("Error getting domain '{0}' id from Power DNS.", domainName), ex);
}
return domainId;
}
///
/// Determines notified_serial value from Domains table in Power DNS database.
///
/// Domain name in Power DNS database.
/// string represeting notified_serial field.
protected string GetDomainNotifiedSerial(string domainName)
{
string domainId = string.Empty;
try
{
MySqlParameter DomainName = new MySqlParameter("?DomainName", MySqlDbType.VarString);
DomainName.Value = domainName;
IDataReader reader = ExecuteReader(
"SELECT notified_serial FROM domains WHERE name = ?DomainName LIMIT 1"
, DomainName
);
if (reader.Read())
{
domainId = reader["notified_serial"].ToString();
}
reader.Close();
}
catch (Exception ex)
{
Log.WriteError(String.Format("Error getting notofied serial for domain '{0}' from Power DNS.", domainName), ex);
}
return domainId;
}
///
/// Inserts domain into Power DNS database and returns it's id.
///
/// Domain name in Power DNS database.
/// Can be Native or Slave
/// An id of the inserted domain
protected string AddDomainAndReturnDomainId(string zoneName, string domainType)
{
AddDomain(zoneName, domainType);
return GetDomainId(zoneName);
}
///
/// Add domain into Power DNS database.
///
/// Domain name in Power DNS database.
/// Can be Native or Slave
protected void AddDomain(string zoneName, string domainType)
{
try
{
MySqlParameter DomainName = new MySqlParameter("?DomainName", MySqlDbType.VarString);
DomainName.Value = zoneName;
MySqlParameter DomainType = new MySqlParameter("?DomainType", MySqlDbType.VarString);
DomainType.Value = domainType;
ExecuteNonQuery(
"INSERT INTO domains (name, type) VALUES (?DomainName, ?DomainType)"
, DomainName
, DomainType
);
}
catch (Exception ex)
{
Log.WriteError(String.Format("Error adding domain '{0}' of type '{1}' to Power DNS", zoneName, domainType), ex);
}
}
#endregion
#region Conversion Methods
public DnsRecordType ConvertStringToDnsRecordType(string recordType)
{
DnsRecordType result = DnsRecordType.Other;
switch (recordType)
{
case "A":
result = DnsRecordType.A;
break;
case "CNAME":
result = DnsRecordType.CNAME;
break;
case "MX":
result = DnsRecordType.MX;
break;
case "NS":
result = DnsRecordType.NS;
break;
case "TXT":
result = DnsRecordType.TXT;
break;
case "SOA":
result = DnsRecordType.SOA;
break;
default:
result = DnsRecordType.Other;
break;
}
return result;
}
public string ConvertDnsRecordTypeToString(DnsRecordType recordType)
{
string result = string.Empty;
switch (recordType)
{
case DnsRecordType.A:
result = "A";
break;
case DnsRecordType.CNAME:
result = "CNAME";
break;
case DnsRecordType.MX:
result = "MX";
break;
case DnsRecordType.NS:
result = "NS";
break;
case DnsRecordType.SOA:
result = "SOA";
break;
case DnsRecordType.TXT:
result = "TXT";
break;
case DnsRecordType.Other:
default:
throw new NotSupportedException("Record type not supported.");
}
return result;
}
#endregion
///
/// If zoneName stored in Power DNS is the same as record name (host) for this zone the the return value is string.Empty.
/// If record name different, then we delete zone name from record name ans return the rest.
///
/// Represents domain name in Power DNS database.
/// FQDN, record name in Power DNS database.
/// Third Level Domain name or empty string if zoneName == host.
private string CorrectHost(string zoneName, string host)
{
if (host == String.Empty)
return host;
if (host.ToLower() == zoneName.ToLower())
return string.Empty;
else
return host.Substring(0, (host.Length - zoneName.Length - 1));
}
public override void DeleteServiceItems(ServiceProviderItem[] items)
{
foreach (ServiceProviderItem item in items)
{
if (item is DnsZone)
{
try
{
// delete DNS zone
DeleteZone(item.Name);
}
catch (Exception ex)
{
Log.WriteError(String.Format("Error deleting '{0}' Power DNS zone", item.Name), ex);
}
}
}
}
public override bool IsInstalled()
{
return false;
}
}
}