\r
\r
using System;\r
+using System.Globalization;\r
using System.Net.Sockets;\r
using System.Runtime.InteropServices;\r
using System.Text;\r
static int Fill (ushort [] addr, string ipString)\r
{\r
int p = 0;\r
+ int pdigits = 0;\r
int slot = 0;\r
\r
if (ipString.Length == 0)\r
return 0;\r
\r
// Catch double uses of ::\r
- if (ipString.IndexOf ("::") != -1)\r
+ if (ipString.IndexOf ("::", StringComparison.Ordinal) != -1)\r
return -1;\r
\r
for (int i = 0; i < ipString.Length; i++){\r
int n;\r
\r
if (c == ':'){\r
+ // Leading : is not allowed.\r
+ if (i == 0)\r
+ return -1;\r
+ \r
// Trailing : is not allowed.\r
if (i == ipString.Length-1)\r
return -1;\r
\r
addr [slot++] = (ushort) p;\r
p = 0;\r
+ pdigits = 0;\r
continue;\r
- } if ('0' <= c && c <= '9')\r
+ }\r
+ pdigits++;\r
+ if (pdigits > 4)\r
+ return -1;\r
+ if ('0' <= c && c <= '9')\r
n = (int) (c - '0');\r
else if ('a' <= c && c <= 'f')\r
n = (int) (c - 'a' + 10);\r
\r
return slot;\r
}\r
+\r
+ static bool TryParse (string prefix, out int res)\r
+ {\r
+ return Int32.TryParse (prefix, NumberStyles.Integer, CultureInfo.InvariantCulture, out res);\r
+ }\r
\r
public static bool TryParse (string ipString, out IPv6Address result)\r
{\r
int pos = ipString.LastIndexOf ('/');\r
if (pos != -1) {\r
string prefix = ipString.Substring (pos + 1);\r
- try {\r
- prefixLen = Int32.Parse (prefix);\r
- } catch (Exception) {\r
+ if (!TryParse (prefix , out prefixLen))\r
prefixLen = -1;\r
- }\r
if (prefixLen < 0 || prefixLen > 128)\r
return false;\r
ipString = ipString.Substring (0, pos);\r
pos = ipString.LastIndexOf ('%');\r
if (pos != -1) {\r
string prefix = ipString.Substring (pos + 1);\r
- try {\r
- scopeId = Int32.Parse (prefix);\r
- } \r
- catch (Exception) {\r
+ if (!TryParse (prefix, out scopeId))\r
scopeId = 0;\r
- }\r
ipString = ipString.Substring (0, pos);\r
} \r
}\r
//\r
// Is there an ipv4 address at the end?\r
//\r
- bool ipv4 = false;\r
- int pos2 = ipString.LastIndexOf (":");\r
+ int pos2 = ipString.LastIndexOf (':');\r
if (pos2 == -1)\r
return false;\r
\r
ipString = ipString.Substring (0, pos2 + 1);\r
else\r
ipString = ipString.Substring (0, pos2);\r
- ipv4 = true;\r
slots = 2;\r
}\r
} \r
// Only an ipv6 block remains, either:\r
// "hexnumbers::hexnumbers", "hexnumbers::" or "hexnumbers"\r
//\r
- int c = ipString.IndexOf ("::");\r
+ int c = ipString.IndexOf ("::", StringComparison.Ordinal);\r
if (c != -1){\r
int right_slots = Fill (addr, ipString.Substring (c+2));\r
if (right_slots == -1){\r
return false;\r
}\r
\r
- // Now check the results in the ipv6-address range only\r
- bool ipv6 = false;\r
- for (int i = 0; i < slots; i++){\r
- if (addr [i] != 0 || i == 5 && addr [i] != 0xffff)\r
- ipv6 = true;\r
- }\r
- \r
- // check IPv4 validity\r
- if (ipv4 && !ipv6) {\r
- for (int i = 0; i < 5; i++) {\r
- if (addr [i] != 0)\r
- return false;\r
- }\r
-\r
- if (addr [5] != 0 && addr [5] != 0xffff)\r
- return false;\r
- }\r
-\r
result = new IPv6Address (addr, prefixLen, scopeId);\r
return true;\r
}\r
}\r
\r
// Convert the address into a format expected by the IPAddress (long) ctor\r
- private int AsIPv4Int ()\r
+ // This needs to be unsigned to satisfy the '> 1' test in IsIPv4Compatible()\r
+ private uint AsIPv4Int ()\r
{\r
- return (SwapUShort (address [7]) << 16) + SwapUShort (address [6]);\r
+ return (uint)(SwapUShort (address [7]) << 16) + SwapUShort (address [6]);\r
} \r
\r
public bool IsIPv4Compatible ()\r
for (int i = 0; i < 6; i++) \r
if (address [i] != 0)\r
return false;\r
+ /* MS .net only seems to format the last 4\r
+ * bytes as an IPv4 address if address[6] is\r
+ * non-zero\r
+ */\r
+ if (address[6] == 0)\r
+ return false;\r
return (AsIPv4Int () > 1);\r
}\r
\r
for (int i = 0; i < 5; i++) \r
if (address [i] != 0)\r
return false;\r
+ /* MS .net only seems to format the last 4\r
+ * bytes as an IPv4 address if address[6] is\r
+ * non-zero\r
+ */\r
+ if (address[6] == 0)\r
+ return false;\r
+ \r
return address [5] == 0xffff;\r
}\r
\r