27 votes

Déterminer si une chaîne de caractères est une adresse IPv4 valide en C

Quelle serait la meilleure façon de déterminer si une chaîne de caractères contient une adresse IPv4 ? Devrais-je utiliser isdigit() ?

64voto

Bill the Lizard Points 147311

J'ai demandé une question similaire pour le C++ . Vous devriez pouvoir utiliser une version légèrement modifiée (pour le C) de ce que j'avais proposé à l'époque.

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

Vous devez #include <arpa/inet.h> pour utiliser le inet_pton() fonction.

Mise à jour sur la base des commentaires à la question : Si vous voulez savoir si une chaîne de style C contient une adresse IP, vous devez combiner les deux réponses données jusqu'à présent. Utilisez une expression régulière pour trouver des motifs qui correspondent approximativement à une adresse IP, puis utilisez la fonction ci-dessus pour vérifier la correspondance et voir s'il s'agit d'une vraie adresse.

14voto

paxdiablo Points 341644

Il s'agit d'une routine que j'ai écrite il y a quelque temps pour un système embarqué qui générait divers modèles suspects sur un réseau. En tant que telle, elle utilise absolument non des choses fantaisistes comme les bibliothèques réseau ou même les bibliothèques C standard, préférant rester à l'écart de tous les trucs modernes comme la symbolisation des chaînes de caractères et les bibliothèques d'expressions régulières (qui font frémir) :-) A cette fin, il est adapté à presque tous les environnements dans lesquels vous pourriez vous trouver, et il était d'une rapidité aveuglante.

Toutefois, si vous êtes dans un environnement qui a quelque chose comme checkIp4Addess() Je vous suggère de l'utiliser à la place. Il s'agit d'une indication des problèmes que l'on doit parfois affronter lorsqu'on fait des choses intégrées (bien qu'il s'agisse d'un problème de sécurité). est une véritable 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;
}

Il fonctionne avec la représentation de l'adresse décimale en pointillés (quatre segments), mais comme c'est de loin la forme la plus courante, je ne considère pas cela comme une limitation. Il y a étaient d'autres représentations il y a longtemps (qui sont probablement encore valables) mais il est rare de les voir.

4voto

M M. Points 29201
int validateIP4Dotted(const char *s)
{
    int len = strlen(s);

    if (len < 7 || len > 15)
        return 0;

    char tail[16];
    tail[0] = 0;

    unsigned int d[4];
    int c = sscanf(s, "%3u.%3u.%3u.%3u%s", &d[0], &d[1], &d[2], &d[3], tail);

    if (c != 4 || tail[0])
        return 0;

    for (int i = 0; i < 4; i++)
        if (d[i] > 255)
            return 0;

    return 1;
}

1voto

Andrew Hare Points 159332

J'utiliserais cette expression régulière (avec l'aimable autorisation de Exemples d'expressions régulières ) :

`\b(?:\d{1,3}\.){3}\d{1,3}\b`

1voto

Tom Points 16783

Je donnerai la solution "je ne veux pas deux problèmes" :

#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 peut ne pas être thread safe (crédits à Adam Rosenfield)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X