netdev_ipaddr.c 6.0 KB

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