ipaddrparse.c
上传用户:ig0539
上传日期:2022-05-21
资源大小:181k
文件大小:5k
源码类别:

Ftp客户端

开发平台:

C/C++

  1. /*
  2.  * Part of Very Secure FTPd
  3.  * Licence: GPL v2
  4.  * Author: Chris Evans
  5.  * ipaddrparse.c
  6.  *
  7.  * A routine to parse ip addresses. I'm paranoid and don't want to use
  8.  * inet_pton.
  9.  */
  10. #include "ipaddrparse.h"
  11. #include "sysutil.h"
  12. #include "str.h"
  13. static int ipv6_parse_main(struct mystr* p_out_str,
  14.                            const struct mystr* p_in_str);
  15. static int ipv6_parse_hex(struct mystr* p_out_str,
  16.                           const struct mystr* p_in_str);
  17. static int ipv4_parse_dotquad(struct mystr* p_out_str,
  18.                               const struct mystr* p_in_str);
  19. const unsigned char*
  20. vsf_sysutil_parse_ipv6(const struct mystr* p_str)
  21. {
  22.   static struct mystr s_ret;
  23.   static struct mystr s_rhs_ret;
  24.   static struct mystr s_lhs_str;
  25.   static struct mystr s_rhs_str;
  26.   unsigned int lhs_len;
  27.   unsigned int rhs_len;
  28.   str_empty(&s_ret);
  29.   str_empty(&s_rhs_ret);
  30.   str_copy(&s_lhs_str, p_str);
  31.   str_split_text(&s_lhs_str, &s_rhs_str, "::");
  32.   if (!ipv6_parse_main(&s_ret, &s_lhs_str))
  33.   {
  34.     return 0;
  35.   }
  36.   if (!ipv6_parse_main(&s_rhs_ret, &s_rhs_str))
  37.   {
  38.     return 0;
  39.   }
  40.   lhs_len = str_getlen(&s_ret);
  41.   rhs_len = str_getlen(&s_rhs_ret);
  42.   if (lhs_len + rhs_len > 16)
  43.   {
  44.     return 0;
  45.   }
  46.   if (rhs_len > 0)
  47.   {
  48.     unsigned int add_nulls = 16 - (lhs_len + rhs_len);
  49.     while (add_nulls--)
  50.     {
  51.       str_append_char(&s_ret, '');
  52.     }
  53.     str_append_str(&s_ret, &s_rhs_ret);
  54.   }
  55.   return (const unsigned char*) str_getbuf(&s_ret);
  56. }
  57. const unsigned char*
  58. vsf_sysutil_parse_ipv4(const struct mystr* p_str)
  59. {
  60.   static unsigned char items[4];
  61.   return vsf_sysutil_parse_uchar_string_sep(p_str, '.', items, sizeof(items));
  62. }
  63. const unsigned char*
  64. vsf_sysutil_parse_uchar_string_sep(
  65.   const struct mystr* p_str, char sep, unsigned char* p_items,
  66.   unsigned int items)
  67. {
  68.   static struct mystr s_tmp_str;
  69.   unsigned int i;
  70.   str_copy(&s_tmp_str, p_str);
  71.   for (i=0; i<items; i++)
  72.   {
  73.     static struct mystr s_rhs_sep_str;
  74.     int this_number;
  75.     /* This puts a single separator delimited field in tmp_str */
  76.     str_split_char(&s_tmp_str, &s_rhs_sep_str, sep);
  77.     /* Sanity - check for too many or two few dots! */
  78.     if ( (i < (items-1) && str_isempty(&s_rhs_sep_str)) ||
  79.          (i == (items-1) && !str_isempty(&s_rhs_sep_str)))
  80.     {
  81.       return 0;
  82.     }
  83.     this_number = str_atoi(&s_tmp_str);
  84.     if (this_number < 0 || this_number > 255)
  85.     {
  86.       return 0;
  87.     }
  88.     /* If this truncates from int to uchar, we don't care */
  89.     p_items[i] = (unsigned char) this_number;
  90.     /* The right hand side of the comma now becomes the new string to
  91.      * breakdown
  92.      */
  93.     str_copy(&s_tmp_str, &s_rhs_sep_str);
  94.   }
  95.   return p_items;
  96. }
  97. static int
  98. ipv6_parse_main(struct mystr* p_out_str, const struct mystr* p_in_str)
  99. {
  100.   static struct mystr s_lhs_str;
  101.   static struct mystr s_rhs_str;
  102.   struct str_locate_result loc_ret;
  103.   str_copy(&s_lhs_str, p_in_str);
  104.   while (!str_isempty(&s_lhs_str))
  105.   {
  106.     str_split_char(&s_lhs_str, &s_rhs_str, ':');
  107.     if (str_isempty(&s_lhs_str))
  108.     {
  109.       return 0;
  110.     }
  111.     loc_ret = str_locate_char(&s_lhs_str, '.');
  112.     if (loc_ret.found)
  113.     {
  114.       if (!ipv4_parse_dotquad(p_out_str, &s_lhs_str))
  115.       {
  116.         return 0;
  117.       }
  118.     }
  119.     else if (!ipv6_parse_hex(p_out_str, &s_lhs_str))
  120.     {
  121.       return 0;
  122.     }
  123.     str_copy(&s_lhs_str, &s_rhs_str);
  124.   }
  125.   return 1;
  126. }
  127. static int
  128. ipv6_parse_hex(struct mystr* p_out_str, const struct mystr* p_in_str)
  129. {
  130.   unsigned int len = str_getlen(p_in_str);
  131.   unsigned int i;
  132.   unsigned int val = 0;
  133.   for (i=0; i<len; ++i)
  134.   {
  135.     int ch = vsf_sysutil_toupper(str_get_char_at(p_in_str, i));
  136.     if (ch >= '0' && ch <= '9')
  137.     {
  138.       ch -= '0';
  139.     }
  140.     else if (ch >= 'A' && ch <= 'F')
  141.     {
  142.       ch -= 'A';
  143.       ch += 10;
  144.     }
  145.     else
  146.     {
  147.       return 0;
  148.     }
  149.     val <<= 4;
  150.     val |= ch;
  151.     if (val > 0xFFFF)
  152.     {
  153.       return 0;
  154.     }
  155.   }
  156.   str_append_char(p_out_str, (val >> 8));
  157.   str_append_char(p_out_str, (val & 0xFF));
  158.   return 1;
  159. }
  160. static int
  161. ipv4_parse_dotquad(struct mystr* p_out_str, const struct mystr* p_in_str)
  162. {
  163.   unsigned int len = str_getlen(p_in_str);
  164.   unsigned int i;
  165.   unsigned int val = 0;
  166.   unsigned int final_val = 0;
  167.   int seen_char = 0;
  168.   int dots = 0;
  169.   for (i=0; i<len; ++i)
  170.   {
  171.     int ch = str_get_char_at(p_in_str, i);
  172.     if (ch == '.')
  173.     {
  174.       if (!seen_char || dots == 3)
  175.       {
  176.         return 0;
  177.       }
  178.       seen_char = 0;
  179.       dots++;
  180.       final_val <<= 8;
  181.       final_val |= val;
  182.       val = 0;
  183.     }
  184.     else if (ch >= '0' && ch <= '9')
  185.     {
  186.       ch -= '0';
  187.       val *= 10;
  188.       val += ch;
  189.       if (val > 255)
  190.       {
  191.         return 0;
  192.       }
  193.       seen_char = 1;
  194.     }
  195.     else
  196.     {
  197.       return 0;
  198.     }
  199.   }
  200.   if (dots != 3 || !seen_char)
  201.   {
  202.     return 0;
  203.   }
  204.   final_val <<= 8;
  205.   final_val |= val;
  206.   str_append_char(p_out_str, (final_val >> 24));
  207.   str_append_char(p_out_str, ((final_val >> 16) & 0xFF));
  208.   str_append_char(p_out_str, ((final_val >> 8) & 0xFF));
  209.   str_append_char(p_out_str, (final_val & 0xFF));
  210.   return 1;
  211. }