Merge with Ipv6 contribution

This commit is contained in:
Feodor 2012-08-20 12:35:46 -07:00
commit df5da7b015
35 changed files with 2893 additions and 158 deletions

BIN
IPv6 Test Cases.docx Normal file

Binary file not shown.

View file

@ -0,0 +1,164 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace WebsitePanel.EnterpriseServer {
public struct IPAddress {
public Int128 Address;
public bool V6 { get; private set; }
public bool V4 { get { return !V6 || Null; } }
public bool IsSubnet { get; private set; }
public bool IsMask { get; private set; }
public int Cidr { get; private set; }
public bool Null { get; private set; }
public IPAddress LastSubnetIP { get { return new IPAddress { Address = (Address | (~((Int128)0) >> (V4 ? Cidr + 64 : Cidr))), Cidr = V4 ? 32 : 128, IsSubnet = false, Null = false, V6 = V6 }; } }
public IPAddress FirstSubnetIP { get { return new IPAddress { Address = (Address & ~(~((Int128)0) >> (V4 ? Cidr + 64 : Cidr))) + 1, Cidr = V4 ? 32 : 128, IsSubnet = false, Null = false, V6 = V6 }; } }
public Int128 Mask { get { return IsSubnet ? Int128.MinValue >> (Cidr-1) : Address; } }
const int c = 256*256;
public static IPAddress Parse(string ip)
{
IPAddress adr = default(IPAddress);
adr.V6 = false;
if (String.IsNullOrEmpty(ip)) {
adr.Address = 0; adr.Null = true; adr.Cidr = 32; adr.IsSubnet = false;
return adr;
}
if (ip.Contains('/')) {
var tokens = ip.Split('/');
ip = tokens[0];
adr.IsSubnet = true;
adr.Cidr = Utils.ParseInt(tokens[1], -1);
}
if (string.IsNullOrWhiteSpace(ip)) {
adr.IsMask = true; adr.V6 = true;
adr.Address = adr.Mask;
} else {
var ipadr = System.Net.IPAddress.Parse(ip);
if (adr.V6 = ipadr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) {
byte[] bytes = ipadr.GetAddressBytes();
Int128 a = 0;
for (int i = 0; i < 16; i++) {
a = a * 256 + bytes[i];
}
adr.Address = a;
} else {
string[] parts = ip.Split('.');
adr.Address = (Int128)(Int32.Parse(parts[3]) +
(Int32.Parse(parts[2]) << 8) +
(Int32.Parse(parts[1]) << 16) +
(Int32.Parse(parts[0]) << 24));
}
}
if (adr.V4 && (adr.Cidr > 32 || 0 > adr.Cidr)) throw new ArgumentOutOfRangeException("Cidr must not be greater than 32 for IPv4 Addresses.");
if (adr.V6 && (adr.Cidr > 128 || 0 > adr.Cidr)) throw new ArgumentOutOfRangeException("Cidr must not be greater than 128 for IPv6 Addresses.");
return adr;
}
public override string ToString()
{
if (Null)
return "";
var s = new System.Text.StringBuilder();
if (!V6) {
var ipl = (long)Address;
s.Append(String.Format("{0}.{1}.{2}.{3}", (ipl >> 24) & 0xFFL, (ipl >> 16) & 0xFFL, (ipl >> 8) & 0xFFL, (ipl & 0xFFL)));
} else if (!IsMask) {
var vals = new List<int>();
int i;
Int128 a = Address;
for (i = 0; i < 8; i++) {
vals.Add((int)(a % c));
a = a / c;
}
int index = -1, n = 0, m = 0;
for (i = 7; i >= 0; i--) {
if (vals[i] == 0) {
n++;
if (n > m) {
index = i;
m = n;
}
}
}
index += m-1;
i = 7;
while (i >= 0) {
if (i == index) {
if (m == 8) s.Append("::");
else s.Append(":");
i -= m;
}
if (i >= 0) {
if (i < 7) s.Append(":");
s.Append(vals[i].ToString("x"));
}
i--;
}
}
if (IsSubnet && !(IsMask && V4)) {
s.Append('/'); s.Append(Cidr.ToString());
}
return s.ToString();
}
public string ToV4MaskString() {
V6 = false;
IsMask = true;
return ToString();
}
public static bool operator ==(IPAddress a, IPAddress b) { return a.Address == b.Address && a.Null == b.Null && (a.Null || !(a.IsSubnet && b.IsSubnet || a.IsMask && b.IsMask) || a.Cidr == b.Cidr); }
public static bool operator ==(IPAddress a, long b) { return a.Address == b; }
public static bool operator !=(IPAddress a, IPAddress b) { return !(a == b); }
public static bool operator !=(IPAddress a, long b) { return a.Address != b; }
public static bool operator <(IPAddress a, IPAddress b) { return a.Address < b.Address; }
public static bool operator >(IPAddress a, IPAddress b) { return a.Address > b.Address; }
public static bool operator <=(IPAddress a, IPAddress b) { return a.Address <= b.Address; }
public static bool operator >=(IPAddress a, IPAddress b) { return a.Address >= b.Address; }
/*
public static IPAddress operator +(IPAddress a, IPAddress b) {
if (a.IsSubnet || b.IsSubnet || a.V6 != b.V6) throw new ArgumentException("Arithmetic with subnets or mixed v4 & v6 addresses not supported.");
return new IPAddress { Address = a.Address + b.Address, Null = a.Null && b.Null, Cidr = 0, V6 = a.V6 };
}*/
public static Int128 operator -(IPAddress a, IPAddress b) {
if (a.IsSubnet || b.IsSubnet || a.V6 != b.V6) throw new ArgumentException("Arithmetic with subnets or mixed v4 & v6 addresses not supported.");
return a.Address - b.Address;
}
public static IPAddress operator +(IPAddress a, Int128 b) {
return new IPAddress { Address = a.Address + b, Null = a.Null, Cidr = a.V4 ? 32 : 128, V6 = a.V6 };
}
public static IPAddress operator -(IPAddress a, Int128 b) {
return new IPAddress { Address = a.Address - b, Null = a.Null, Cidr = a.V4 ? 32 : 128, V6 = a.V6 };
}
public static IPAddress operator |(IPAddress a, IPAddress b) {
if (a.V6 != b.V6) throw new ArgumentException("Arithmetic with mixed v4 & v6 addresses not supported.");
return new IPAddress { Address = a.Address | b.Address, Cidr = a.V4 ? 32 : 128, Null = false, V6 = a.V6, IsSubnet = false };
}
public static IPAddress operator &(IPAddress a, IPAddress b) {
if (a.V6 != b.V6) throw new ArgumentException("Arithmetic with mixed v4 & v6 addresses not supported.");
return new IPAddress { Address = a.Address | b.Address, Cidr = a.V4 ? 32 : 128, Null = false, V6 = a.V6, IsSubnet = false };
}
public static IPAddress operator ~(IPAddress a) {
if (a.Null) return new IPAddress { Address = 0, Null = true, Cidr = a.V4 ? 32 : 128, V6 = true, IsSubnet = false };
return new IPAddress { Address = ~a.Address, Cidr = a.Cidr , Null = false, V6 = a.V6, IsSubnet = false };
}
public static implicit operator IPAddress(NullIPAddress a) { return new IPAddress { Null = true, Address = 0, Cidr = -1 }; }
}
public class NullIPAddress { }
}

File diff suppressed because it is too large Load diff

View file

@ -281,7 +281,7 @@ namespace WebsitePanel.EnterpriseServer
rr.RecordType = (DnsRecordType)Enum.Parse(typeof(DnsRecordType), record.RecordType, true); rr.RecordType = (DnsRecordType)Enum.Parse(typeof(DnsRecordType), record.RecordType, true);
rr.RecordName = record.RecordName; rr.RecordName = record.RecordName;
if (record.RecordType == "A") if (record.RecordType == "A" || record.RecordType == "AAAA")
{ {
rr.RecordData = String.IsNullOrEmpty(record.RecordData) ? record.ExternalIP : record.RecordData; rr.RecordData = String.IsNullOrEmpty(record.RecordData) ? record.ExternalIP : record.RecordData;
rr.RecordData = Utils.ReplaceStringVariable(rr.RecordData, "ip", record.ExternalIP); rr.RecordData = Utils.ReplaceStringVariable(rr.RecordData, "ip", record.ExternalIP);

View file

@ -65,7 +65,7 @@ namespace WebsitePanel.EnterpriseServer
DnsRecord[] records = ServerController.GetDnsZoneRecords(domainId); DnsRecord[] records = ServerController.GetDnsZoneRecords(domainId);
foreach (DnsRecord record in records) foreach (DnsRecord record in records)
{ {
if ((record.RecordType == DnsRecordType.A) && (String.Compare(recordName, record.RecordName, true) == 0)) if ((record.RecordType == DnsRecordType.A || record.RecordType == DnsRecordType.AAAA) && (String.Compare(recordName, record.RecordName, true) == 0))
{ {
CompleteTask(ret, CrmErrorCodes.CANNOT_CREATE_DNS_ZONE, null, CompleteTask(ret, CrmErrorCodes.CANNOT_CREATE_DNS_ZONE, null,
string.Format("DNS record already exists. DomainId={0}, RecordName={1}", domainId, recordName)); string.Format("DNS record already exists. DomainId={0}, RecordName={1}", domainId, recordName));
@ -73,8 +73,8 @@ namespace WebsitePanel.EnterpriseServer
return ret; return ret;
} }
} }
var type = ip.Contains(":") ? DnsRecordType.AAAA : DnsRecordType.A;
int res = ServerController.AddDnsZoneRecord(domainId, recordName, DnsRecordType.A, ip, 0, 0, 0, 0); int res = ServerController.AddDnsZoneRecord(domainId, recordName, type, ip, 0);
if (res != 0) if (res != 0)
{ {
CompleteTask(ret, CrmErrorCodes.CANNOT_CREATE_DNS_ZONE, null, CompleteTask(ret, CrmErrorCodes.CANNOT_CREATE_DNS_ZONE, null,
@ -373,7 +373,8 @@ namespace WebsitePanel.EnterpriseServer
try try
{ {
int res = ServerController.DeleteDnsZoneRecord(domainId, recordName, DnsRecordType.A, ip); var type = ip.Contains(":") ? DnsRecordType.AAAA : DnsRecordType.A;
int res = ServerController.DeleteDnsZoneRecord(domainId, recordName, type, ip);
if (res != 0) if (res != 0)
{ {

View file

@ -948,6 +948,8 @@ namespace WebsitePanel.EnterpriseServer
public static ResultObject AddIPAddressesRange(IPAddressPool pool, int serverId, public static ResultObject AddIPAddressesRange(IPAddressPool pool, int serverId,
string externalIP, string endIP, string internalIP, string subnetMask, string defaultGateway, string comments) string externalIP, string endIP, string internalIP, string subnetMask, string defaultGateway, string comments)
{ {
const int MaxSubnet = 512; // TODO bigger max subnet?
ResultObject res = new ResultObject(); ResultObject res = new ResultObject();
#region Check account statuses #region Check account statuses
@ -973,23 +975,28 @@ namespace WebsitePanel.EnterpriseServer
return res; return res;
} }
long startExternalIP = ConvertIPToLong(externalIP); var startExternalIP = IPAddress.Parse(externalIP);
long startInternalIP = ConvertIPToLong(internalIP); var startInternalIP = IPAddress.Parse(internalIP);
long endExternalIP = ConvertIPToLong(endIP); var endExternalIP = IPAddress.Parse(endIP);
// handle CIDR notation IP/Subnet addresses
if (startExternalIP.IsSubnet && endExternalIP == null) {
endExternalIP = startExternalIP.LastSubnetIP;
startExternalIP = startExternalIP.FirstSubnetIP;
}
if (startExternalIP.V6 != startInternalIP.V6 && (startExternalIP.V6 != endExternalIP.V6 && endExternalIP != null)) throw new NotSupportedException("All IP addresses must be either V4 or V6.");
int i = 0; int i = 0;
long step = (endExternalIP < startExternalIP) ? -1 : 1; long step = (endExternalIP < startExternalIP) ? -1 : 1;
while (true) while (true)
{ {
if (i > 128) if (i > MaxSubnet)
break; break;
// add IP address // add IP address
DataProvider.AddIPAddress((int)pool, serverId, DataProvider.AddIPAddress((int)pool, serverId, startExternalIP.ToString(), startInternalIP.ToString(), subnetMask, defaultGateway, comments);
ConvertLongToIP(startExternalIP),
ConvertLongToIP(startInternalIP),
subnetMask, defaultGateway, comments);
if (startExternalIP == endExternalIP) if (startExternalIP == endExternalIP)
break; break;
@ -2439,26 +2446,78 @@ namespace WebsitePanel.EnterpriseServer
#endregion #endregion
#region Private methods #region Private methods
public static long ConvertIPToLong(string ip)
/*
const int c = 256*256;
public static BigInt ConvertIPToInt(string ip, out bool v6)
{ {
v6 = false;
if (String.IsNullOrEmpty(ip)) if (String.IsNullOrEmpty(ip))
return 0; return 0;
var adr = System.Net.IPAddress.Parse(ip);
if (v6 = adr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) {
string[] parts = ip.Split('.'); string[] parts = ip.Split('.');
return Int32.Parse(parts[3]) + return (BigInt)(Int32.Parse(parts[3]) +
(Int32.Parse(parts[2]) << 8) + (Int32.Parse(parts[2]) << 8) +
(Int32.Parse(parts[1]) << 16) + (Int32.Parse(parts[1]) << 16) +
(Int32.Parse(parts[0]) << 24); (Int32.Parse(parts[0]) << 24));
} else {
byte[] bytes = adr.GetAddressBytes();
var a = BigInt.Zero;
for (int i = 0; i < 16; i--) {
a = a*256 + bytes[i];
}
return a;
}
} }
public static string ConvertLongToIP(long ip) public static string ConvertIntToIP(BigInt ip, bool v6)
{ {
if (ip == 0) if (ip == BigInt.Zero)
return ""; return "";
if (!v6) {
var ipl = (long)ip;
return String.Format("{0}.{1}.{2}.{3}", return String.Format("{0}.{1}.{2}.{3}",
(ip >> 24) & 0xFFL, (ip >> 16) & 0xFFL, (ip >> 8) & 0xFFL, (ip & 0xFFL)); (ipl >> 24) & 0xFFL, (ipl >> 16) & 0xFFL, (ipl >> 8) & 0xFFL, (ipl & 0xFFL));
} else {
var vals = new List<int>();
int i;
for (i = 0; i < 8; i++) {
vals.Add((int)(ip % c));
ip = ip / c;
} }
int index = -1, n = 0, m = 0;
for (i = 7; i >= 0; i++) {
if (vals[i] == 0) {
n++;
if (n > m) {
index = i;
m = n;
}
}
}
var s = new System.Text.StringBuilder();
i = 7;
while (i >= 0) {
if (i != index) {
if (i < 7) s.Append(":");
s.Append(vals[i].ToString("x"));
i--;
} else {
s.Append(":");
while (vals[i] == 0) i--;
}
}
return s.ToString();
}
}
*/
#endregion #endregion
} }
} }

View file

@ -339,14 +339,19 @@ namespace WebsitePanel.EnterpriseServer.Code.SharePoint
DnsRecord[] records = ServerController.GetDnsZoneRecords(domain.DomainId); DnsRecord[] records = ServerController.GetDnsZoneRecords(domain.DomainId);
foreach (DnsRecord record in records) foreach (DnsRecord record in records)
{ {
if (record.RecordType.Equals(DnsRecordType.A) && (record.RecordName == hostName)) var type = record.RecordType;
if ((type == DnsRecordType.A || type == DnsRecordType.AAAA) && String.IsNullOrEmpty(record.RecordName))
{ {
ServerController.DeleteDnsZoneRecord(domain.DomainId, hostName, DnsRecordType.A, record.RecordData); ServerController.DeleteDnsZoneRecord(domain.DomainId, String.Empty, type, record.RecordData);
break; break;
} }
} }
ServerController.AddDnsZoneRecord(domain.DomainId, hostName, DnsRecordType.A, hostedSharePointSettings["RootWebApplicationIpAddress"], 0, 0, 0, 0); ServerController.AddDnsZoneRecord(domain.DomainId, hostName, DnsRecordType.A, hostedSharePointSettings["RootWebApplicationIpAddress"], 0, 0, 0, 0);
var ip = hostedSharePointSettings["RootWebApplicationIpAddress"];
var type2 = ip.Contains(":") ? DnsRecordType.AAAA : DnsRecordType.A;
ServerController.AddDnsZoneRecord(domain.DomainId, String.Empty, type2, ip, 0);
} }
} }
@ -411,7 +416,26 @@ namespace WebsitePanel.EnterpriseServer.Code.SharePoint
DomainInfo domain = ServerController.GetDomain(domainName); DomainInfo domain = ServerController.GetDomain(domainName);
if (domain != null) if (domain != null)
{ {
ServerController.DeleteDnsZoneRecord(domain.DomainId, hostName, DnsRecordType.A, hostedSharePointSettings["RootWebApplicationIpAddress"]); var ip = hostedSharePointSettings["RootWebApplicationIpAddress"];
var type = ip.Contains(":") ? DnsRecordType.AAAA : DnsRecordType.A;
ServerController.DeleteDnsZoneRecord(domain.DomainId, String.Empty, type, ip);
ServerController.DeleteDnsZoneRecord(domain.DomainId, "www", type, ip);
if (!String.IsNullOrEmpty(domain.WebSiteName))
{
DnsRecord[] records = ServerController.GetDnsZoneRecords(domain.DomainId);
foreach (DnsRecord record in records)
{
type = record.RecordType;
if ((type == DnsRecordType.A || type == DnsRecordType.AAAA) && record.RecordName.Equals("www", StringComparison.CurrentCultureIgnoreCase))
{
ServerController.AddDnsZoneRecord(domain.DomainId, String.Empty, DnsRecordType.A,
record.RecordData, 0);
break;
}
}
}
} }
} }

View file

@ -2969,14 +2969,16 @@ namespace WebsitePanel.EnterpriseServer
{ {
// custom format // custom format
nic.NetworkFormat = settings["PrivateIPAddress"]; nic.NetworkFormat = settings["PrivateIPAddress"];
nic.SubnetMask = GetPrivateNetworkSubnetMask(settings["PrivateSubnetMask"]); var v6 = IPAddress.Parse(nic.NetworkFormat).V6;
nic.SubnetMask = GetPrivateNetworkSubnetMask(settings["PrivateSubnetMask"], v6);
} }
else else
{ {
// standard format // standard format
string[] formatPair = settings["PrivateNetworkFormat"].Split('/'); string[] formatPair = settings["PrivateNetworkFormat"].Split('/');
nic.NetworkFormat = formatPair[0]; nic.NetworkFormat = formatPair[0];
nic.SubnetMask = GetPrivateNetworkSubnetMask(formatPair[1]); var v6 = IPAddress.Parse(nic.NetworkFormat).V6;
nic.SubnetMask = GetPrivateNetworkSubnetMask(formatPair[1], v6);
} }
nic.SubnetMaskCidr = GetSubnetMaskCidr(nic.SubnetMask); nic.SubnetMaskCidr = GetSubnetMaskCidr(nic.SubnetMask);
@ -3038,7 +3040,7 @@ namespace WebsitePanel.EnterpriseServer
List<PrivateIPAddress> ips = GetPackagePrivateIPAddresses(vm.PackageId); List<PrivateIPAddress> ips = GetPackagePrivateIPAddresses(vm.PackageId);
// sort them // sort them
SortedList<long, string> sortedIps = GetSortedNormalizedIPAddresses(ips, nic.SubnetMask); SortedList<IPAddress, string> sortedIps = GetSortedNormalizedIPAddresses(ips, nic.SubnetMask);
if (selectRandom) if (selectRandom)
{ {
@ -3209,14 +3211,14 @@ namespace WebsitePanel.EnterpriseServer
return res; return res;
} }
private static string GenerateNextAvailablePrivateIP(SortedList<long, string> ips, string subnetMask, string startIPAddress) private static string GenerateNextAvailablePrivateIP(SortedList<IPAddress, string> ips, string subnetMask, string startIPAddress)
{ {
// start IP address // start IP address
long startIp = ServerController.ConvertIPToLong(startIPAddress); var startIp = IPAddress.Parse(startIPAddress);
long mask = ServerController.ConvertIPToLong(subnetMask); var mask = IPAddress.Parse(subnetMask);
long lastAddress = (startIp & ~mask) - 1; var lastAddress = (startIp & ~mask) - 1;
foreach (long addr in ips.Keys) foreach (var addr in ips.Keys)
{ {
if ((addr - lastAddress) > 1) if ((addr - lastAddress) > 1)
{ {
@ -3229,11 +3231,11 @@ namespace WebsitePanel.EnterpriseServer
} }
} }
long genAddr = lastAddress + 1; var genAddr = lastAddress + 1;
// convert to IP address // convert to IP address
long ip = startIp & mask | (uint)genAddr; var ip = startIp & mask | genAddr;
string genIP = ServerController.ConvertLongToIP(ip); string genIP = ip.ToString();
// store in cache // store in cache
ips.Add(genAddr, genIP); ips.Add(genAddr, genIP);
@ -3241,46 +3243,44 @@ namespace WebsitePanel.EnterpriseServer
return genIP; return genIP;
} }
private static SortedList<long, string> GetSortedNormalizedIPAddresses(List<PrivateIPAddress> ips, string subnetMask) private static SortedList<IPAddress, string> GetSortedNormalizedIPAddresses(List<PrivateIPAddress> ips, string subnetMask)
{ {
long mask = ServerController.ConvertIPToLong(subnetMask); var mask = IPAddress.Parse(subnetMask);
SortedList<long, string> sortedIps = new SortedList<long, string>(); SortedList<IPAddress, string> sortedIps = new SortedList<IPAddress, string>();
foreach (PrivateIPAddress ip in ips) foreach (PrivateIPAddress ip in ips)
{ {
long addr = ~mask & ServerController.ConvertIPToLong(ip.IPAddress); var addr = ~mask & IPAddress.Parse(ip.IPAddress);
sortedIps.Add(addr, ip.IPAddress); sortedIps.Add(addr, ip.IPAddress);
} }
return sortedIps; return sortedIps;
} }
private static string GetPrivateNetworkSubnetMask(string cidr) private static string GetPrivateNetworkSubnetMask(string cidr, bool v6) {
{ if (v6) return "/" + cidr;
int digits = 32 - Utils.ParseInt(cidr, 0); else return IPAddress.Parse("/" + cidr).ToV4MaskString();
long mask = 0xFFFFFFFF;
mask = mask << digits;
return ServerController.ConvertLongToIP(mask);
} }
private static string GetSubnetMaskCidr(string subnetMask) private static string GetSubnetMaskCidr(string subnetMask) {
{
if (String.IsNullOrEmpty(subnetMask)) if (String.IsNullOrEmpty(subnetMask))
return subnetMask; return subnetMask;
var ip = IPAddress.Parse(subnetMask);
if (ip.V4) {
int cidr = 32; int cidr = 32;
long mask = ServerController.ConvertIPToLong(subnetMask); long mask = (long)ip.Address;
while ((mask & 1) == 0 && cidr > 0) while ((mask & 1) == 0 && cidr > 0) {
{
mask >>= 1; mask >>= 1;
cidr -= 1; cidr -= 1;
} }
return cidr.ToString(); return cidr.ToString();
} else {
return ip.Cidr.ToString();
}
} }
private static bool CheckPrivateIPAddress(string subnetMask, string ipAddress) private static bool CheckPrivateIPAddress(string subnetMask, string ipAddress)
{ {
long mask = ServerController.ConvertIPToLong(subnetMask); var mask = IPAddress.Parse(subnetMask);
long ip = ServerController.ConvertIPToLong(ipAddress); var ip = IPAddress.Parse(ipAddress);
return ((mask & ip) == mask); return ((mask & ip) == mask);
} }

View file

@ -3019,14 +3019,16 @@ namespace WebsitePanel.EnterpriseServer
{ {
// custom format // custom format
nic.NetworkFormat = settings["PrivateIPAddress"]; nic.NetworkFormat = settings["PrivateIPAddress"];
nic.SubnetMask = GetPrivateNetworkSubnetMask(settings["PrivateSubnetMask"]); var v6 = IPAddress.Parse(nic.NetworkFormat).V6;
nic.SubnetMask = GetPrivateNetworkSubnetMask(settings["PrivateSubnetMask"], v6);
} }
else else
{ {
// standard format // standard format
string[] formatPair = settings["PrivateNetworkFormat"].Split('/'); string[] formatPair = settings["PrivateNetworkFormat"].Split('/');
nic.NetworkFormat = formatPair[0]; nic.NetworkFormat = formatPair[0];
nic.SubnetMask = GetPrivateNetworkSubnetMask(formatPair[1]); var v6 = IPAddress.Parse(nic.NetworkFormat).V6;
nic.SubnetMask = GetPrivateNetworkSubnetMask(formatPair[1], v6);
} }
nic.SubnetMaskCidr = GetSubnetMaskCidr(nic.SubnetMask); nic.SubnetMaskCidr = GetSubnetMaskCidr(nic.SubnetMask);
@ -3088,7 +3090,7 @@ namespace WebsitePanel.EnterpriseServer
List<PrivateIPAddress> ips = GetPackagePrivateIPAddresses(vm.PackageId); List<PrivateIPAddress> ips = GetPackagePrivateIPAddresses(vm.PackageId);
// sort them // sort them
SortedList<long, string> sortedIps = GetSortedNormalizedIPAddresses(ips, nic.SubnetMask); SortedList<IPAddress, string> sortedIps = GetSortedNormalizedIPAddresses(ips, nic.SubnetMask);
if (selectRandom) if (selectRandom)
{ {
@ -3259,14 +3261,14 @@ namespace WebsitePanel.EnterpriseServer
return res; return res;
} }
private static string GenerateNextAvailablePrivateIP(SortedList<long, string> ips, string subnetMask, string startIPAddress) private static string GenerateNextAvailablePrivateIP(SortedList<IPAddress, string> ips, string subnetMask, string startIPAddress)
{ {
// start IP address // start IP address
long startIp = ServerController.ConvertIPToLong(startIPAddress); var startIp = IPAddress.Parse(startIPAddress);
long mask = ServerController.ConvertIPToLong(subnetMask); var mask = IPAddress.Parse(subnetMask);
long lastAddress = (startIp & ~mask) - 1; var lastAddress = (startIp & ~mask) - 1;
foreach (long addr in ips.Keys) foreach (var addr in ips.Keys)
{ {
if ((addr - lastAddress) > 1) if ((addr - lastAddress) > 1)
{ {
@ -3279,11 +3281,11 @@ namespace WebsitePanel.EnterpriseServer
} }
} }
long genAddr = lastAddress + 1; var genAddr = lastAddress + 1;
// convert to IP address // convert to IP address
long ip = startIp & mask | (uint)genAddr; var ip = startIp & mask | genAddr;
string genIP = ServerController.ConvertLongToIP(ip); string genIP = ip.ToString();
// store in cache // store in cache
ips.Add(genAddr, genIP); ips.Add(genAddr, genIP);
@ -3291,46 +3293,45 @@ namespace WebsitePanel.EnterpriseServer
return genIP; return genIP;
} }
private static SortedList<long, string> GetSortedNormalizedIPAddresses(List<PrivateIPAddress> ips, string subnetMask) private static SortedList<IPAddress, string> GetSortedNormalizedIPAddresses(List<PrivateIPAddress> ips, string subnetMask)
{ {
long mask = ServerController.ConvertIPToLong(subnetMask); var mask = IPAddress.Parse(subnetMask);
SortedList<long, string> sortedIps = new SortedList<long, string>(); SortedList<IPAddress, string> sortedIps = new SortedList<IPAddress, string>();
foreach (PrivateIPAddress ip in ips) foreach (PrivateIPAddress ip in ips)
{ {
long addr = ~mask & ServerController.ConvertIPToLong(ip.IPAddress); var addr = ~mask & IPAddress.Parse(ip.IPAddress);
sortedIps.Add(addr, ip.IPAddress); sortedIps.Add(addr, ip.IPAddress);
} }
return sortedIps; return sortedIps;
} }
private static string GetPrivateNetworkSubnetMask(string cidr) private static string GetPrivateNetworkSubnetMask(string cidr, bool v6)
{ {
int digits = 32 - Utils.ParseInt(cidr, 0); if (v6) return "/" + cidr;
else return IPAddress.Parse("/" + cidr).ToV4MaskString();
long mask = 0xFFFFFFFF;
mask = mask << digits;
return ServerController.ConvertLongToIP(mask);
} }
private static string GetSubnetMaskCidr(string subnetMask) private static string GetSubnetMaskCidr(string subnetMask) {
{
if (String.IsNullOrEmpty(subnetMask)) if (String.IsNullOrEmpty(subnetMask))
return subnetMask; return subnetMask;
var ip = IPAddress.Parse(subnetMask);
if (ip.V4) {
int cidr = 32; int cidr = 32;
long mask = ServerController.ConvertIPToLong(subnetMask); long mask = (long)ip.Address;
while ((mask & 1) == 0 && cidr > 0) while ((mask & 1) == 0 && cidr > 0) {
{
mask >>= 1; mask >>= 1;
cidr -= 1; cidr -= 1;
} }
return cidr.ToString(); return cidr.ToString();
} else {
return ip.Cidr.ToString();
}
} }
private static bool CheckPrivateIPAddress(string subnetMask, string ipAddress) private static bool CheckPrivateIPAddress(string subnetMask, string ipAddress)
{ {
long mask = ServerController.ConvertIPToLong(subnetMask); var mask = IPAddress.Parse(subnetMask);
long ip = ServerController.ConvertIPToLong(ipAddress); var ip = IPAddress.Parse(ipAddress);
return ((mask & ip) == mask); return ((mask & ip) == mask);
} }

View file

@ -603,11 +603,12 @@ namespace WebsitePanel.EnterpriseServer
private static void FillWebServerBindings(List<ServerBinding> bindings, List<GlobalDnsRecord> dnsRecords, private static void FillWebServerBindings(List<ServerBinding> bindings, List<GlobalDnsRecord> dnsRecords,
string ipAddr, string domainName) string ipAddr, string domainName)
// TODO test if IPv6 works
{ {
int bindingsCount = bindings.Count; int bindingsCount = bindings.Count;
foreach (GlobalDnsRecord dnsRecord in dnsRecords) foreach (GlobalDnsRecord dnsRecord in dnsRecords)
{ {
if (dnsRecord.RecordType == "A" && if ((dnsRecord.RecordType == "A" || dnsRecord.RecordType == "AAAA") &&
dnsRecord.RecordName != "*") dnsRecord.RecordName != "*")
{ {
string recordData = dnsRecord.RecordName + string recordData = dnsRecord.RecordName +

View file

@ -18,7 +18,7 @@
</UpgradeBackupLocation> </UpgradeBackupLocation>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile /> <TargetFrameworkProfile />
<UseIISExpress>false</UseIISExpress> <UseIISExpress>true</UseIISExpress>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@ -124,6 +124,8 @@
<Compile Include="Code\Common\FileUtils.cs"> <Compile Include="Code\Common\FileUtils.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="Code\Common\Int128.cs" />
<Compile Include="Code\Common\IPAddress.cs" />
<Compile Include="Code\Common\MailHelper.cs" /> <Compile Include="Code\Common\MailHelper.cs" />
<Compile Include="Code\Common\ObjectUtils.cs" /> <Compile Include="Code\Common\ObjectUtils.cs" />
<Compile Include="Code\Common\SecurityContext.cs" /> <Compile Include="Code\Common\SecurityContext.cs" />
@ -424,12 +426,11 @@
<VisualStudio> <VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}"> <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties> <WebProjectProperties>
<UseIIS>False</UseIIS> <UseIIS>True</UseIIS>
<AutoAssignPort>False</AutoAssignPort> <AutoAssignPort>False</AutoAssignPort>
<DevelopmentServerPort>9005</DevelopmentServerPort> <DevelopmentServerPort>9005</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath> <DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl> <IISUrl>http://localhost:9005/</IISUrl>
</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication> <NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer> <UseCustomServer>False</UseCustomServer>
<CustomServerUrl> <CustomServerUrl>

View file

@ -35,6 +35,7 @@ namespace WebsitePanel.Providers.DNS
public enum DnsRecordType public enum DnsRecordType
{ {
A, A,
AAAA,
NS, NS,
MX, MX,
CNAME, CNAME,

View file

@ -267,6 +267,8 @@ namespace WebsitePanel.Providers.DNS
{ {
if (record.RecordType == DnsRecordType.A) if (record.RecordType == DnsRecordType.A)
AddARecord(zoneName, record.RecordName, record.RecordData); AddARecord(zoneName, record.RecordName, record.RecordData);
else if (record.RecordType == DnsRecordType.AAAA)
AddAAAARecord(zoneName, record.RecordName, record.RecordData);
else if (record.RecordType == DnsRecordType.CNAME) else if (record.RecordType == DnsRecordType.CNAME)
AddCNameRecord(zoneName, record.RecordName, record.RecordData); AddCNameRecord(zoneName, record.RecordName, record.RecordData);
else if (record.RecordType == DnsRecordType.MX) else if (record.RecordType == DnsRecordType.MX)
@ -293,7 +295,7 @@ namespace WebsitePanel.Providers.DNS
{ {
try try
{ {
if (record.RecordType == DnsRecordType.A || record.RecordType == DnsRecordType.CNAME) if (record.RecordType == DnsRecordType.A || record.RecordType == DnsRecordType.AAAA || record.RecordType == DnsRecordType.CNAME)
record.RecordName = CorrectRecordName(zoneName, record.RecordName); record.RecordName = CorrectRecordName(zoneName, record.RecordName);
// delete record // delete record
@ -377,6 +379,36 @@ namespace WebsitePanel.Providers.DNS
#endregion #endregion
#region AAAA records
private void AddAAAARecord(string zoneName, string host, string ip) {
// get all zone records
List<DnsRecord> records = GetZoneRecordsArrayList(zoneName);
// delete A record
//DeleteARecordInternal(records, zoneName, host);
//check if user tries to add existent zone record
foreach (DnsRecord dnsRecord in records) {
if ((String.Compare(dnsRecord.RecordName, host, StringComparison.OrdinalIgnoreCase) == 0)
&& (String.Compare(dnsRecord.RecordData, ip, StringComparison.OrdinalIgnoreCase) == 0)
)
return;
}
// add new A record
DnsRecord record = new DnsRecord();
record.RecordType = DnsRecordType.AAAA;
record.RecordName = host;
record.RecordData = ip;
records.Add(record);
// update zone
UpdateZone(zoneName, records);
}
#endregion
#region NS records #region NS records
private void AddNsRecord(string zoneName, string host, string nameServer) private void AddNsRecord(string zoneName, string host, string nameServer)
{ {
@ -630,6 +662,15 @@ namespace WebsitePanel.Providers.DNS
r.RecordText = zfLine; r.RecordText = zfLine;
records.Add(r); records.Add(r);
} }
else if (recordType == "AAAA") // A record
{
DnsRecord r = new DnsRecord();
r.RecordType = DnsRecordType.AAAA;
r.RecordName = CorrectRecordName(zoneName, recordName);
r.RecordData = recordData;
r.RecordText = zfLine;
records.Add(r);
}
else if (recordType == "CNAME") // CNAME record else if (recordType == "CNAME") // CNAME record
{ {
DnsRecord r = new DnsRecord(); DnsRecord r = new DnsRecord();
@ -728,6 +769,12 @@ namespace WebsitePanel.Providers.DNS
host = rr.RecordName; host = rr.RecordName;
data = rr.RecordData; data = rr.RecordData;
} }
else if (rr.RecordType == DnsRecordType.AAAA)
{
type = "AAAA";
host = rr.RecordName;
data = rr.RecordData;
}
else if (rr.RecordType == DnsRecordType.NS) else if (rr.RecordType == DnsRecordType.NS)
{ {
type = "NS"; type = "NS";

View file

@ -130,6 +130,8 @@ namespace WebsitePanel.Providers.DNS
ManagementObjectCollection rrsA = wmi.GetWmiObjects("MicrosoftDNS_AType", "DomainName='{0}'", zoneName); ManagementObjectCollection rrsA = wmi.GetWmiObjects("MicrosoftDNS_AType", "DomainName='{0}'", zoneName);
ManagementObjectCollection rrsAAAA = wmi.GetWmiObjects("MicrosoftDNS_AAAAType", "DomainName='{0}'", zoneName);
ManagementObjectCollection rrsCNAME = wmi.GetWmiObjects("MicrosoftDNS_CNAMEType", "DomainName='{0}'", zoneName); ManagementObjectCollection rrsCNAME = wmi.GetWmiObjects("MicrosoftDNS_CNAMEType", "DomainName='{0}'", zoneName);
ManagementObjectCollection rrsMX = wmi.GetWmiObjects("MicrosoftDNS_MXType", "DomainName='{0}'", zoneName); ManagementObjectCollection rrsMX = wmi.GetWmiObjects("MicrosoftDNS_MXType", "DomainName='{0}'", zoneName);
@ -158,6 +160,14 @@ namespace WebsitePanel.Providers.DNS
records.Add(record); records.Add(record);
} }
foreach (ManagementObject rr in rrsAAAA) {
record = new DnsRecord();
record.RecordType = DnsRecordType.AAAA;
record.RecordName = CorrectHost(zoneName, (string)rr.Properties["OwnerName"].Value);
record.RecordData = (string)rr.Properties["RecordData"].Value;
records.Add(record);
}
foreach (ManagementObject rr in rrsCNAME) foreach (ManagementObject rr in rrsCNAME)
{ {
record = new DnsRecord(); record = new DnsRecord();
@ -448,6 +458,8 @@ namespace WebsitePanel.Providers.DNS
{ {
if (record.RecordType == DnsRecordType.A) if (record.RecordType == DnsRecordType.A)
AddARecord(zoneName, record.RecordName, record.RecordData); AddARecord(zoneName, record.RecordName, record.RecordData);
else if (record.RecordType == DnsRecordType.AAAA)
AddAAAARecord(zoneName, record.RecordName, record.RecordData);
else if (record.RecordType == DnsRecordType.CNAME) else if (record.RecordType == DnsRecordType.CNAME)
AddCNameRecord(zoneName, record.RecordName, record.RecordData); AddCNameRecord(zoneName, record.RecordName, record.RecordData);
else if (record.RecordType == DnsRecordType.MX) else if (record.RecordType == DnsRecordType.MX)
@ -481,6 +493,8 @@ namespace WebsitePanel.Providers.DNS
{ {
if (record.RecordType == DnsRecordType.A) if (record.RecordType == DnsRecordType.A)
DeleteARecord(zoneName, record.RecordName, record.RecordData); DeleteARecord(zoneName, record.RecordName, record.RecordData);
else if (record.RecordType == DnsRecordType.AAAA)
DeleteAAAARecord(zoneName, record.RecordName, record.RecordData);
else if (record.RecordType == DnsRecordType.CNAME) else if (record.RecordType == DnsRecordType.CNAME)
DeleteCNameRecord(zoneName, record.RecordName, record.RecordData); DeleteCNameRecord(zoneName, record.RecordName, record.RecordData);
else if (record.RecordType == DnsRecordType.MX) else if (record.RecordType == DnsRecordType.MX)
@ -689,6 +703,57 @@ namespace WebsitePanel.Providers.DNS
} }
#endregion #endregion
#region AAAA Record
/// <summary>
///
/// </summary>
/// <param name="zoneName"></param>
/// <param name="host"></param>
/// <param name="ip"></param>
/// <remarks>Supports managed resources disposal</remarks>
private void AddAAAARecord(string zoneName, string host, string ip) {
// add record
using (ManagementClass clsRR = wmi.GetClass("MicrosoftDNS_AAAAType")) {
clsRR.InvokeMethod("CreateInstanceFromPropertyData", new object[] {
GetDnsServerName(),
zoneName,
CorrectHostName(zoneName, host),
1,
MinimumTTL,
ip
});
}
// update SOA record
if (bulkRecords) return;
UpdateSoaRecord(zoneName);
}
/// <summary>
/// Supports managed resources disposal
/// </summary>
/// <param name="zoneName"></param>
/// <param name="host"></param>
/// <param name="ip"></param>
private void DeleteAAAARecord(string zoneName, string host, string ip) {
string query = String.Format("SELECT * FROM MicrosoftDNS_AAAAType " +
"WHERE ContainerName = '{0}' AND OwnerName = '{1}'",
zoneName, CorrectHostName(zoneName, host));
if (ip != null)
query += String.Format(" AND RecordData = '{0}'", ip);
using (ManagementObjectCollection objRRs = wmi.ExecuteQuery(query)) {
foreach (ManagementObject objRR in objRRs) using (objRR)
objRR.Delete();
}
// update SOA record
UpdateSoaRecord(zoneName);
}
#endregion
#region CNAME Record #region CNAME Record
/// <summary> /// <summary>
/// ///

View file

@ -101,6 +101,9 @@ namespace WebsitePanel.Providers.DNS
case "A": case "A":
dnsRecord.RecordType = DnsRecordType.A; dnsRecord.RecordType = DnsRecordType.A;
break; break;
case "AAAA":
dnsRecord.RecordType = DnsRecordType.AAAA;
break;
case "MX": case "MX":
dnsRecord.RecordType = DnsRecordType.MX; dnsRecord.RecordType = DnsRecordType.MX;
break; break;

View file

@ -1058,6 +1058,10 @@ namespace WebsitePanel.Providers.DNS
{ {
case "A": case "A":
result = DnsRecordType.A; result = DnsRecordType.A;
break;
case "AAAA":
result = DnsRecordType.AAAA;
break; break;
case "CNAME": case "CNAME":
@ -1098,6 +1102,10 @@ namespace WebsitePanel.Providers.DNS
result = "A"; result = "A";
break; break;
case DnsRecordType.AAAA:
result = "AAAA";
break;
case DnsRecordType.CNAME: case DnsRecordType.CNAME:
result = "CNAME"; result = "CNAME";
break; break;

View file

@ -190,6 +190,8 @@ namespace WebsitePanel.Providers.DNS
{ {
if (record.RecordType == DnsRecordType.A) if (record.RecordType == DnsRecordType.A)
AddARecord(zoneName, record.RecordName, record.RecordData); AddARecord(zoneName, record.RecordName, record.RecordData);
else if (record.RecordType == DnsRecordType.AAAA)
AddAAAARecord(zoneName, record.RecordName, record.RecordData);
else if (record.RecordType == DnsRecordType.CNAME) else if (record.RecordType == DnsRecordType.CNAME)
AddCNameRecord(zoneName, record.RecordName, record.RecordData); AddCNameRecord(zoneName, record.RecordName, record.RecordData);
else if (record.RecordType == DnsRecordType.MX) else if (record.RecordType == DnsRecordType.MX)
@ -225,7 +227,7 @@ namespace WebsitePanel.Providers.DNS
{ {
try try
{ {
if (record.RecordType == DnsRecordType.A || record.RecordType == DnsRecordType.CNAME) if (record.RecordType == DnsRecordType.A || record.RecordType == DnsRecordType.AAAA || record.RecordType == DnsRecordType.CNAME)
record.RecordName = CorrectRecordName(zoneName, record.RecordName); record.RecordName = CorrectRecordName(zoneName, record.RecordName);
// delete record // delete record
@ -254,7 +256,7 @@ namespace WebsitePanel.Providers.DNS
} }
#endregion #endregion
#region A records #region A & AAAA records
private void AddARecord(string zoneName, string host, string ip) private void AddARecord(string zoneName, string host, string ip)
{ {
// get all zone records // get all zone records
@ -285,6 +287,34 @@ namespace WebsitePanel.Providers.DNS
UpdateZone(zoneName, records); UpdateZone(zoneName, records);
} }
private void AddAAAARecord(string zoneName, string host, string ip) {
// get all zone records
List<DnsRecord> records = GetZoneRecordsArrayList(zoneName);
// delete AAAA record
//DeleteARecordInternal(records, zoneName, host);
//check if user tries to add existent zone record
foreach (DnsRecord dnsRecord in records) {
if ((String.Compare(dnsRecord.RecordName, host, StringComparison.OrdinalIgnoreCase) == 0)
&& (String.Compare(dnsRecord.RecordData, ip, StringComparison.OrdinalIgnoreCase) == 0)
)
return;
}
// add new AAAA record
DnsRecord record = new DnsRecord();
record.RecordType = DnsRecordType.AAAA;
record.RecordName = host;
record.RecordData = ip;
records.Add(record);
// update zone
UpdateZone(zoneName, records);
}
private void DeleteRecord(string zoneName, DnsRecordType recordType, private void DeleteRecord(string zoneName, DnsRecordType recordType,
string recordName, string recordData) string recordName, string recordData)
{ {
@ -576,6 +606,15 @@ namespace WebsitePanel.Providers.DNS
r.RecordText = zfLine; r.RecordText = zfLine;
records.Add(r); records.Add(r);
} }
else if (recordType == "AAAA") // A record
{
DnsRecord r = new DnsRecord();
r.RecordType = DnsRecordType.AAAA;
r.RecordName = CorrectRecordName(zoneName, recordName);
r.RecordData = recordData;
r.RecordText = zfLine;
records.Add(r);
}
else if (recordType == "CNAME") // CNAME record else if (recordType == "CNAME") // CNAME record
{ {
DnsRecord r = new DnsRecord(); DnsRecord r = new DnsRecord();
@ -696,6 +735,12 @@ namespace WebsitePanel.Providers.DNS
data = rr.RecordData; data = rr.RecordData;
name = BuildRecordName(zoneName, host); name = BuildRecordName(zoneName, host);
} }
else if (rr.RecordType == DnsRecordType.AAAA) {
type = "AAAA";
host = rr.RecordName;
data = rr.RecordData;
name = BuildRecordName(zoneName, host);
}
else if (rr.RecordType == DnsRecordType.NS) else if (rr.RecordType == DnsRecordType.NS)
{ {
type = "NS"; type = "NS";

View file

@ -89,6 +89,8 @@ namespace WebsitePanel.Providers.DNS
{ {
// A record // A record
{ DnsRecordType.A, new BuildDnsRecordDataEventHandler(BuildRecordData_ARecord) }, { DnsRecordType.A, new BuildDnsRecordDataEventHandler(BuildRecordData_ARecord) },
// AAAA record
{ DnsRecordType.AAAA, new BuildDnsRecordDataEventHandler(BuildRecordData_AAAARecord) },
// NS record // NS record
{ DnsRecordType.NS, new BuildDnsRecordDataEventHandler(BuildRecordData_NSRecord) }, { DnsRecordType.NS, new BuildDnsRecordDataEventHandler(BuildRecordData_NSRecord) },
// CNAME // CNAME
@ -148,6 +150,13 @@ namespace WebsitePanel.Providers.DNS
RecordData = record.DataFields[0] RecordData = record.DataFields[0]
}; };
break; break;
case "AAAA":
dnsRecord = new DnsRecord {
RecordName = recordName,
RecordType = DnsRecordType.AAAA,
RecordData = record.DataFields[0]
};
break;
case "NS": case "NS":
dnsRecord = new DnsRecord dnsRecord = new DnsRecord
{ {
@ -531,6 +540,12 @@ namespace WebsitePanel.Providers.DNS
// //
dnsZone.Records.Add(m_strRecordName, "A", rr.RecordData); dnsZone.Records.Add(m_strRecordName, "A", rr.RecordData);
break; break;
case DnsRecordType.AAAA:
// cleanup DNS record if exists
dnsZone.Records.Remove(m_strRecordName, "AAAA");
//
dnsZone.Records.Add(m_strRecordName, "AAAA", rr.RecordData);
break;
case DnsRecordType.NS: case DnsRecordType.NS:
// cleanup DNS record if exists // cleanup DNS record if exists
dnsZone.Records.Remove(m_strRecordName, "NS"); dnsZone.Records.Remove(m_strRecordName, "NS");
@ -583,6 +598,8 @@ namespace WebsitePanel.Providers.DNS
{ {
if (r_type == DnsRecordType.A) if (r_type == DnsRecordType.A)
return "A"; return "A";
else if (r_type == DnsRecordType.AAAA)
return "AAAA";
else if (r_type == DnsRecordType.CNAME) else if (r_type == DnsRecordType.CNAME)
return "CNAME"; return "CNAME";
else if (r_type == DnsRecordType.MX) else if (r_type == DnsRecordType.MX)
@ -610,6 +627,13 @@ namespace WebsitePanel.Providers.DNS
data.Add(record.RecordData); data.Add(record.RecordData);
} }
static void BuildRecordData_AAAARecord(string zoneName, ref string type,
DnsRecord record, List<string> data)
{
type = "AAAA";
data.Add(record.RecordData);
}
static void BuildRecordData_NSRecord(string zoneName, ref string type, static void BuildRecordData_NSRecord(string zoneName, ref string type,
DnsRecord record, List<string> data) DnsRecord record, List<string> data)
{ {

View file

@ -74,6 +74,7 @@
<td class="NormalBold"> <td class="NormalBold">
<asp:DropDownList ID="ddlRecordType" runat="server" SelectedValue='<%# Bind("RecordType") %>' CssClass="NormalTextBox" AutoPostBack="True" OnSelectedIndexChanged="ddlRecordType_SelectedIndexChanged"> <asp:DropDownList ID="ddlRecordType" runat="server" SelectedValue='<%# Bind("RecordType") %>' CssClass="NormalTextBox" AutoPostBack="True" OnSelectedIndexChanged="ddlRecordType_SelectedIndexChanged">
<asp:ListItem>A</asp:ListItem> <asp:ListItem>A</asp:ListItem>
<asp:ListItem>AAAA</asp:ListItem>
<asp:ListItem>MX</asp:ListItem> <asp:ListItem>MX</asp:ListItem>
<asp:ListItem>NS</asp:ListItem> <asp:ListItem>NS</asp:ListItem>
<asp:ListItem>TXT</asp:ListItem> <asp:ListItem>TXT</asp:ListItem>
@ -91,11 +92,11 @@
<tr id="rowData" runat="server"> <tr id="rowData" runat="server">
<td class="SubHead"><asp:Label ID="lblRecordData" runat="server" meta:resourcekey="lblRecordData" Text="Record Data:"></asp:Label></td> <td class="SubHead"><asp:Label ID="lblRecordData" runat="server" meta:resourcekey="lblRecordData" Text="Record Data:"></asp:Label></td>
<td class="NormalBold" nowrap> <td class="NormalBold" nowrap>
<asp:TextBox ID="txtRecordData" runat="server" Width="200px" CssClass="NormalTextBox"></asp:TextBox> <asp:TextBox ID="txtRecordData" runat="server" Width="260px" CssClass="NormalTextBox"></asp:TextBox>
<asp:RequiredFieldValidator ID="valRequireData" runat="server" ControlToValidate="txtRecordData" <asp:RequiredFieldValidator ID="valRequireData" runat="server" ControlToValidate="txtRecordData"
ErrorMessage="*" ValidationGroup="DnsZoneRecord" Display="Dynamic"></asp:RequiredFieldValidator> ErrorMessage="*" ValidationGroup="DnsZoneRecord" Display="Dynamic"></asp:RequiredFieldValidator>
<asp:regularexpressionvalidator id="IPValidator" runat="server" ValidationExpression="^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$" <asp:CustomValidator ID="IPValidator" runat="server" ControlToValidate="txtRecordData" ValidationGroup="DnsZoneRecord" Display="Dynamic" CssClass="NormalBold"
Display="Dynamic" ErrorMessage="Please enter a valid IP" ValidationGroup="DnsZoneRecord" ControlToValidate="txtRecordData" CssClass="NormalBold"></asp:regularexpressionvalidator> Text="Please enter a valid IP" OnServerValidate="Validate" meta:resourcekey="IPValidator" />
</td> </td>
</tr> </tr>
@ -104,9 +105,9 @@
<td class="NormalBold"> <td class="NormalBold">
<asp:TextBox ID="txtMXPriority" runat="server" Width="30" CssClass="NormalTextBox"></asp:TextBox> <asp:TextBox ID="txtMXPriority" runat="server" Width="30" CssClass="NormalTextBox"></asp:TextBox>
<asp:RequiredFieldValidator ID="valRequireMxPriority" runat="server" ControlToValidate="txtMXPriority" <asp:RequiredFieldValidator ID="valRequireMxPriority" runat="server" ControlToValidate="txtMXPriority"
ErrorMessage="*" ValidationGroup="DnsZoneRecord" Display="Dynamic"></asp:RequiredFieldValidator> ErrorMessage="*" ValidationGroup="DnsZoneRecord" Display="Dynamic" />
<asp:RegularExpressionValidator ID="valRequireCorrectPriority" runat="server" ControlToValidate="txtMXPriority" <asp:RegularExpressionValidator ID="valRequireCorrectPriority" runat="server" ControlToValidate="txtMXPriority"
ErrorMessage="*" ValidationExpression="\d{1,3}"></asp:RegularExpressionValidator></td> ErrorMessage="*" ValidationExpression="\d{1,3}" ValidationGroup="DnsZoneRecord" /></td>
</tr> </tr>
<tr id="rowSRVPriority" runat="server"> <tr id="rowSRVPriority" runat="server">

View file

@ -129,6 +129,10 @@ namespace WebsitePanel.Portal
lblRecordData.Text = "IP:"; lblRecordData.Text = "IP:";
IPValidator.Enabled = true; IPValidator.Enabled = true;
break; break;
case "AAAA":
lblRecordData.Text = "IP (v6):";
IPValidator.Enabled = true;
break;
case "MX": case "MX":
rowMXPriority.Visible = true; rowMXPriority.Visible = true;
break; break;
@ -142,6 +146,15 @@ namespace WebsitePanel.Portal
break; break;
} }
}
protected void Validate(object source, ServerValidateEventArgs args) {
var ip = args.Value;
System.Net.IPAddress ipaddr;
args.IsValid = System.Net.IPAddress.TryParse(ip, out ipaddr) && (ip.Contains(":") || ip.Contains(".")) &&
((ddlRecordType.SelectedValue == "A" && ipaddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) ||
(ddlRecordType.SelectedValue == "AAAA" && ipaddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6));
} }
private void SaveRecord() private void SaveRecord()

View file

@ -201,7 +201,7 @@ namespace WebsitePanel.Portal {
/// Auto-generated field. /// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file. /// To modify move field declaration from designer file to code-behind file.
/// </remarks> /// </remarks>
protected global::System.Web.UI.WebControls.RegularExpressionValidator IPValidator; protected global::System.Web.UI.WebControls.CustomValidator IPValidator;
/// <summary> /// <summary>
/// rowMXPriority control. /// rowMXPriority control.

View file

@ -116,6 +116,7 @@
<td class="NormalBold" width="100%"> <td class="NormalBold" width="100%">
<asp:DropDownList ID="ddlRecordType" runat="server" SelectedValue='<%# Bind("RecordType") %>' CssClass="NormalTextBox" AutoPostBack="True" OnSelectedIndexChanged="ddlRecordType_SelectedIndexChanged"> <asp:DropDownList ID="ddlRecordType" runat="server" SelectedValue='<%# Bind("RecordType") %>' CssClass="NormalTextBox" AutoPostBack="True" OnSelectedIndexChanged="ddlRecordType_SelectedIndexChanged">
<asp:ListItem>A</asp:ListItem> <asp:ListItem>A</asp:ListItem>
<asp:ListItem>AAAA</asp:ListItem>
<asp:ListItem>MX</asp:ListItem> <asp:ListItem>MX</asp:ListItem>
<asp:ListItem>NS</asp:ListItem> <asp:ListItem>NS</asp:ListItem>
<asp:ListItem>TXT</asp:ListItem> <asp:ListItem>TXT</asp:ListItem>
@ -133,7 +134,7 @@
<tr id="rowData" runat="server"> <tr id="rowData" runat="server">
<td class="SubHead"><asp:Label ID="lblRecordData" runat="server" meta:resourcekey="lblRecordData" Text="Record Data:"></asp:Label></td> <td class="SubHead"><asp:Label ID="lblRecordData" runat="server" meta:resourcekey="lblRecordData" Text="Record Data:"></asp:Label></td>
<td class="NormalBold" nowrap> <td class="NormalBold" nowrap>
<asp:TextBox ID="txtRecordData" runat="server" Width="200px" CssClass="NormalTextBox"></asp:TextBox> <asp:TextBox ID="txtRecordData" runat="server" Width="260px" CssClass="NormalTextBox"></asp:TextBox>
<asp:RequiredFieldValidator ID="valRequireData" runat="server" ControlToValidate="txtRecordData" <asp:RequiredFieldValidator ID="valRequireData" runat="server" ControlToValidate="txtRecordData"
ErrorMessage="*" ValidationGroup="DnsZoneRecord" Display="Dynamic"></asp:RequiredFieldValidator> ErrorMessage="*" ValidationGroup="DnsZoneRecord" Display="Dynamic"></asp:RequiredFieldValidator>
<asp:regularexpressionvalidator id="IPValidator" runat="server" ValidationExpression="^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$" <asp:regularexpressionvalidator id="IPValidator" runat="server" ValidationExpression="^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$"
@ -142,8 +143,8 @@
</tr> </tr>
<tr> <tr>
<asp:regularexpressionvalidator id="IPValidator1" runat="server" ValidationExpression="^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$" <asp:CustomValidator ID="IPValidator" runat="server" ControlToValidate="txtRecordData" ValidationGroup="DnsZoneRecord" Display="Dynamic"
Display="Dynamic" ErrorMessage="Please enter a valid IP" ValidationGroup="DnsZoneRecord" ControlToValidate="txtRecordData" CssClass="NormalBold"></asp:regularexpressionvalidator> OnServerValidate="Validate" Text="Please enter a valid IP" meta:resourcekey="IPValidator" />
</tr> </tr>
<tr id="rowMXPriority" runat="server"> <tr id="rowMXPriority" runat="server">
<td class="SubHead"><asp:Label ID="lblMXPriority" runat="server" meta:resourcekey="lblMXPriority" Text="MX Priority:"></asp:Label></td> <td class="SubHead"><asp:Label ID="lblMXPriority" runat="server" meta:resourcekey="lblMXPriority" Text="MX Priority:"></asp:Label></td>

View file

@ -140,6 +140,10 @@ namespace WebsitePanel.Portal.ExchangeServer
lblRecordData.Text = "IP:"; lblRecordData.Text = "IP:";
IPValidator.Enabled = true; IPValidator.Enabled = true;
break; break;
case "AAAA":
lblRecordData.Text = "IP (v6):";
IPValidator.Enabled = true;
break;
case "MX": case "MX":
rowMXPriority.Visible = true; rowMXPriority.Visible = true;
break; break;
@ -154,6 +158,14 @@ namespace WebsitePanel.Portal.ExchangeServer
} }
} }
protected void Validate(object source, ServerValidateEventArgs args) {
var ip = args.Value;
System.Net.IPAddress ipaddr;
args.IsValid = System.Net.IPAddress.TryParse(ip, out ipaddr) && (ip.Contains(":") || ip.Contains(".")) &&
((ddlRecordType.SelectedValue == "A" && ipaddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) ||
(ddlRecordType.SelectedValue == "AAAA" && ipaddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6));
}
private void SaveRecord() private void SaveRecord()
{ {
if (!Page.IsValid) if (!Page.IsValid)

View file

@ -238,13 +238,12 @@ namespace WebsitePanel.Portal.ExchangeServer {
protected global::System.Web.UI.WebControls.RegularExpressionValidator IPValidator; protected global::System.Web.UI.WebControls.RegularExpressionValidator IPValidator;
/// <summary> /// <summary>
/// IPValidator1 control.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Auto-generated field. /// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file. /// To modify move field declaration from designer file to code-behind file.
/// </remarks> /// </remarks>
protected global::System.Web.UI.WebControls.RegularExpressionValidator IPValidator1; protected global::System.Web.UI.WebControls.CustomValidator IPValidator;
/// <summary> /// <summary>
/// rowMXPriority control. /// rowMXPriority control.

View file

@ -35,6 +35,7 @@
<td class="Normal" width="100%"> <td class="Normal" width="100%">
<asp:DropDownList ID="ddlRecordType" runat="server" SelectedValue='<%# Bind("RecordType") %>' CssClass="NormalTextBox" AutoPostBack="True" OnSelectedIndexChanged="ddlRecordType_SelectedIndexChanged"> <asp:DropDownList ID="ddlRecordType" runat="server" SelectedValue='<%# Bind("RecordType") %>' CssClass="NormalTextBox" AutoPostBack="True" OnSelectedIndexChanged="ddlRecordType_SelectedIndexChanged">
<asp:ListItem>A</asp:ListItem> <asp:ListItem>A</asp:ListItem>
<asp:ListItem>AAAA</asp:ListItem>
<asp:ListItem>MX</asp:ListItem> <asp:ListItem>MX</asp:ListItem>
<asp:ListItem>NS</asp:ListItem> <asp:ListItem>NS</asp:ListItem>
<asp:ListItem>TXT</asp:ListItem> <asp:ListItem>TXT</asp:ListItem>
@ -52,13 +53,21 @@
<tr id="rowData" runat="server"> <tr id="rowData" runat="server">
<td class="SubHead"><asp:Label ID="lblRecordData" runat="server" meta:resourcekey="lblRecordData" Text="Record Data:"></asp:Label></td> <td class="SubHead"><asp:Label ID="lblRecordData" runat="server" meta:resourcekey="lblRecordData" Text="Record Data:"></asp:Label></td>
<td class="Normal" nowrap> <td class="Normal" nowrap>
<asp:TextBox ID="txtRecordData" runat="server" Width="200px" CssClass="NormalTextBox"></asp:TextBox><uc1:SelectIPAddress ID="ipAddress" runat="server" /> <asp:TextBox ID="txtRecordData" runat="server" Width="260px" CssClass="NormalTextBox"></asp:TextBox><uc1:SelectIPAddress ID="ipAddress" runat="server" />
<asp:RequiredFieldValidator ID="valRequireData" runat="server" ControlToValidate="txtRecordData"
ErrorMessage="*" ValidationGroup="DnsRecord" Display="Dynamic"></asp:RequiredFieldValidator>
<asp:CustomValidator ID="IPValidator" runat="server" ControlToValidate="txtRecordData" ValidationGroup="DnsRecord" Display="Dynamic" CssClass="NormalBold"
OnServerValidate="Validate" Text="Please enter a valid IP" meta:resourcekey="IPValidator"/>
</td> </td>
</tr> </tr>
<tr id="rowMXPriority" runat="server"> <tr id="rowMXPriority" runat="server">
<td class="SubHead"><asp:Label ID="lblMXPriority" runat="server" meta:resourcekey="lblMXPriority" Text="MX Priority:"></asp:Label></td> <td class="SubHead"><asp:Label ID="lblMXPriority" runat="server" meta:resourcekey="lblMXPriority" Text="MX Priority:"></asp:Label></td>
<td class="Normal"> <td class="Normal">
<asp:TextBox ID="txtMXPriority" runat="server" Width="30" CssClass="NormalTextBox"></asp:TextBox> <asp:TextBox ID="txtMXPriority" runat="server" Width="30" CssClass="NormalTextBox"></asp:TextBox>
<asp:RequiredFieldValidator ID="valRequireMxPriority" runat="server" ControlToValidate="txtMXPriority"
ErrorMessage="*" ValidationGroup="DnsRecord" Display="Dynamic"></asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="valRequireCorrectPriority" runat="server" ControlToValidate="txtMXPriority"
ErrorMessage="*" ValidationExpression="\d{1,3}" ValidationGroup="DnsRecord" />
</td> </td>
</tr> </tr>

View file

@ -144,7 +144,6 @@ namespace WebsitePanel.Portal
private void ToggleRecordControls() private void ToggleRecordControls()
{ {
rowMXPriority.Visible = false; rowMXPriority.Visible = false;
rowSRVPriority.Visible = false; rowSRVPriority.Visible = false;
rowSRVWeight.Visible = false; rowSRVWeight.Visible = false;
@ -158,6 +157,10 @@ namespace WebsitePanel.Portal
lblRecordData.Text = "IP:"; lblRecordData.Text = "IP:";
ipAddress.Visible = true; ipAddress.Visible = true;
break; break;
case "AAAA":
lblRecordData.Text = "IP (v6):";
ipAddress.Visible = true;
break;
case "MX": case "MX":
rowMXPriority.Visible = true; rowMXPriority.Visible = true;
break; break;
@ -165,15 +168,25 @@ namespace WebsitePanel.Portal
rowSRVPriority.Visible = true; rowSRVPriority.Visible = true;
rowSRVWeight.Visible = true; rowSRVWeight.Visible = true;
rowSRVPort.Visible = true; rowSRVPort.Visible = true;
lblRecordData.Text = "Host offering this service:"; lblRecordData.Text = "Host offering this service:";
break; break;
default: default:
break; break;
} }
} }
protected void Validate(object source, ServerValidateEventArgs args) {
var ip = args.Value;
System.Net.IPAddress ipaddr;
args.IsValid = System.Net.IPAddress.TryParse(ip, out ipaddr) && (ip.Contains(":") || ip.Contains(".")) &&
((ddlRecordType.SelectedValue == "A" && ipaddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) ||
(ddlRecordType.SelectedValue == "AAAA" && ipaddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6));
}
private void SaveRecord() private void SaveRecord()
{ {
if (!Page.IsValid) return;
GlobalDnsRecord record = new GlobalDnsRecord(); GlobalDnsRecord record = new GlobalDnsRecord();
record.RecordId = (int)ViewState["RecordID"]; record.RecordId = (int)ViewState["RecordID"];
record.RecordType = ddlRecordType.SelectedValue; record.RecordType = ddlRecordType.SelectedValue;

View file

@ -8,6 +8,8 @@
<asp:ValidationSummary ID="validatorsSummary" runat="server" <asp:ValidationSummary ID="validatorsSummary" runat="server"
ValidationGroup="EditAddress" ShowMessageBox="True" ShowSummary="False" /> ValidationGroup="EditAddress" ShowMessageBox="True" ShowSummary="False" />
<asp:CustomValidator ID="consistentAddresses" runat="server" ErrorMessage="You must not mix IPv4 and IPv6 addresses." ValidationGroup="EditAddress" Display="dynamic" ServerValidate="CheckIPAddresses" />
<table cellspacing="0" cellpadding="3"> <table cellspacing="0" cellpadding="3">
<tr> <tr>
<td style="width:150px;"> <td style="width:150px;">
@ -33,7 +35,7 @@
<td><asp:Localize ID="lblExternalIP" runat="server" meta:resourcekey="lblExternalIP" Text="IP Address:"></asp:Localize></td> <td><asp:Localize ID="lblExternalIP" runat="server" meta:resourcekey="lblExternalIP" Text="IP Address:"></asp:Localize></td>
<td> <td>
<wsp:EditIPAddressControl id="startIP" runat="server" ValidationGroup="EditAddress" Required="true" /> <wsp:EditIPAddressControl id="startIP" runat="server" ValidationGroup="EditAddress" Required="true" AllowSubnet="true" />
&nbsp;<asp:Localize ID="locTo" runat="server" meta:resourcekey="locTo" Text="to"></asp:Localize>&nbsp; &nbsp;<asp:Localize ID="locTo" runat="server" meta:resourcekey="locTo" Text="to"></asp:Localize>&nbsp;
@ -52,7 +54,7 @@
<tr id="SubnetRow" runat="server"> <tr id="SubnetRow" runat="server">
<td><asp:Localize ID="locSubnetMask" runat="server" meta:resourcekey="locSubnetMask" Text="Subnet Mask:"></asp:Localize></td> <td><asp:Localize ID="locSubnetMask" runat="server" meta:resourcekey="locSubnetMask" Text="Subnet Mask:"></asp:Localize></td>
<td class="NormalBold"> <td class="NormalBold">
<wsp:EditIPAddressControl id="subnetMask" runat="server" ValidationGroup="EditAddress" Required="true" /> <wsp:EditIPAddressControl id="subnetMask" runat="server" ValidationGroup="EditAddress" Required="true" AllowSubnet="true" />
</td> </td>
</tr> </tr>
<tr id="GatewayRow" runat="server"> <tr id="GatewayRow" runat="server">

View file

@ -49,6 +49,7 @@ namespace WebsitePanel.Portal
{ {
if (!IsPostBack) if (!IsPostBack)
{ {
// bind dropdowns // bind dropdowns
try try
{ {
@ -96,7 +97,7 @@ namespace WebsitePanel.Portal
string comments = txtComments.Text.Trim(); string comments = txtComments.Text.Trim();
// add ip address // add ip address
if (endIP.Text != "") if (endIP.Text != "" || startIP.Text.Contains("/"))
{ {
try try
{ {
@ -162,5 +163,12 @@ namespace WebsitePanel.Portal
SubnetRow.Visible = vps; SubnetRow.Visible = vps;
GatewayRow.Visible = vps; GatewayRow.Visible = vps;
} }
public void CheckIPAddresses(object sender, ServerValidateEventArgs args) {
startIP.Validate(sender, args);
endIP.Validate(sender, args);
subnetMask.Validate(sender, args);
args.IsValid = startIP.IsV6 == endIP.IsV6 && (startIP.IsV6 == subnetMask.IsV6 || subnetMask.IsMask);
}
} }
} }

View file

@ -1,7 +1,6 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.
// Runtime Version:2.0.50727.1434
// //
// Changes to this file may cause incorrect behavior and will be lost if // Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated. // the code is regenerated.
@ -31,6 +30,15 @@ namespace WebsitePanel.Portal {
/// </remarks> /// </remarks>
protected global::System.Web.UI.WebControls.ValidationSummary validatorsSummary; protected global::System.Web.UI.WebControls.ValidationSummary validatorsSummary;
/// <summary>
/// consistent Addresses control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.CustomValidator consistentAddresses;
/// <summary> /// <summary>
/// locPool control. /// locPool control.
/// </summary> /// </summary>

View file

@ -288,7 +288,7 @@
<td> <td>
<wsp:EditIPAddressControl id="privateIPAddress" runat="server" Required="true" /> <wsp:EditIPAddressControl id="privateIPAddress" runat="server" Required="true" />
/ /
<asp:TextBox ID="privateSubnetMask" runat="server" MaxLength="2" Width="40px" CssClass="NormalTextBox"></asp:TextBox> <asp:TextBox ID="privateSubnetMask" runat="server" MaxLength="3" Width="40px" CssClass="NormalTextBox"></asp:TextBox>
<asp:RequiredFieldValidator ID="privateSubnetMaskValidator" runat="server" ControlToValidate="privateSubnetMask" <asp:RequiredFieldValidator ID="privateSubnetMaskValidator" runat="server" ControlToValidate="privateSubnetMask"
Text="*" meta:resourcekey="privateSubnetMaskValidator" Display="Dynamic" SetFocusOnError="true" /> Text="*" meta:resourcekey="privateSubnetMaskValidator" Display="Dynamic" SetFocusOnError="true" />
</td> </td>

View file

@ -1,7 +1,6 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.
// Runtime Version:2.0.50727.4927
// //
// Changes to this file may cause incorrect behavior and will be lost if // Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated. // the code is regenerated.

View file

@ -1,8 +1,5 @@
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="EditIPAddressControl.ascx.cs" Inherits="WebsitePanel.Portal.UserControls.EditIPAddressControl" %> <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="EditIPAddressControl.ascx.cs" Inherits="WebsitePanel.Portal.UserControls.EditIPAddressControl" %>
<asp:TextBox ID="txtAddress" runat="server" Width="110px" MaxLength="15" CssClass="NormalTextBox"></asp:TextBox> <asp:TextBox ID="txtAddress" runat="server" Width="260px" MaxLength="45" CssClass="NormalTextBox"></asp:TextBox>
<asp:RequiredFieldValidator ID="requireAddressValidator" runat="server" meta:resourcekey="requireAddressValidator" <asp:RequiredFieldValidator ID="requireAddressValidator" runat="server" meta:resourcekey="requireAddressValidator"
ControlToValidate="txtAddress" SetFocusOnError="true" Text="*" Enabled="false" Display="Dynamic"> ControlToValidate="txtAddress" SetFocusOnError="true" Text="*" Enabled="false" Display="Dynamic" />
</asp:RequiredFieldValidator><asp:RegularExpressionValidator id="addressValidator" runat="server" <asp:CustomValidator ID="addressValidator" runat="server" ControlToValidate="txtAddress" OnServerValidate="Validate" Text="*" meta:resourcekey="addressValidator"/>
ValidationExpression="^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$"
Display="Dynamic" SetFocusOnError="true" ControlToValidate="txtAddress" Text="*" meta:resourcekey="addressValidator">
</asp:RegularExpressionValidator>

View file

@ -34,8 +34,16 @@ using System.Web.UI.WebControls;
namespace WebsitePanel.Portal.UserControls namespace WebsitePanel.Portal.UserControls
{ {
[Flags]
public enum IPValidationMode { V4 = 1, V6 = 2, V4AndV6 = 3 };
public partial class EditIPAddressControl : WebsitePanelControlBase public partial class EditIPAddressControl : WebsitePanelControlBase
{ {
public IPValidationMode Validation { get; set; }
public EditIPAddressControl() { Validation = IPValidationMode.V4AndV6; AllowSubnet = false; }
public bool Required public bool Required
{ {
get { return requireAddressValidator.Enabled; } get { return requireAddressValidator.Enabled; }
@ -86,5 +94,30 @@ namespace WebsitePanel.Portal.UserControls
{ {
} }
public bool AllowSubnet { get; set; }
public bool IsV6 { get; private set; }
public bool IsMask { get; private set; }
public void Validate(object source, ServerValidateEventArgs args) {
IsMask = IsV6 = false;
var ip = args.Value;
int net = 0;
if (ip.Contains("/")) {
args.IsValid = AllowSubnet;
var tokens = ip.Split('/');
ip = tokens[0];
args.IsValid &= int.TryParse(tokens[1], out net) && net <= 128;
if (string.IsNullOrEmpty(ip)) {
IsMask = true;
return;
}
}
System.Net.IPAddress ipaddr;
args.IsValid &= System.Net.IPAddress.TryParse(ip, out ipaddr) && (ip.Contains(":") || ip.Contains(".")) &&
(((Validation & IPValidationMode.V6) != 0 && (IsV6 = ipaddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)) ||
((Validation & IPValidationMode.V4) != 0 && ipaddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork));
args.IsValid &= ipaddr.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork || net < 32;
}
} }
} }

View file

@ -1,7 +1,6 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.
// Runtime Version:2.0.50727.1434
// //
// Changes to this file may cause incorrect behavior and will be lost if // Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated. // the code is regenerated.
@ -38,6 +37,6 @@ namespace WebsitePanel.Portal.UserControls {
/// Auto-generated field. /// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file. /// To modify move field declaration from designer file to code-behind file.
/// </remarks> /// </remarks>
protected global::System.Web.UI.WebControls.RegularExpressionValidator addressValidator; protected global::System.Web.UI.WebControls.CustomValidator addressValidator;
} }
} }

View file

@ -6,7 +6,6 @@
<add tagPrefix="ajaxToolkit" namespace="AjaxControlToolkit" assembly="AjaxControlToolkit"/> <add tagPrefix="ajaxToolkit" namespace="AjaxControlToolkit" assembly="AjaxControlToolkit"/>
</controls> </controls>
</pages> </pages>
<compilation targetFramework="4.0"> <compilation targetFramework="4.0" debug="true"/>
</compilation>
</system.web> </system.web>
</configuration> </configuration>