How to determine if string is an IP address? [duplicate] - c#

I have a function that returns if a given ip address is valid or not using the IPAddress class. I was testing it and it returns valid(true) even when I pass "0123456" or "11111" or "99999" without a dot as argument. I wrote it in VB.net and C# with the same result.
// C#
public bool CheckIpAddress(string ipAddr)
{
IPAddress ip = null;
return IPAddress.TryParse(ipAddr,out ip);
}
// VB.net
Public Function CheckIpAddress(ipAddr As String) As Boolean
Dim ip As IPAddress = Nothing
Return Net.IPAddress.TryParse(ipAddr, ip)
End Function
Could somebody explain me why is this happening. I have matched my code with some sources through the internet and is fine.

IP Address is just 32 bit number, so 11111 is definitely a correct IP Address. Dots in IP Address are there just to make reading them easier for humans. They are not required.
IP addresses are binary numbers, but they are usually stored in text files and displayed in human-readable notations, such as 172.16.254.1 (for IPv4), and 2001:db8:0:1234:0:567:8:1 (for IPv6).
from IP address - Wikipedia
That's why IPAddress.TryParse returns true.
It's even described on MSDN: IPAddress.Parse Method
The number of parts (each part is separated by a period) in ipString determines how the IP address is constructed. A one part address is stored directly in the network address. A two part address, convenient for specifying a class A address, puts the leading part in the first byte and the trailing part in the right-most three bytes of the network address. A three part address, convenient for specifying a class B address, puts the first part in the first byte, the second part in the second byte, and the final part in the right-most two bytes of the network address.
There is also an example (see the first one):
1 -- "65536" 0.0.255.255
2 -- "20.2" 20.0.0.2
2 -- "20.65535" 20.0.255.255
3 -- "128.1.2" 128.1.0.2

If you want to validate against a pattern, you should instead be using a RegEx.
This code should help:
Match match = Regex.Match(input, #"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$");
if (match.Success)
{
Console.WriteLine("It is a valid IP Address");
}

Since this had a vb.net tag
Public Function CheckIpAddress(ipAddr As String) As Boolean
Dim parts() As String = ipAddr.Split(New Char() {"."c}, StringSplitOptions.RemoveEmptyEntries)
Dim rv As Boolean
If parts.Length <> 4 Then
rv = False
Else
Dim anIP As Net.IPAddress
If Net.IPAddress.TryParse(ipAddr, anIP) Then
rv = True
Else
rv = False
End If
End If
Return rv
End Function

Related

Why IPAddress.Parse("192.168.001.001") works while IPAddress.Parse("192.168.001.009") don't?

I'm stuck trying to parse IP addresses from a API result where each of the four pats of the IPv4 Address comes prefixed with 0 (zeroes). Something like this:
127.000.000.001 instead of 127.0.0.1
I started getting parse errors when trying to parse 192.168.001.009. It also fails for 192.168.001.008, but works for 007, 006, 005 up to 001!!!
It also fails for 192.168.001.018, but works for .017, .016 down to 010!
It works for 192.168.001.8 or .8 and also 192.168.001.18 and .19...
Is this a bug in the CLR? Or am I missing something stupid?
Just try:
IPAddress.Parse("192.168.001.007"); // works
IPAddress.Parse("192.168.001.87"); // works
IPAddress.Parse("192.168.001.008"); // throws exception
IPAddress.Parse("192.168.001.19"); // works
IPAddress.Parse("192.168.001.019"); // throws exception
// and so on!
The numbers, since they are starting with 0, are being interpreted as octal instead of decimal. These are not C# literals, so it's up to the library to interpret it one way or another.
A simple way to test it would be to construct an IP ending in ".010", parse it, and you'll see that it was parsed as an ip ending in .8.
A possible quick and dirty solution would be to search for the regex /\.0*/ and replace it with "."
You can find more information on the wikipedia entry for Dot-decimal-notation:
A popular implementation of IP networking, originating in 4.2BSD, contains a function inet_aton() for converting IP addresses in character strings representation to internal binary storage. In addition to the basic four-decimals format and full 32-bit addresses, it also supported intermediate syntaxes of octet.24bits (e.g. 10.1234567; for Class A addresses) and octet.octet.16bits (e.g. 172.16.12345; for Class B addresses). It also allowed the numbers to be written in hexadecimal and octal, by prefixing them with 0x and 0, respectively. These features continue to be supported by software until today, even though they are seen as non-standard. But this also means addresses where an IP address component is written with a leading zero digit may be interpreted differently by different programs: some will ignore the leading zero, some will interpret the number as octal.
This is probably because 00X or 0XY are considered octal numbers which allows only digits 0 through 7. Digits 8 and 9 are an error.

Regular expression that matches all valid format IPv6 addresses

At first glance, I concede that this question looks like a duplicate of this question and any other related to it:
Regular expression that matches valid IPv6 addresses
That question in fact has an answer that nearly answers my question, but not fully.
The code from that question which I have issues with, yet had the most success with, is as shown below:
private string RemoveIPv6(string sInput)
{
string pattern = #"(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))";
//That is one looooong regex! From: https://stackoverflow.com/a/17871737/3472690
//if (IsCompressedIPv6(sInput))
// sInput = UncompressIPv6(sInput);
string output = Regex.Replace(sInput, pattern, "");
if (output.Contains("Addresses"))
output = output.Substring(0, "Addresses: ".Length);
return output;
}
The issues I had with the regex pattern as provided in this answer, David M. Syzdek's Answer, is that it doesn't match and remove the full form of the IPv6 addresses I'm throwing at it.
I'm using the regex pattern to mainly replace IPv6 addresses in strings with blanks or null value.
For instance,
Addresses: 2404:6800:4003:c02::8a
As well as...
Addresses: 2404:6800:4003:804::200e
And finally...
Addresses: 2001:4998:c:a06::2:4008
All either don't get fully matched by the regex, or failed to be completely matched.
The regex will return me the remaining parts of the string as shown below:
Addresses: 8a
Addresses: 200e
Addresses: 2:4008
As can be seen, it has left remnants of the IPv6 addresses, which is hard to detect and remove, due to the varying formats that the remnants take on. Below is the regex pattern by itself for better analysis:
(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))
Therefore, my question is, how can this regex pattern be corrected so it can match, and therefore allow the complete removal of any IPv6 addresses, from a string that doesn't solely contain the IPv6 address(es) itself?
Alternatively, how can the code snippet I provided above be corrected to provide the required outcome?
For those who may be wondering, I am getting the string from the StandardOutput of nslookup commands, and the IPv6 addresses will always differ. For the examples above, I got those IPv6 addresses from "google.com" and "yahoo.com".
I am not using the built-in function to resolve DNS entries for a good reason, which I don't think will matter for the moment, therefore I am using nslookup.
As for the code that is calling that function, if required, is as below: (It itself is also another function/method, or rather part of one)
string output = "";
string garbagecan = "";
string tempRead = "";
string lastRead = "";
using (StreamReader reader = nslookup.StandardOutput)
{
while (reader.Peek() != -1)
{
if (LinesRead > 3)
{
tempRead = reader.ReadLine();
tempRead = RemoveIPv6(tempRead);
if (tempRead.Contains("Addresses"))
output += tempRead;
else if (lastRead.Contains("Addresses"))
output += tempRead.Trim() + Environment.NewLine;
else
output += tempRead + Environment.NewLine;
lastRead = tempRead;
}
else
garbagecan = reader.ReadLine();
LinesRead++;
}
}
return output;
The corrected regex should only allow the removal of IPv6 addresses, and leave IPv4 addresses untouched. The string that will be passed to the regex will not contain the IPv6 address(es) alone, and will almost always contain other details, and as such, it is unpredictable at which index will the addresses appear. The regex is also skipping all other IPv6 addresses after the first occuring IPv6 addresses as well for some reason, it should be noted.
Apologies if there are any missing details, I will try my best to include them in when alerted. I would also prefer working code samples, if possible, as I have almost zero knowledge regarding regex.
(?:^|(?<=\s))(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))(?=\s|$)
Using lookarounds you can enforce a complete match rather than a partial match.See demo.
https://regex101.com/r/cT0hV4/5
(?i)(?<ipv6>(?:[\da-f]{0,4}:){1,7}(?:(?<ipv4>(?:(?:25[0-5]|2[0-4]\d|1?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|1?\d\d?))|[\da-f]{0,4}))
Demo: Regex101
Github Repository

Blocking mixed IPv6 formatting in System.Net.IPAddress class

I was searching an answer but I can't find it.
I am using something like this
if (IPAddress.TryParse(val, out parsedOutput))
{
// ip address
parsedOk = true;
}
I am passing as val a string which looks like this: 0:0:0:0:0:0:1111:0
I am getting in parsedOutput this: ::17.17.0.0
Is there any way to get something like this: ::1111:0 instead of this "mixed" ipv4/ipv6 value?
The notation is actually correct according to RFC 5952 (A Recommendation for IPv6 Address Text Representation). In section 5 it says:
Addresses such as IPv4-Mapped IPv6 addresses, ISATAP
[RFC5214], and IPv4-translatable
addresses
[ADDR-FORMAT]
have IPv4 addresses embedded in the low-order 32 bits of the address.
These addresses have a special representation that may mix hexadecimal
and dot decimal notations. The decimal notation may be used only for
the last 32 bits of the address. For these addresses, mixed notation
is RECOMMENDED if the following condition is met: the address can be
distinguished as having IPv4 addresses embedded in the lower 32 bits
solely from the address field through the use of a well-known prefix.
Such prefixes are defined in
[RFC4291] and
[RFC2765] at the time of this
writing.
The IPv6 address you show is an IPv4-Compatible IPv6 Address. Its use is now deprecated, but it is still an IPv6 Address with Embedded IPv4 Addresses according to RFC 4291 section 2.5.5. The parsed output is therefore correct and recommended.
Solution: It's the string you are trying to parse. IPv6 addresses must have something in the first portion of the address, so if you were to throw in something like 2000 in there like this: 2000:0:0:0:0:0:1111:0 it will parse it correctly. It has to do with the way IPv6 address are understood by the computer.

How to validate ip address in C#

I'm doing an application that uses IP address. I have to validate them to start from at least 1.0.0.1 but with the codes below it accepts 0.0.0.0:
\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b
I also tried changing it to:
\b(25[0-5]|2[0-4][0-9]|[01]?[1-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b
This code does not accept 0.0.0.0 but does not accept 100.0.0.0 to 109.0.0.0 either.
Can someone help?
Use
IPAddress addr = IPAddress.TryParse(str);
Then, if that worked get the numbers using
addr.GetAddressBytes();
and then check the byte values for the correct conditions using normal if-cases.
Save yourself the pain! Convert to a string, split on the dot character and check whether each of the 4 segments is in the range 0 or 1 to 255.
Otherwise if you use RegexBuddy (which is a fantastic app for RegEx) it has a bunch of IP address examples in the Library inc for 0.0.0.0 to 255.255.255.255:
\b(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\b
Try using this,
ValidIpAddressRegex = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$";

IP address parsing in .NET

I'm using IPAddress.TryParse() to parse IP addresses. However, it's a little too permissive (parsing "1" returns 0.0.0.1). I'd like to limit the input to dotted octet notation. What's the best way to do this?
(Note: I'm using .NET 2.0)
Edit
Let me clarify:
I'm writing an app that will scan a range of IPs looking for certain devices (basically a port scanner). When the user enters "192.168.0.1" for the starting address, I want to automatically fill in "192.168.0.255" as the ending address. The problem is that when they type "1", it parses as "0.0.0.1" and the ending address fills in as "0.0.0.255" - which looks goofy.
If you are interested in parsing the format, then I'd use a regular expression. Here's a good one (source):
bool IsDottedDecimalIP(string possibleIP)
{
Regex R = New Regex(#"\b(?:\d{1,3}\.){3}\d{1,3}\b");
return R.IsMatch(possibleIP) && Net.IPAddress.TryParse(possibleIP, null);
}
That regex doesn't catch invalid IPs but does enforce your pattern. The TryParse checks their validity.
An IP address is actually a 32 bit number - it is not xxx.xxx.xxx.xxx - that's just a human readable format for the same. So IP address 1 is actually 0.0.0.1.
EDIT: Given the clarification, you could either go with a regex as has been suggested, or you could format the short cuts to your liking, so if you want "1" to appears as "1.0.0.0". you could append that and still use the parse method.

Categories

Resources