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() ?

1voto

piotr Points 2826

Dans l'url/uri rfc 3986, la forme augmentée Backus-Naur (ABNF) de l'adresse ipv4 est définie comme suit :

  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

J'ai implémenté la vérification avec une expression rationnelle sous la forme suivante :

// 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 ")"

1voto

Dilandau Points 11

Voici mon essai de programmation en C de très bas niveau (utilisé dans un de mes programmes pour un microcontrôleur PIC). Il n'utilise pas la bibliothèque string.h. Il n'utilise pas les pointeurs, car le compilateur que j'utilise ne fonctionne pas bien avec eux, même si vous pouvez les utiliser. En prenant cela en compte et en définissant au préalable une variable pour gérer le tampon de données entrant comme ceci :

#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;
}//

J'espère que cette fonction vous sera utile. Encore une fois, tenez compte du faible niveau de programmation de cette fonction avant de la critiquer.

0voto

Joshua Points 13231
inet_aton()

0voto

jillybean_64 Points 1

Je devais déterminer si une chaîne de caractères entrante "contient" une adresse IP valide, et renvoyer un pointeur vers la partie de la chaîne de caractères entrante qui est l'adresse IP valide, si c'est le cas. Si ce n'est pas le cas, la fonction renvoie un pointeur nul.

Voici un code qui semble fonctionner, bien qu'il n'ait pas encore été testé, je viens de l'écrire et de l'essayer rapidement. Je n'ai pas encore ajouté de vérification pour limiter les nombres à des valeurs d'un octet, mais je vérifie qu'ils sont limités à des nombres de trois chiffres.

int IsDigit(char ch)
{
   int is_digit = 0;
   if ( ch >= '0' && ch <= '9' )
   {
      is_digit = 1;
   }
   return is_digit;
}

#define FIND_IP_START         0
#define FIND_IP_DIGIT         1
#define FIND_IP_DIG_OR_DEC    2
#define FIND_IP_DECIMAL       3
#define FIND_IP_DIG_OR_END    4
#define FIND_IP_END           5
#define FIND_IP_DONE          6

char * StringContainsValidIpAddress(char * input_buf_pointer)
{
   char * pos       = input_buf_pointer;
   int    octets    = 0; 
   int    digits    = 0;
   int    state     = FIND_IP_START;
   char * ip_string = 0;

   char   ch        = *pos; 

   while ( (ch != NULL) && (state != FIND_IP_DONE) )
   {
      switch ( state )
      {
      case FIND_IP_START:
         if ( IsDigit(ch) )
         {
            ip_string = pos;  //potential start of ip string
            digits = 1;   // first digit
            octets = 1;   // of first octet
            state = FIND_IP_DIG_OR_DEC;
         }
         break;
      case FIND_IP_DIGIT:
         if ( IsDigit(ch) )
         {
            digits = 1;    // first digit
            octets++;      // of next octet
            if ( octets == 4 )
            {
               state = FIND_IP_DIG_OR_END;
            }
            else
            {
                   state = FIND_IP_DIG_OR_DEC;
            }
         }
         else
         {
            // Start over
            state = FIND_IP_START;
         }
         break;
      case FIND_IP_DIG_OR_DEC:
         // Here we are looking for another digit 
         // of the same octet or the decimal between 
         // octets.
         if (ch == '.')
         {
               state = FIND_IP_DIGIT;
         }
         else if ( IsDigit(ch) )
         {
            digits++;      // next digit
            if ( digits == 3 )
            {
               state = FIND_IP_DECIMAL;
            }
         }
         else
         {
            // Start over
            state = FIND_IP_START;
         }
         break;
      case FIND_IP_DECIMAL:
         if (ch == '.')
         {
               state = FIND_IP_DIGIT;
         }
         break;
      case FIND_IP_DIG_OR_END:
         // Here we are looking for another digit 
         // of the same octet or the end (which could
         // be a space or CR or LF or really any 
         // non-digit).
         if ( IsDigit(ch) )
         {
            digits++;      // next digit
            if ( digits == 3 )
            {
               state = FIND_IP_END;
            }
         }
         else
         {  
            *pos = 0;  // Null terminate the IP address string
            state = FIND_IP_DONE;
         }
         break;
      case FIND_IP_END:
         if ( !IsDigit(ch) )
         {
            *pos = 0;  // Null terminate the IP address string
            state = FIND_IP_DONE;
         }
         break;
      case FIND_IP_DONE:
         break;
      default:
         break;
      }

      // Fetch the next character
      ch = *++pos; 
   } 

   if (state == FIND_IP_DONE) 
   {
      return ip_string; 
   }
   else
   {
      return 0;
   }
}

0voto

user3896692 Points 1

Faites-le à partir de zéro comme ceci. Ce code contient des outils permettant de vérifier si une chaîne contient une adresse IPv4.

#define MAX_HEX_NUMBER_COUNT 8 

int ishexdigit(char ch) 
{
   if((ch>='0'&&ch<='9')||(ch>='a'&&ch<='f')||(ch>='A'&&ch<='F'))
      return(1);
   return(0);
}

int IsIp6str(char *str)
{ 
   int hdcount=0;
   int hncount=0;
   int err=0;
   int packed=0;

   if(*str==':')
   {
      str++;    
      if(*str!=':')
         return(0);
      else
      {
         packed=1;
         hncount=1;
         str++;

         if(*str==0)
            return(1);
      }
   }

   if(ishexdigit(*str)==0)
   {
      return(0);        
   }

   hdcount=1;
   hncount=1;
   str++;

   while(err==0&&*str!=0)   
   {                      
      if(*str==':')
      {
         str++;
         if(*str==':')
         {
           if(packed==1)
              err=1;
           else
           {
              str++;

          if(ishexdigit(*str)||*str==0&&hncount<MAX_HEX_NUMBER_COUNT)
          {
             packed=1;
             hncount++;

             if(ishexdigit(*str))
             {
                if(hncount==MAX_HEX_NUMBER_COUNT)
                {
                   err=1;
                } else
                {
                   hdcount=1;
                   hncount++;
                   str++;   
                }
             }
          } else
          {
             err=1;
          }
       }
    } else
    {
           if(!ishexdigit(*str))
           {
              err=1;
           } else
           {
              if(hncount==MAX_HEX_NUMBER_COUNT)
              {
                 err=1;
              } else
              {
                  hdcount=1;
                  hncount++;
                  str++;   
              }
           }
        }
     } else
     {  
        if(ishexdigit(*str))
        {
           if(hdcount==4)
              err=1;
           else
           {
              hdcount++;          
              str++;
           }
         } else
            err=1;
     } 
   }

   if(hncount<MAX_HEX_NUMBER_COUNT&&packed==0)
      err=1;

    return(err==0);
}

int IsIp4str(char *str) 
{
   int nnumber=0;
   int value=0;
   int err=0;

   if(*str>='0'&&*str<='9')
   {
      value=*str-'0';
      str++;
   } else
      return(0);

   nnumber=1;

   while(err==0&&*str!=0)
   {
      if(*str>='0'&&*str<='9')
      {
         if(255/value>=10)
         {
            value*=10;

            if(255-value>=(*str-'0'))
            {
               value+=(*str-'0');
               str++;
            } else
                err=1;
         } else
           err=1;
      }  else
      {
         if(*str=='.')
         {      
            str++;
            if(*str>='0'&&*str<='9')
            {
               if(nnumber==4)
                  err=1;
               else
               {
                  if(*str=='0')
                  {
                     *str++;
                     if(*str!='.'&&*str!=0)
                        err=1;
                     else
                     {
                        nnumber++;
                        value=0;
                     }
                  } else
                  {
                     nnumber++;
                     value=*str-'0';
                     str++;
                  }
               }
            } else
            {
               err=1;
            }
         } else
           if(*str!=0)
             err=1;
      }
   }

   if(nnumber!=4)
      err=1;

   return(err==0);
}

Fonction IsIp4str(char *str) teste si la chaîne contient une adresse IP au format quatre. IsIp6str(char *str) fonction testant si la chaîne contient le format d'adresse IP version six.

Les fonctions IsIp4str(char *str) et IsIp6str(char *str) renvoient un message vrai si la chaîne contient l'adresse IP ou faux si la chaîne ne contient pas l'adresse IP.

Si vous devez vérifier si une chaîne contient une adresse IP au format IPv6, vous pouvez utiliser la fonction int IsIp6str(char *str). Elle fonctionne de la même manière que

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