netdev_ipaddr.c 15 KB

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