sal_ipaddr.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * File : sal_ipaddr.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2018-05-18 ChenYong First version
  23. */
  24. #include <sal_ipaddr.h>
  25. #include <rtthread.h>
  26. /* Here for now until needed in other places in lwIP */
  27. #ifndef isprint
  28. #define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
  29. #define isprint(c) in_range(c, 0x20, 0x7f)
  30. #define isdigit(c) in_range(c, '0', '9')
  31. #define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
  32. #define islower(c) in_range(c, 'a', 'z')
  33. #define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
  34. #endif
  35. /**
  36. * Check whether "cp" is a valid ascii representation
  37. * of an Internet address and convert to a binary address.
  38. * Returns 1 if the address is valid, 0 if not.
  39. * This replaces inet_addr, the return value from which
  40. * cannot distinguish between failure and a local broadcast address.
  41. *
  42. * @param cp IP address in ascii representation (e.g. "127.0.0.1")
  43. * @param addr pointer to which to save the ip address in network order
  44. * @return 1 if cp could be converted to addr, 0 on failure
  45. */
  46. int sal_ip4addr_aton(const char *cp, ip4_addr_t *addr)
  47. {
  48. u32_t val;
  49. u8_t base;
  50. char c;
  51. u32_t parts[4];
  52. u32_t *pp = parts;
  53. c = *cp;
  54. for (;;)
  55. {
  56. /*
  57. * Collect number up to ``.''.
  58. * Values are specified as for C:
  59. * 0x=hex, 0=octal, 1-9=decimal.
  60. */
  61. if (!isdigit(c))
  62. {
  63. return 0;
  64. }
  65. val = 0;
  66. base = 10;
  67. if (c == '0')
  68. {
  69. c = *++cp;
  70. if (c == 'x' || c == 'X')
  71. {
  72. base = 16;
  73. c = *++cp;
  74. }
  75. else
  76. {
  77. base = 8;
  78. }
  79. }
  80. for (;;)
  81. {
  82. if (isdigit(c))
  83. {
  84. val = (val * base) + (u32_t) (c - '0');
  85. c = *++cp;
  86. }
  87. else if (base == 16 && isxdigit(c))
  88. {
  89. val = (val << 4) | (u32_t) (c + 10 - (islower(c) ? 'a' : 'A'));
  90. c = *++cp;
  91. }
  92. else
  93. {
  94. break;
  95. }
  96. }
  97. if (c == '.')
  98. {
  99. /*
  100. * Internet format:
  101. * a.b.c.d
  102. * a.b.c (with c treated as 16 bits)
  103. * a.b (with b treated as 24 bits)
  104. */
  105. if (pp >= parts + 3)
  106. {
  107. return 0;
  108. }
  109. *pp++ = val;
  110. c = *++cp;
  111. }
  112. else
  113. {
  114. break;
  115. }
  116. }
  117. /*
  118. * Check for trailing characters.
  119. */
  120. if (c != '\0' && !isspace(c))
  121. {
  122. return 0;
  123. }
  124. /*
  125. * Concoct the address according to
  126. * the number of parts specified.
  127. */
  128. switch (pp - parts + 1)
  129. {
  130. case 0:
  131. return 0; /* initial nondigit */
  132. case 1: /* a -- 32 bits */
  133. break;
  134. case 2: /* a.b -- 8.24 bits */
  135. if (val > 0xffffffUL)
  136. {
  137. return 0;
  138. }
  139. if (parts[0] > 0xff)
  140. {
  141. return 0;
  142. }
  143. val |= parts[0] << 24;
  144. break;
  145. case 3: /* a.b.c -- 8.8.16 bits */
  146. if (val > 0xffff)
  147. {
  148. return 0;
  149. }
  150. if ((parts[0] > 0xff) || (parts[1] > 0xff))
  151. {
  152. return 0;
  153. }
  154. val |= (parts[0] << 24) | (parts[1] << 16);
  155. break;
  156. case 4: /* a.b.c.d -- 8.8.8.8 bits */
  157. if (val > 0xff)
  158. {
  159. return 0;
  160. }
  161. if ((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff))
  162. {
  163. return 0;
  164. }
  165. val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
  166. break;
  167. default:
  168. RT_ASSERT(0);
  169. break;
  170. }
  171. if (addr)
  172. {
  173. ip4_addr_set_u32(addr, htonl(val));
  174. }
  175. return 1;
  176. }
  177. /**
  178. * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
  179. *
  180. * @param addr ip address in network order to convert
  181. * @param buf target buffer where the string is stored
  182. * @param buflen length of buf
  183. * @return either pointer to buf which now holds the ASCII
  184. * representation of addr or NULL if buf was too small
  185. */
  186. char *sal_ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen)
  187. {
  188. u32_t s_addr;
  189. char inv[3];
  190. char *rp;
  191. u8_t *ap;
  192. u8_t rem;
  193. u8_t n;
  194. u8_t i;
  195. int len = 0;
  196. s_addr = ip4_addr_get_u32(addr);
  197. rp = buf;
  198. ap = (u8_t *) &s_addr;
  199. for (n = 0; n < 4; n++)
  200. {
  201. i = 0;
  202. do
  203. {
  204. rem = *ap % (u8_t) 10;
  205. *ap /= (u8_t) 10;
  206. inv[i++] = (char) ('0' + rem);
  207. } while (*ap);
  208. while (i--)
  209. {
  210. if (len++ >= buflen)
  211. {
  212. return NULL;
  213. }
  214. *rp++ = inv[i];
  215. }
  216. if (len++ >= buflen)
  217. {
  218. return NULL;
  219. }
  220. *rp++ = '.';
  221. ap++;
  222. }
  223. *--rp = 0;
  224. return buf;
  225. }
  226. /**
  227. * Convert numeric IP address into decimal dotted ASCII representation.
  228. * returns ptr to static buffer; not reentrant!
  229. *
  230. * @param addr ip address in network order to convert
  231. * @return pointer to a global static (!) buffer that holds the ASCII
  232. * representation of addr
  233. */
  234. char *sal_ip4addr_ntoa(const ip4_addr_t *addr)
  235. {
  236. static char str[IP4ADDR_STRLEN_MAX];
  237. return sal_ip4addr_ntoa_r(addr, str, IP4ADDR_STRLEN_MAX);
  238. }
  239. /**
  240. * Ascii internet address interpretation routine.
  241. * The value returned is in network order.
  242. *
  243. * @param cp IP address in ascii representation (e.g. "127.0.0.1")
  244. * @return ip address in network order
  245. */
  246. in_addr_t sal_ipaddr_addr(const char *cp)
  247. {
  248. ip4_addr_t val;
  249. if (sal_ip4addr_aton(cp, &val)) {
  250. return ip4_addr_get_u32(&val);
  251. }
  252. return (IPADDR_NONE);
  253. }