tags:

views:

2163

answers:

7

Hey everybody,

What would be a good way to determine if a string contains an IP address. Should I use isdigit()?

Suggestions would be appreciate it.

Thanks

+1  A: 

I would use this regular expression (courtesy of Regular Expression Examples):

`\b(?:\d{1,3}\.){3}\d{1,3}\b`
Andrew Hare
Note: this will match IP4 addresses in dotted-decimal notation ONLY
Nick Whaley
This also doesn't detect if any octet is larger than 255. Regexes are a bit overkill for this problem.
Adam Rosenfield
if you fancy a bit of 'overkill' that's a little more effective, try this ^((([0-9]{1,2})|(1[0-9]{2,2})|(2[0-4][0-9])|(25[0-5])|\*)\.){3}(([0-9]{1,2})|(1[0-9]{2,2})|(2[0-4][0-9])|(25[0-5])|\*)$ (thanks to apoorv020 from my question http://stackoverflow.com/questions/2999282/regular-expression-to-match-ip-address-wildcard)
Ed Woodcock
+11  A: 

I asked a similar question for C++. You should be able to use a slightly modified (for C) version of what I came up with back then.

bool isValidIpAddress(char *ipAddress)
{
    struct sockaddr_in sa;
    int result = inet_pton(AF_INET, ipAddress, &(sa.sin_addr));
    return result != 0;
}

You'll need to #include <arpa/inet.h> to use the inet_pton() function.

Update based on comments to the question: If you want to know if a C-style string contains an IP address, then you should combine the two answers given so far. Use a regular expression to find patterns that roughly match an IP address, then use the function above to check the match to see if it's the real deal.

Bill the Lizard
+1 , you beat me to it :)
Tim Post
A: 

I'll give the "don't want two problems" solution:

#include <string.h>



int isIp_v4( char* ip){
        int num;
        int flag = 1;
        int counter=0;
        char* p = strtok(ip,".");

        while (p && flag ){
                num = atoi(p);

                if (num>=0 && num<=255 && (counter++<4)){
                        flag=1;
                        p=strtok(NULL,".");

                }
                else{
                        flag=0;
                        break;
                }
        }

        return flag && (counter==3);

}

EDIT: strtok may not be thread safe (credits to Adam Rosenfield)

Tom
strtok is not necessarily thread-safe (it may be in some implementations, but it is not guaranteed to be).
Adam Rosenfield
@Adam: I see your point, but i think is reading too much between the lines. However, strtok could be replaced (when neccessary) with a custom thread safe strtok implementation.
Tom
would downvoter please comment?
Tom
A: 
inet_aton()
Joshua
A: 

In the url/uri rfc 3986, the Augmented Backus-Naur Form (ABNF) ipv4 address is defined as:

  IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet

  dec-octet   = DIGIT                 ; 0-9
              / %x31-39 DIGIT         ; 10-99
              / "1" 2DIGIT            ; 100-199
              / "2" %x30-34 DIGIT     ; 200-249
              / "25" %x30-35          ; 250-255

I implemented the check with regexp in the following form:

// Although the RFC says ipv6 octects like 001 are not valid, it would be risky
// not to accept those
#define decoct "([01]?[0-9]?[0-9]|2[0-4][0-0]|25[0-5])"
#define ipv4 "(" decoct "\\." decoct "\\." decoct "\\." decoct ")"
piotr
+1  A: 

This is a routine I wrote a while ago for an embedded system which generated various suspect patterns on a network. As such, it uses absolutely no fancy stuff like network libraries or even the standard C libraries, preferring to steer clear of all that modern stuff like string tokenizing and (shudder) regular expression libraries :-) To that end, it's suited to just about any environment you could find yourself in, and it was blindingly fast.

Although, if you're in an environment that has something like checkIp4Addess(), I'd suggest you use that instead. It's an indication of the stuff you sometimes have to put up with when doing embedded stuff (although it is a real solution).

int isValidIp4 (char *str) {
    int segs = 0;   /* Segment count. */
    int chcnt = 0;  /* Character count within segment. */
    int accum = 0;  /* Accumulator for segment. */

    /* Catch NULL pointer. */

    if (str == NULL)
        return 0;

    /* Process every character in string. */

    while (*str != '\0') {
        /* Segment changeover. */

        if (*str == '.') {
            /* Must have some digits in segment. */

            if (chcnt == 0)
                return 0;

            /* Limit number of segments. */

            if (++segs == 4)
                return 0;

            /* Reset segment values and restart loop. */

            chcnt = accum = 0;
            str++;
            continue;
        }

 

        /* Check numeric. */

        if ((*str < '0') || (*str > '9'))
            return 0;

        /* Accumulate and check segment. */

        if ((accum = accum * 10 + *str - '0') > 255)
            return 0;

        /* Advance other segment specific stuff and continue loop. */

        chcnt++;
        str++;
    }

    /* Check enough segments and enough characters in last segment. */

    if (segs != 3)
        return 0;

    if (chcnt == 0)
        return 0;

    /* Address okay. */

    return 1;
}
paxdiablo
Segment can not start with 0? What about 192.168.0.1 ?...
Matthew Flaschen
That's a good point - I think we put that in to stop things like 192.1.004.1. Either that client's been very lucky or they stopped using our code due to bugs :-). I'll fix it.
paxdiablo
A: 

This is my try with a very low level C programming ( actually used in one of my programs for a PIC microcontroller). It does not use of string.h library. It does not use pointers, as this compiler I am using does not work well with them, anyway you could use them. Taking this into account and previosly defining a variable to handle the incoming data buffer like this:

#define isdigit(x)  isamong(x,"0123456789")
char    IPACK_Buff[IPACK_SIZE]; 

// Check if string is a valid IP
int IPACK_is_valid_ip(int len)
{
    int i = 0;
    int j = 0;
    int NumDots = 0;
    char number[4] = "000\0";

    // Check first  char is numeric
    if (!isdigit(IPACK_Buff[0])) 
        return 0;

    for (i = 0 ; i< len; i++)
    {
        if (isdigit(IPACK_Buff[i]))
        {
            number[j] = IPACK_Buff[i];
            j++;
            if (j>3)    
                return 0;
        }
        else if (IPACK_Buff[i] == '.')
        {
            if (atof(number)> 255) return 0;
            memset(number, '\0', 4);

            j = 0;
            NumDots++;
            if(NumDots>3)
                return 0;
        }
    }

    if (NumDots == 3)
    {
        return 1;
    }
    else 
        return 0;
}//

I hope this function helps you all. Again, take into account the low level this function is programmed before criticize.

Dilandau