using System; using System.Globalization; using Org.BouncyCastle.Math; namespace Org.BouncyCastle.Utilities.Net { public class IPAddress { /** * Validate the given IPv4 or IPv6 address. * * @param address the IP address as a string. * * @return true if a valid address, false otherwise */ public static bool IsValid( string address) { return IsValidIPv4(address) || IsValidIPv6(address); } /** * Validate the given IPv4 or IPv6 address and netmask. * * @param address the IP address as a string. * * @return true if a valid address with netmask, false otherwise */ public static bool IsValidWithNetMask( string address) { return IsValidIPv4WithNetmask(address) || IsValidIPv6WithNetmask(address); } /** * Validate the given IPv4 address. * * @param address the IP address as a string. * * @return true if a valid IPv4 address, false otherwise */ public static bool IsValidIPv4( string address) { try { return unsafeIsValidIPv4(address); } catch (FormatException) {} catch (OverflowException) {} return false; } private static bool unsafeIsValidIPv4( string address) { if (address.Length == 0) return false; int octets = 0; string temp = address + "."; int pos; int start = 0; while (start < temp.Length && (pos = temp.IndexOf('.', start)) > start) { if (octets == 4) return false; string octetStr = temp.Substring(start, pos - start); int octet = Int32.Parse(octetStr); if (octet < 0 || octet > 255) return false; start = pos + 1; octets++; } return octets == 4; } public static bool IsValidIPv4WithNetmask( string address) { int index = address.IndexOf('/'); string mask = address.Substring(index + 1); return (index > 0) && IsValidIPv4(address.Substring(0, index)) && (IsValidIPv4(mask) || IsMaskValue(mask, 32)); } public static bool IsValidIPv6WithNetmask( string address) { int index = address.IndexOf('/'); string mask = address.Substring(index + 1); return (index > 0) && (IsValidIPv6(address.Substring(0, index)) && (IsValidIPv6(mask) || IsMaskValue(mask, 128))); } private static bool IsMaskValue( string component, int size) { int val = Int32.Parse(component); try { return val >= 0 && val <= size; } catch (FormatException) {} catch (OverflowException) {} return false; } /** * Validate the given IPv6 address. * * @param address the IP address as a string. * * @return true if a valid IPv4 address, false otherwise */ public static bool IsValidIPv6( string address) { try { return unsafeIsValidIPv6(address); } catch (FormatException) {} catch (OverflowException) {} return false; } private static bool unsafeIsValidIPv6( string address) { if (address.Length == 0) { return false; } int octets = 0; string temp = address + ":"; bool doubleColonFound = false; int pos; int start = 0; while (start < temp.Length && (pos = temp.IndexOf(':', start)) >= start) { if (octets == 8) { return false; } if (start != pos) { string value = temp.Substring(start, pos - start); if (pos == (temp.Length - 1) && value.IndexOf('.') > 0) { if (!IsValidIPv4(value)) { return false; } octets++; // add an extra one as address covers 2 words. } else { string octetStr = temp.Substring(start, pos - start); int octet = Int32.Parse(octetStr, NumberStyles.AllowHexSpecifier); if (octet < 0 || octet > 0xffff) return false; } } else { if (pos != 1 && pos != temp.Length - 1 && doubleColonFound) { return false; } doubleColonFound = true; } start = pos + 1; octets++; } return octets == 8 || doubleColonFound; } } }