Определите, является ли строка действительным адресом IPv4 в C - PullRequest
25 голосов
/ 27 апреля 2009

Какой будет хороший способ определить, содержит ли строка адрес IPv4? Должен ли я использовать isdigit()?

Ответы [ 14 ]

53 голосов
/ 27 апреля 2009

Я задал аналогичный вопрос для C ++ . Вы должны быть в состоянии использовать слегка измененную (для C) версию того, что я придумал тогда.

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

Вам понадобится #include <arpa/inet.h>, чтобы использовать функцию inet_pton () .

Обновление на основе комментариев к вопросу: Если вы хотите узнать, содержит ли строка в стиле C IP-адрес , вам следует объединить два ответа, приведенные до сих пор. Используйте регулярное выражение, чтобы найти шаблоны, которые приблизительно соответствуют IP-адресу, а затем используйте функцию выше, чтобы проверить соответствие, чтобы увидеть, если это реальная сделка.

7 голосов
/ 27 апреля 2009

Это процедура, которую я написал некоторое время назад для встроенной системы, которая генерировала различные подозрительные шаблоны в сети. Таким образом, он использует абсолютно никаких причудливых вещей, таких как сетевые библиотеки или даже стандартные библиотеки C, предпочитая держаться подальше от всего этого современного материала, такого как токенизация строк и (дрожь) библиотеки регулярных выражений :-) С этой целью Он подходит практически для любой среды, в которой вы можете оказаться, и это было невероятно быстро.

Хотя, если вы находитесь в среде с чем-то вроде checkIp4Addess(), я бы посоветовал вам использовать это вместо этого. Это указание на то, с чем вам иногда приходится сталкиваться при выполнении встроенных программ (хотя - это реальное решение).

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;
}
1 голос
/ 06 января 2013
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;
}
1 голос
/ 08 июля 2010

Это моя попытка программирования на очень низком уровне C (фактически используется в одной из моих программ для микроконтроллера PIC). Он не использует библиотеку string.h. Он не использует указатели, так как этот компилятор, который я использую, плохо с ними работает, в любом случае вы можете их использовать. Принимая это во внимание и предварительно определяя переменную для обработки входящего буфера данных следующим образом:

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

Я надеюсь, что эта функция поможет вам всем. Опять же, примите во внимание низкий уровень, запрограммированный этой функцией, прежде чем критиковать.

1 голос
/ 27 апреля 2009

Я дам решение "не хочу двух проблем":

#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);

}

РЕДАКТИРОВАТЬ: strtok не может быть потокобезопасным (кредиты Адаму Розенфилду)

1 голос
/ 27 апреля 2009

Я бы использовал это регулярное выражение (любезно предоставлено Примеры регулярных выражений ):

`\b(?:\d{1,3}\.){3}\d{1,3}\b`
0 голосов
/ 25 января 2019

Я изменяю один из ответов, чтобы сделать его более полным, и прилагаю весь код (включая тест)

#include <stdio.h>
#include <assert.h>
#include <string.h>

int validateIP4Dotted(char *str, unsigned int pIPAddress[])
{
    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 == '.')
        {
            pIPAddress[segs] = accum;
            /* Must have some digits in segment. */

            if (chcnt == 0 || chcnt > 3)
                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. */
    pIPAddress[segs] = accum;

    if (segs != 3)
        return 0;

    if (chcnt == 0 || chcnt > 3)
        return 0;

    if (pIPAddress[0] >=224)
        return 0;
    /* Address okay. */

    return 1;
}


int main()
{
    unsigned int IpAddress[4];
    char str_ip[128];

    strcpy(str_ip, "192.168.1.10");
    assert(validateIP4Dotted(str_ip, IpAddress));
    assert(
            IpAddress[0] == 192 && IpAddress[1] == 168 && IpAddress[2] == 1
                    && IpAddress[3] == 10);

    strcpy(str_ip, "0.0.0.0");
    assert(validateIP4Dotted(str_ip, IpAddress));
    assert(
            IpAddress[0] == 0 && IpAddress[1] == 0 && IpAddress[2] == 0
                    && IpAddress[3] == 0);

    strcpy(str_ip, "/192.168.1.10");
    assert(!validateIP4Dotted(str_ip, IpAddress));

    strcpy(str_ip, "192..168.1.10");
    assert(!validateIP4Dotted(str_ip, IpAddress));

    strcpy(str_ip, ".192.168.1.10");
    assert(!validateIP4Dotted(str_ip, IpAddress));

    strcpy(str_ip, "192.168.1.10.");
    assert(!validateIP4Dotted(str_ip, IpAddress));

    strcpy(str_ip, "192.168.1.10.10");
    assert(!validateIP4Dotted(str_ip, IpAddress));

    strcpy(str_ip, "192.168.1.");
    assert(!validateIP4Dotted(str_ip, IpAddress));

    strcpy(str_ip, "192.168.1");
    assert(!validateIP4Dotted(str_ip, IpAddress));

    strcpy(str_ip, "255.168.1.10");
    assert(!validateIP4Dotted(str_ip, IpAddress));

    strcpy(str_ip, "10.260.1.10");
    assert(!validateIP4Dotted(str_ip, IpAddress));

    strcpy(str_ip, "10.200.0001.10");
    assert(!validateIP4Dotted(str_ip, IpAddress));

    return 0;
}
0 голосов
/ 13 сентября 2016
//  you can even use the v value array to return the unsigned int 
//  version of the IP if desired in an unsigned int reference.   

bool isvalidip(const char * s) 
{
  char t[8];
  int p = 0;
  int v[8];
  int numnum = 0;
  for (int i = 0; i < (int) strlen(s); i++) {
    char c = s[i];
    int cgood = 0;
    if (c >= '0' && c <= '9' && p < 4) {
      t[p++] = c;
      t[p] = 0;
      cgood++;
      continue;
    }
    if (p == 4) return false;
    if (c == '.') {
      if (!p) return false;
      v[numnum++] = atoi(t);
      p = 0;
      cgood++;
      continue;
    }
    if (!cgood) return false; // not a valid character
    if (numnum > 4) return false; // we have a lot of dots....
  }
  v[numnum++] = atoi(t); // we did not have a dot, we had a NULL.....
  if (numnum != 4) return false; // we must have had 4 valid numbers....
  for (int i = 0; i < 4; i++)
  {
    if (v[i] < 0 || v[i] > 255) return false; // octet values out-of-range
  }
  return true; //we good..
}
0 голосов
/ 08 июня 2015

Вот начало функции, над которой я работал, хотя она и не завершена, она может вызвать идеи или комментарии. Мысль, стоящая за функцией:

  1. Убедитесь, что переданный символьный указатель или строка является IPv4-адресом без порта с использованием его минимального / максимального размера, количества точек в строке и наличия символа двоеточия: или нет.
  2. Если строка не является IPv4 с портом или без него, проверьте, является ли строка IPv6, если не IPv6, то формат IP не распознается, поскольку он еще не реализован.

Я думаю, это зависит от того, насколько глубоко вы хотите углубиться в проблему, насколько глубоко вы хотите углубиться, чтобы понять, какие проблемы могут возникнуть.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>

int isIP(char *ip)
{
    char *data_ptr = ip;    // Create a pointer to passed data
    int orig_str_size = 0;  // Create an int to hold passed data size
    int str_index = 0;      // Create an int to iterate individual ip characters
    int dot_count = 0;      // Create an int to check for the number of dots

    // Count the number of characters in data_ptr
    while (*data_ptr++ != '\0'){ orig_str_size++; }

    if(orig_str_size <= 0) // If nothing
    {
        printf("Get a grip, ip is empty\n\n");
        exit(0);
    }
    else // If within IPv4 size range
    if(orig_str_size >= 7 && orig_str_size <= INET_ADDRSTRLEN)
    {
        char *data1_ptr = ip; // Create a pointer to passed data
        printf("Within IPv4 range, %i characters in length\n\n", orig_str_size);

        // Count the number of dots in the string, 3 for IPv4
        for(str_index; str_index < orig_str_size; str_index++)
        {
            if(data1_ptr[str_index] == '.'){ dot_count++; }
        }

        // If theres 3 dots, while ignoring dots, check each char is a digit 
        if(dot_count == 3)
        {

            printf("There's three dots in the string\n\n");
            data1_ptr = ip;
            str_index = 0;

            // Iterate the string char by char
            for(str_index; str_index < orig_str_size; str_index++)
            {
                // Ignoring dots
                if(data1_ptr[str_index] != '.')
                { 
                    // If isdigit() is happy its a digit and isalpha() happy not alphabetic
                    if(isdigit(data1_ptr[str_index]) && !isalpha(data1_ptr[str_index]))
                    {
                        printf("Digit found and is not alphabetic\n\n");
                        continue;
                    }
                    else
                    if(!isdigit(data1_ptr[str_index]) && isalpha(data1_ptr[str_index]))
                    {
                        printf("Not a recognised IPv4 address, character detected in string\n\n");
                        exit(0);
                    }
                }
            }

            return 0;
        }
    }
    else // If IPv6
    if(orig_str_size > 0 && orig_str_size > INET_ADDRSTRLEN && orig_str_size <= INET6_ADDRSTRLEN)
    {
        printf("Within IPv6 range %i\n\n", orig_str_size);
        return 0;
    }
    else
    {
        printf("Unknown target format, the format you provided as a target is not implemented\n\n");
        exit(0);
    }

}

Межсетевое взаимодействие TCP / IP

RFC791 - Интернет-протокол - https://tools.ietf.org/html/rfc791

Справочник по межсетевым технологиям CISCO http://docwiki.cisco.com/wiki/Internetworking_Technology_Handbook

Эталонная модель взаимодействия открытых систем http://docwiki.cisco.com/wiki/Internetworking_Basics#Open_Systems_Interconnection_Reference_Model

CISCO Устранение неполадок в сетях TCP / IP https://www.cisco.com/en/US/docs/internetworking/troubleshooting/guide/tr1907.pdf

Какой самый большой номер сетевого порта TCP / IP допустим для IPv4?

0 голосов
/ 31 июля 2014

Сделай это с нуля вот так. Этот код содержит инструменты для проверки, содержит ли строка IPv4 IP-адрес.

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

Функция IsIp4str (char * str) проверяет, содержит ли строка формат адреса IP версии четыре. Функциональный тест IsIp6str (char * str), если строка содержит формат адреса версии 6 IP-адреса.

Функции IsIp4str (char * str) и IsIp6str (char * str) возвращает true, если строка str содержит IP-адрес, или false, если строка str не содержит IP-адрес.

Если вам нужно проверить, содержит ли строка IP-адрес в формате IPv6, это можно сделать с помощью функции int IsIp6str (char * str). Он работает так же, как

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...