netdev_ipaddr.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  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. #define xchar(i) ((i) < 10 ? '0' + (i) : 'A' + (i) - 10)
  21. #endif
  22. #if NETDEV_IPV4
  23. /**
  24. * Check whether "cp" is a valid ascii representation
  25. * of an Internet address and convert to a binary address.
  26. * Returns 1 if the address is valid, 0 if not.
  27. * This replaces inet_addr, the return value from which
  28. * cannot distinguish between failure and a local broadcast address.
  29. *
  30. * @param cp IP address in ascii representation (e.g. "127.0.0.1")
  31. * @param addr pointer to which to save the ip address in network order
  32. * @return 1 if cp could be converted to addr, 0 on failure
  33. */
  34. int netdev_ip4addr_aton(const char *cp, ip4_addr_t *addr)
  35. {
  36. uint32_t val;
  37. uint8_t base;
  38. char c;
  39. uint32_t parts[4];
  40. uint32_t *pp = parts;
  41. c = *cp;
  42. for (;;)
  43. {
  44. /*
  45. * Collect number up to ``.''.
  46. * Values are specified as for C:
  47. * 0x=hex, 0=octal, 1-9=decimal.
  48. */
  49. if (!isdigit(c))
  50. {
  51. return 0;
  52. }
  53. val = 0;
  54. base = 10;
  55. if (c == '0')
  56. {
  57. c = *++cp;
  58. if (c == 'x' || c == 'X')
  59. {
  60. base = 16;
  61. c = *++cp;
  62. }
  63. else
  64. {
  65. base = 8;
  66. }
  67. }
  68. for (;;)
  69. {
  70. if (isdigit(c))
  71. {
  72. val = (val * base) + (uint32_t) (c - '0');
  73. c = *++cp;
  74. }
  75. else if (base == 16 && isxdigit(c))
  76. {
  77. val = (val << 4) | (uint32_t) (c + 10 - (islower(c) ? 'a' : 'A'));
  78. c = *++cp;
  79. }
  80. else
  81. {
  82. break;
  83. }
  84. }
  85. if (c == '.')
  86. {
  87. /*
  88. * Internet format:
  89. * a.b.c.d
  90. * a.b.c (with c treated as 16 bits)
  91. * a.b (with b treated as 24 bits)
  92. */
  93. if (pp >= parts + 3)
  94. {
  95. return 0;
  96. }
  97. *pp++ = val;
  98. c = *++cp;
  99. }
  100. else
  101. {
  102. break;
  103. }
  104. }
  105. /*
  106. * Check for trailing characters.
  107. */
  108. if (c != '\0' && !isspace(c))
  109. {
  110. return 0;
  111. }
  112. /*
  113. * Concoct the address according to
  114. * the number of parts specified.
  115. */
  116. switch (pp - parts + 1)
  117. {
  118. case 0:
  119. return 0; /* initial nondigit */
  120. case 1: /* a -- 32 bits */
  121. break;
  122. case 2: /* a.b -- 8.24 bits */
  123. if (val > 0xffffffUL)
  124. {
  125. return 0;
  126. }
  127. if (parts[0] > 0xff)
  128. {
  129. return 0;
  130. }
  131. val |= parts[0] << 24;
  132. break;
  133. case 3: /* a.b.c -- 8.8.16 bits */
  134. if (val > 0xffff)
  135. {
  136. return 0;
  137. }
  138. if ((parts[0] > 0xff) || (parts[1] > 0xff))
  139. {
  140. return 0;
  141. }
  142. val |= (parts[0] << 24) | (parts[1] << 16);
  143. break;
  144. case 4: /* a.b.c.d -- 8.8.8.8 bits */
  145. if (val > 0xff)
  146. {
  147. return 0;
  148. }
  149. if ((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff))
  150. {
  151. return 0;
  152. }
  153. val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
  154. break;
  155. default:
  156. RT_ASSERT(0);
  157. break;
  158. }
  159. if (addr)
  160. {
  161. ip4_addr_set_u32(addr, htonl(val));
  162. }
  163. return 1;
  164. }
  165. /**
  166. * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
  167. *
  168. * @param addr ip address in network order to convert
  169. * @param buf target buffer where the string is stored
  170. * @param buflen length of buf
  171. * @return either pointer to buf which now holds the ASCII
  172. * representation of addr or NULL if buf was too small
  173. */
  174. char *netdev_ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen)
  175. {
  176. uint32_t s_addr;
  177. char inv[3];
  178. char *rp;
  179. uint8_t *ap;
  180. uint8_t rem;
  181. uint8_t n;
  182. uint8_t i;
  183. int len = 0;
  184. s_addr = ip4_addr_get_u32(addr);
  185. rp = buf;
  186. ap = (uint8_t *) &s_addr;
  187. for (n = 0; n < 4; n++)
  188. {
  189. i = 0;
  190. do
  191. {
  192. rem = *ap % (uint8_t) 10;
  193. *ap /= (uint8_t) 10;
  194. inv[i++] = (char) ('0' + rem);
  195. } while (*ap);
  196. while (i--)
  197. {
  198. if (len++ >= buflen)
  199. {
  200. return NULL;
  201. }
  202. *rp++ = inv[i];
  203. }
  204. if (len++ >= buflen)
  205. {
  206. return NULL;
  207. }
  208. *rp++ = '.';
  209. ap++;
  210. }
  211. *--rp = 0;
  212. return buf;
  213. }
  214. /**
  215. * Convert numeric IP address into decimal dotted ASCII representation.
  216. * returns ptr to static buffer; not reentrant!
  217. *
  218. * @param addr ip address in network order to convert
  219. * @return pointer to a global static (!) buffer that holds the ASCII
  220. * representation of addr
  221. */
  222. char *netdev_ip4addr_ntoa(const ip4_addr_t *addr)
  223. {
  224. static char str[IP4ADDR_STRLEN_MAX];
  225. return netdev_ip4addr_ntoa_r(addr, str, IP4ADDR_STRLEN_MAX);
  226. }
  227. /**
  228. * Ascii internet address interpretation routine.
  229. * The value returned is in network order.
  230. *
  231. * @param cp IP address in ascii representation (e.g. "127.0.0.1")
  232. * @return ip address in network order
  233. */
  234. in_addr_t netdev_ipaddr_addr(const char *cp)
  235. {
  236. ip4_addr_t val;
  237. if (netdev_ip4addr_aton(cp, &val)) {
  238. return ip4_addr_get_u32(&val);
  239. }
  240. return (IPADDR_NONE);
  241. }
  242. #endif /* NETDEV_IPV4 */
  243. #if NETDEV_IPV6
  244. RT_WEAK const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
  245. /**
  246. * Check whether "cp" is a valid ascii representation
  247. * of an IPv6 address and convert to a binary address.
  248. * Returns 1 if the address is valid, 0 if not.
  249. *
  250. * @param cp IPv6 address in ascii representation (e.g. "FF01::1")
  251. * @param addr pointer to which to save the ip address in network order
  252. * @return 1 if cp could be converted to addr, 0 on failure
  253. */
  254. int
  255. netdev_ip6addr_aton(const char *cp, ip6_addr_t *addr)
  256. {
  257. uint32_t addr_index, zero_blocks, current_block_index, current_block_value;
  258. const char *s;
  259. /* Count the number of colons, to count the number of blocks in a "::" sequence
  260. zero_blocks may be 1 even if there are no :: sequences */
  261. zero_blocks = 8;
  262. for (s = cp; *s != 0; s++)
  263. {
  264. if (*s == ':')
  265. {
  266. zero_blocks--;
  267. }
  268. else if (!isxdigit(*s))
  269. {
  270. break;
  271. }
  272. }
  273. /* parse each block */
  274. addr_index = 0;
  275. current_block_index = 0;
  276. current_block_value = 0;
  277. for (s = cp; *s != 0; s++)
  278. {
  279. if (*s == ':')
  280. {
  281. if (addr)
  282. {
  283. if (current_block_index & 0x1)
  284. {
  285. addr->addr[addr_index++] |= current_block_value;
  286. }
  287. else
  288. {
  289. addr->addr[addr_index] = current_block_value << 16;
  290. }
  291. }
  292. current_block_index++;
  293. current_block_value = 0;
  294. if (current_block_index > 7)
  295. {
  296. /* address too long! */
  297. return 0;
  298. }
  299. if (s[1] == ':')
  300. {
  301. if (s[2] == ':')
  302. {
  303. /* invalid format: three successive colons */
  304. return 0;
  305. }
  306. s++;
  307. /* "::" found, set zeros */
  308. while (zero_blocks > 0)
  309. {
  310. zero_blocks--;
  311. if (current_block_index & 0x1)
  312. {
  313. addr_index++;
  314. }
  315. else
  316. {
  317. if (addr)
  318. {
  319. addr->addr[addr_index] = 0;
  320. }
  321. }
  322. current_block_index++;
  323. if (current_block_index > 7)
  324. {
  325. /* address too long! */
  326. return 0;
  327. }
  328. }
  329. }
  330. }
  331. else if (isxdigit(*s))
  332. {
  333. /* add current digit */
  334. current_block_value = (current_block_value << 4) +
  335. (isdigit(*s) ? (uint32_t)(*s - '0') : (uint32_t)(10 + (islower(*s) ? *s - 'a' : *s - 'A')));
  336. }
  337. else
  338. {
  339. /* unexpected digit, space? CRLF? */
  340. break;
  341. }
  342. }
  343. if (addr)
  344. {
  345. if (current_block_index & 0x1)
  346. {
  347. addr->addr[addr_index++] |= current_block_value;
  348. }
  349. else
  350. {
  351. addr->addr[addr_index] = current_block_value << 16;
  352. }
  353. }
  354. /* convert to network byte order. */
  355. if (addr)
  356. {
  357. for (addr_index = 0; addr_index < 4; addr_index++)
  358. {
  359. addr->addr[addr_index] = htonl(addr->addr[addr_index]);
  360. }
  361. }
  362. if (current_block_index != 7)
  363. {
  364. return 0;
  365. }
  366. return 1;
  367. }
  368. /**
  369. * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
  370. *
  371. * @param addr ip6 address in network order to convert
  372. * @param buf target buffer where the string is stored
  373. * @param buflen length of buf
  374. * @return either pointer to buf which now holds the ASCII
  375. * representation of addr or NULL if buf was too small
  376. */
  377. char *
  378. netdev_ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen)
  379. {
  380. uint32_t current_block_index, current_block_value, next_block_value;
  381. int32_t i;
  382. uint8_t zero_flag, empty_block_flag;
  383. i = 0;
  384. empty_block_flag = 0; /* used to indicate a zero chain for "::' */
  385. for (current_block_index = 0; current_block_index < 8; current_block_index++)
  386. {
  387. /* get the current 16-bit block */
  388. current_block_value = htonl(addr->addr[current_block_index >> 1]);
  389. if ((current_block_index & 0x1) == 0)
  390. {
  391. current_block_value = current_block_value >> 16;
  392. }
  393. current_block_value &= 0xffff;
  394. /* Check for empty block. */
  395. if (current_block_value == 0)
  396. {
  397. if (current_block_index == 7 && empty_block_flag == 1)
  398. {
  399. /* special case, we must render a ':' for the last block. */
  400. buf[i++] = ':';
  401. if (i >= buflen)
  402. {
  403. return NULL;
  404. }
  405. break;
  406. }
  407. if (empty_block_flag == 0)
  408. {
  409. /* generate empty block "::", but only if more than one contiguous zero block,
  410. * according to current formatting suggestions RFC 5952. */
  411. next_block_value = htonl(addr->addr[(current_block_index + 1) >> 1]);
  412. if ((current_block_index & 0x1) == 0x01)
  413. {
  414. next_block_value = next_block_value >> 16;
  415. }
  416. next_block_value &= 0xffff;
  417. if (next_block_value == 0)
  418. {
  419. empty_block_flag = 1;
  420. buf[i++] = ':';
  421. if (i >= buflen)
  422. {
  423. return NULL;
  424. }
  425. continue; /* move on to next block. */
  426. }
  427. }
  428. else if (empty_block_flag == 1)
  429. {
  430. /* move on to next block. */
  431. continue;
  432. }
  433. }
  434. else if (empty_block_flag == 1)
  435. {
  436. /* Set this flag value so we don't produce multiple empty blocks. */
  437. empty_block_flag = 2;
  438. }
  439. if (current_block_index > 0)
  440. {
  441. buf[i++] = ':';
  442. if (i >= buflen)
  443. {
  444. return NULL;
  445. }
  446. }
  447. if ((current_block_value & 0xf000) == 0)
  448. {
  449. zero_flag = 1;
  450. }
  451. else
  452. {
  453. buf[i++] = xchar(((current_block_value & 0xf000) >> 12));
  454. zero_flag = 0;
  455. if (i >= buflen)
  456. {
  457. return NULL;
  458. }
  459. }
  460. if (((current_block_value & 0xf00) == 0) && (zero_flag))
  461. {
  462. /* do nothing */
  463. }
  464. else
  465. {
  466. buf[i++] = xchar(((current_block_value & 0xf00) >> 8));
  467. zero_flag = 0;
  468. if (i >= buflen)
  469. {
  470. return NULL;
  471. }
  472. }
  473. if (((current_block_value & 0xf0) == 0) && (zero_flag))
  474. {
  475. /* do nothing */
  476. }
  477. else
  478. {
  479. buf[i++] = xchar(((current_block_value & 0xf0) >> 4));
  480. zero_flag = 0;
  481. if (i >= buflen)
  482. {
  483. return NULL;
  484. }
  485. }
  486. buf[i++] = xchar((current_block_value & 0xf));
  487. if (i >= buflen)
  488. {
  489. return NULL;
  490. }
  491. }
  492. buf[i] = 0;
  493. return buf;
  494. }
  495. /**
  496. * Convert numeric IPv6 address into ASCII representation.
  497. * returns ptr to static buffer; not reentrant!
  498. *
  499. * @param addr ip6 address in network order to convert
  500. * @return pointer to a global static (!) buffer that holds the ASCII
  501. * representation of addr
  502. */
  503. char *
  504. netdev_ip6addr_ntoa(const ip6_addr_t *addr)
  505. {
  506. static char str[40];
  507. return netdev_ip6addr_ntoa_r(addr, str, 40);
  508. }
  509. #endif /* NETDEV_IPV6 */
  510. const char *
  511. netdev_inet_ntop(int af, const void *src, char *dst, int32_t size)
  512. {
  513. #define AF_INET 2
  514. #define AF_INET6 10
  515. const char *ret = NULL;
  516. int size_int = (int)size;
  517. if (size_int < 0)
  518. {
  519. return NULL;
  520. }
  521. switch (af)
  522. {
  523. #if NETDEV_IPV4
  524. case AF_INET:
  525. return netdev_ip4addr_ntoa_r((const ip4_addr_t *)src, dst, size_int);
  526. #endif
  527. #if NETDEV_IPV6
  528. case AF_INET6:
  529. return netdev_ip6addr_ntoa_r((const ip6_addr_t *)src, dst, size_int);
  530. #endif
  531. default:
  532. break;
  533. }
  534. return ret;
  535. }
  536. int
  537. netdev_inet_pton(int af, const char *src, void *dst)
  538. {
  539. #define AF_INET 2
  540. #define AF_INET6 10
  541. int err;
  542. switch (af)
  543. {
  544. #if NETDEV_IPV4
  545. case AF_INET:
  546. err = netdev_ip4addr_aton(src, (ip4_addr_t *)dst);
  547. break;
  548. #endif
  549. #if NETDEV_IPV6
  550. case AF_INET6:
  551. {
  552. /* convert into temporary variable since ip6_addr_t might be larger
  553. than in6_addr when scopes are enabled */
  554. ip6_addr_t addr;
  555. err = netdev_ip6addr_aton(src, &addr);
  556. if (err)
  557. {
  558. rt_memcpy(dst, &addr.addr, sizeof(addr.addr));
  559. }
  560. break;
  561. }
  562. #endif
  563. default:
  564. err = -1;
  565. break;
  566. }
  567. return err;
  568. }