tags:

views:

5213

answers:

11

I don't need to validate that the IP address is reachable or anything like that. I just want to validate that the string is in dotted-quad (xxx.xxx.xxx.xxx) fomat, where xxx is between 0 and 255.

A: 

I've used Boost.Regex for that in the past. You can also find it in TR1.

The RE I used:

"^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{"
"2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25"
"[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$";

It's long, but it makes sure each portion is between 0 and 255. I believe I got it from regexlib.com.

Another option is to call inet_addr(), which will convert a string to an address. It will return a failure code if it's not a valid ip address.

Ferruccio
That regex will fail on base 8 or base 16 quads, unfortunately. I'd definitely go with inet_addr and stay away from regexes in this particular case.
Mihai Limbășan
yet another reason to always be very critical of those code snippets from sites like that...
rmeador
I hadn't realized you could use octal or hex in dotted-quad notation. What's the syntax?
Ferruccio
Numbers with a zero prefix are octal, unless it's 0x, then they're hex. For example 192.168.1.017 and 192.168.1.0x0F are the same address.
Bill the Lizard
A: 

Boost.Regex would be appropriate.

bool validate_ip_address(const std::string& s)
{
   static const boost::regex e("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
   return regex_match(s, e);
}
Martin Cote
Not entirely correct, because it doesn't verify that the numbers are in the valid range, but that shouldn't be too hard to fix.
Head Geek
Actually checking numbers are in a valid range is fairly complicated in regex. See Ferruccio's answer for the corrected regex.
Bill the Lizard
You could use REGEX to pull out each of the numbers, and then check each set of digits to ensure it's in the proper range. This may be more useful if you want to stop people from entering IPs that can't be accessed from the outside world such as 127.0.0.1
Kibbee
As noted in the comment on Ferrucio's regex, you must validate for base 8 and base 16 quads too.
Mihai Limbășan
A: 

You could accomplish this very easily with boost tokenizer and boost char_separator.

http://www.boost.org/doc/libs/1_37_0/libs/tokenizer/char_separator.htm

Marcin
A: 

If you wanted to write this yourself rather than use a library then

atoi() to convert characters to ints will let you test the range of each number, and some strcmp's between the "."'s. You can also do some quick checks, such as the length of the string (should be less than 16 characters (not including null terminator), number of dots. etc.

But, it's probably MUCH easier to use existing code.

xan
A: 

If you don't want the overhead of Boost or TR1 you could search for the dots and check if the characters between them are numbers from 0 to 255.

EricSchaefer
+19  A: 

You probably want the inet_pton - which returns -1 on failure, and supports both the IPv4 and future IPv6 addresses. If you still need to write your own IP address system, remember that a standard 32-bit hex number is a valid IP address but not in dotted-decimal notation.

This function both verifies the address, and also allows you to use the same address in related socket calls.

Raymond Martineau
Thanks for answering. I ended up writing a wrapper around inet_pton. See my answer for the (really simple) implementation.
Bill the Lizard
+4  A: 

Here's one straightforward method.

bool IsIPAddress(std::string & ipaddr)
    {    

    StringTokenizer quads(ipaddr,".");

    if (quads.countTokens() != 4) return false;

    for (int i=0; i < 4; i++)
      {
      std::string quad = quads.nextToken();
      for (int j=0; j < quad.length(); j++
         if (!isdigit(quad[j])) return false;

      int quad = atoi(quads.GetTokenAt(i));
      if (quad < 0) || (quad > 255)) return false;
      }

    return true;
    }
Steve
Which library is the StringTokenizer class coming from?
Bill the Lizard
There are plenty out there, or you can implement your own. Here's a pretty good one you can download: http://www.partow.net/programming/stringtokenizer/index.html (make sure the license terms are acceptable for your project)
Steve
+12  A: 

This looks deceptively simple but has a few pitfalls. For example, many of the solutions posted in the previous answers assume that the quads are in base 10 - but a quad starting with a zero must be treated as a base 8 (octal) number, hence for example any quad part starting with zero and containing the digits 8 or 9 is not valid. I.e, the IP number 192.168.1.010 is not 192.168.1.10 but in reality is 192.168.1.8, and the IP number 192.168.019.14 is not valid since the third quad contains the invalid base 8 digit 9.

I emphatically encourage you to use the functions provided by the socket library included in your operating system or compiler environment.

Edit: (Thought it was implicit, but) of course, you can also have hexadecimal quads, a la 192.168.1.0x0A for 192.168.1.10, and of course you can mix and match to your sadistic content happily using upper and lower case, a la 0xC0.0xa8.1.010 for 192.168.1.8. Try some examples using ping if you want to have fun. This works just fine cross-platform (tested a while back while swearing under Linux, NetBSD, and Win32.)

Further edit in response to KaluSingh Gabbar's request: For example, you can specify 192.168.1.10 as 0xc0a8010a and it still represents a valid IP number, a la:

[mihailim@home ~]$ ping 0xc0a8010a
PING 0xc0a8010a (192.168.1.10) 56(84) bytes of data.
^C
--- 0xc0a8010a ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2479ms
Mihai Limbășan
I knew there were pitfalls, but you just opened up a whole new can of worms. :)
Bill the Lizard
Heh. I found out about it the hard way. The RFC describes this in minutiae detail, but nothing beats an upset manager demoing a product at the customer site telling you that "IP addresses with 8 or 9 in them don't work in our app's IP address controls!" Hunting for a nonexistent problem was fun...
Mihai Limbășan
Corollary: Never assume that all people use spaces to neatly line things up. Some use zeroes. *sigh*
Mihai Limbășan
@moocha - welcome to the real world: While octal or hex notation in IP addresses may be valid, it should NOT be encouraged! And the same goes for implementing support for it...
Roddy
Roddy, that is *not* how the real world works. In the real world, where software robustness is regarded as somewhat important, and *especially* when networking is involved, you should try to be as tolerant as possible in what you accept and as strict as possible in what you output.
Mihai Limbășan
A note: Unlike other areas, the URLS RFC's have pretty consistently defined the IPv4 addresses as only dotted quads. The other creative methods are not allowed.Also, for the purposes of the question, the asker didn't seem to ask for a validator for everything that might be accepted by the stack, just a validator of the dotted quad format.
benc
would you please share your thoughts about this line in selected answer for this question " remember that a standard 32-bit hex number is a valid IP address but not in dotted-decimal notation."I am confused there, as you have octal numbers in dotted-decimal format ? ( am I missing something? someone please correct me)
Gollum
+4  A: 

The solution that I settled on was:

bool Config::validateIpAddress(const string ipAddress)
{
    struct sockaddr_in sa;
    int result = inet_pton(AF_INET, ipAddress.c_str(), &(sa.sin_addr));
    return result != 0;
}

This works for most cases that were mentioned in other answers. It doesn't recognize IP addresses with octal or hex formatting, but that's acceptable for my application.

Bill the Lizard
And this got down-voted because...? It's definitely an acceptable answer to the OP. :)
Bill the Lizard
A: 

Boost.Asio provides the class ip::address. If you just want to verify the string, you can use it like this:

std::string ipAddress = "127.0.0.1";
boost::system::error_code ec;
boost::asio::ip::address::from_string( ipAddress, ec );
if ( ec )
    std::cerr << ec.message( ) << std::endl;

This also works for hexadecimal and octal quads. This is also a much more portable solution.

Space_C0wb0y
A: 

I have done the same using only C stdlib functions altough it does not support octal quads as mentioned above, but that should not be an issue, I can easily add that part and give it to you. Being a beginner (student) I din't even know until now that it is possible to get an octal number within your ip. I thought it must be a decimal.

Thanks StackOverFlow, I am learning in an exponential order these days :) !

Gollum
Don't feel bad at all. I was blissfully unaware of a lot of the details mentioned here before I asked this question, including the octal numbers you mentioned.
Bill the Lizard