network.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to
  8. * deal in the Software without restriction, including without limitation the
  9. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  10. * sell copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  22. * IN THE SOFTWARE.
  23. */
  24. #include "private-lib-core.h"
  25. #include <errno.h>
  26. #if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE)
  27. static int
  28. interface_to_sa(struct lws_vhost *vh, const char *ifname,
  29. struct sockaddr_in *addr, size_t addrlen, int allow_ipv6)
  30. {
  31. int ipv6 = 0;
  32. #ifdef LWS_WITH_IPV6
  33. if (allow_ipv6)
  34. ipv6 = LWS_IPV6_ENABLED(vh);
  35. #endif
  36. (void)vh;
  37. return lws_interface_to_sa(ipv6, ifname, addr, addrlen);
  38. }
  39. #endif
  40. #ifndef LWS_PLAT_OPTEE
  41. static int
  42. lws_get_addresses(struct lws_vhost *vh, void *ads, char *name,
  43. int name_len, char *rip, int rip_len)
  44. {
  45. struct addrinfo ai, *res;
  46. struct sockaddr_in addr4;
  47. rip[0] = '\0';
  48. name[0] = '\0';
  49. addr4.sin_family = AF_UNSPEC;
  50. #ifdef LWS_WITH_IPV6
  51. if (LWS_IPV6_ENABLED(vh)) {
  52. if (!lws_plat_inet_ntop(AF_INET6,
  53. &((struct sockaddr_in6 *)ads)->sin6_addr,
  54. rip, rip_len)) {
  55. lwsl_err("inet_ntop: %s", strerror(LWS_ERRNO));
  56. return -1;
  57. }
  58. // Strip off the IPv4 to IPv6 header if one exists
  59. if (strncmp(rip, "::ffff:", 7) == 0)
  60. memmove(rip, rip + 7, strlen(rip) - 6);
  61. getnameinfo((struct sockaddr *)ads, sizeof(struct sockaddr_in6),
  62. name, name_len, NULL, 0, 0);
  63. return 0;
  64. } else
  65. #endif
  66. {
  67. struct addrinfo *result;
  68. memset(&ai, 0, sizeof ai);
  69. ai.ai_family = PF_UNSPEC;
  70. ai.ai_socktype = SOCK_STREAM;
  71. #if !defined(LWS_PLAT_FREERTOS)
  72. if (getnameinfo((struct sockaddr *)ads,
  73. sizeof(struct sockaddr_in),
  74. name, name_len, NULL, 0, 0))
  75. return -1;
  76. #endif
  77. if (getaddrinfo(name, NULL, &ai, &result))
  78. return -1;
  79. res = result;
  80. while (addr4.sin_family == AF_UNSPEC && res) {
  81. switch (res->ai_family) {
  82. case AF_INET:
  83. addr4.sin_addr =
  84. ((struct sockaddr_in *)res->ai_addr)->sin_addr;
  85. addr4.sin_family = AF_INET;
  86. break;
  87. }
  88. res = res->ai_next;
  89. }
  90. freeaddrinfo(result);
  91. }
  92. if (addr4.sin_family == AF_UNSPEC)
  93. return -1;
  94. if (lws_plat_inet_ntop(AF_INET, &addr4.sin_addr, rip, rip_len) == NULL)
  95. return -1;
  96. return 0;
  97. }
  98. const char *
  99. lws_get_peer_simple_fd(lws_sockfd_type fd, char *name, size_t namelen)
  100. {
  101. lws_sockaddr46 sa46;
  102. socklen_t len = sizeof(sa46);
  103. if (getpeername(fd, (struct sockaddr *)&sa46, &len) < 0) {
  104. lws_snprintf(name, namelen, "getpeername: %s",
  105. strerror(LWS_ERRNO));
  106. return name;
  107. }
  108. lws_sa46_write_numeric_address(&sa46, name, namelen);
  109. return name;
  110. }
  111. const char *
  112. lws_get_peer_simple(struct lws *wsi, char *name, size_t namelen)
  113. {
  114. wsi = lws_get_network_wsi(wsi);
  115. return lws_get_peer_simple_fd(wsi->desc.sockfd, name, namelen);
  116. }
  117. #endif
  118. void
  119. lws_get_peer_addresses(struct lws *wsi, lws_sockfd_type fd, char *name,
  120. int name_len, char *rip, int rip_len)
  121. {
  122. #ifndef LWS_PLAT_OPTEE
  123. socklen_t len;
  124. #ifdef LWS_WITH_IPV6
  125. struct sockaddr_in6 sin6;
  126. #endif
  127. struct sockaddr_in sin4;
  128. void *p;
  129. rip[0] = '\0';
  130. name[0] = '\0';
  131. #ifdef LWS_WITH_IPV6
  132. if (LWS_IPV6_ENABLED(wsi->a.vhost)) {
  133. len = sizeof(sin6);
  134. p = &sin6;
  135. } else
  136. #endif
  137. {
  138. len = sizeof(sin4);
  139. p = &sin4;
  140. }
  141. if (getpeername(fd, p, &len) < 0) {
  142. lwsl_warn("getpeername: %s\n", strerror(LWS_ERRNO));
  143. goto bail;
  144. }
  145. lws_get_addresses(wsi->a.vhost, p, name, name_len, rip, rip_len);
  146. bail:
  147. #endif
  148. (void)wsi;
  149. (void)fd;
  150. (void)name;
  151. (void)name_len;
  152. (void)rip;
  153. (void)rip_len;
  154. }
  155. /* note: this returns a random port, or one of these <= 0 return codes:
  156. *
  157. * LWS_ITOSA_USABLE: the interface is usable, returned if so and sockfd invalid
  158. * LWS_ITOSA_NOT_EXIST: the requested iface does not even exist
  159. * LWS_ITOSA_NOT_USABLE: the requested iface exists but is not usable (eg, no IP)
  160. * LWS_ITOSA_BUSY: the port at the requested iface + port is already in use
  161. */
  162. int
  163. lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port,
  164. const char *iface, int ipv6_allowed)
  165. {
  166. #ifdef LWS_WITH_UNIX_SOCK
  167. struct sockaddr_un serv_unix;
  168. #endif
  169. #ifdef LWS_WITH_IPV6
  170. struct sockaddr_in6 serv_addr6;
  171. #endif
  172. struct sockaddr_in serv_addr4;
  173. #ifndef LWS_PLAT_OPTEE
  174. socklen_t len = sizeof(struct sockaddr_storage);
  175. #endif
  176. int n;
  177. #if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE)
  178. int m;
  179. #endif
  180. struct sockaddr_storage sin;
  181. struct sockaddr *v;
  182. memset(&sin, 0, sizeof(sin));
  183. #if defined(LWS_WITH_UNIX_SOCK)
  184. if (!port && LWS_UNIX_SOCK_ENABLED(vhost)) {
  185. v = (struct sockaddr *)&serv_unix;
  186. memset(&serv_unix, 0, sizeof(serv_unix));
  187. serv_unix.sun_family = AF_UNIX;
  188. if (!iface)
  189. return LWS_ITOSA_NOT_EXIST;
  190. if (sizeof(serv_unix.sun_path) <= strlen(iface)) {
  191. lwsl_err("\"%s\" too long for UNIX domain socket\n",
  192. iface);
  193. return LWS_ITOSA_NOT_EXIST;
  194. }
  195. n = (int)(sizeof(uint16_t) + strlen(iface));
  196. strcpy(serv_unix.sun_path, iface);
  197. if (serv_unix.sun_path[0] == '@')
  198. serv_unix.sun_path[0] = '\0';
  199. else
  200. unlink(serv_unix.sun_path);
  201. // lwsl_hexdump_notice(v, n);
  202. } else
  203. #endif
  204. #if defined(LWS_WITH_IPV6) && !defined(LWS_PLAT_FREERTOS)
  205. if (ipv6_allowed && LWS_IPV6_ENABLED(vhost)) {
  206. v = (struct sockaddr *)&serv_addr6;
  207. n = sizeof(struct sockaddr_in6);
  208. memset(&serv_addr6, 0, sizeof(serv_addr6));
  209. if (iface) {
  210. m = interface_to_sa(vhost, iface,
  211. (struct sockaddr_in *)v, n, 1);
  212. if (m == LWS_ITOSA_NOT_USABLE) {
  213. lwsl_info("%s: netif %s: Not usable\n",
  214. __func__, iface);
  215. return m;
  216. }
  217. if (m == LWS_ITOSA_NOT_EXIST) {
  218. lwsl_info("%s: netif %s: Does not exist\n",
  219. __func__, iface);
  220. return m;
  221. }
  222. serv_addr6.sin6_scope_id = lws_get_addr_scope(iface);
  223. }
  224. serv_addr6.sin6_family = AF_INET6;
  225. serv_addr6.sin6_port = htons(port);
  226. } else
  227. #endif
  228. {
  229. v = (struct sockaddr *)&serv_addr4;
  230. n = sizeof(serv_addr4);
  231. memset(&serv_addr4, 0, sizeof(serv_addr4));
  232. serv_addr4.sin_addr.s_addr = INADDR_ANY;
  233. serv_addr4.sin_family = AF_INET;
  234. #if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE)
  235. if (iface) {
  236. m = interface_to_sa(vhost, iface,
  237. (struct sockaddr_in *)v, n, 0);
  238. if (m == LWS_ITOSA_NOT_USABLE) {
  239. lwsl_info("%s: netif %s: Not usable\n",
  240. __func__, iface);
  241. return m;
  242. }
  243. if (m == LWS_ITOSA_NOT_EXIST) {
  244. lwsl_info("%s: netif %s: Does not exist\n",
  245. __func__, iface);
  246. return m;
  247. }
  248. }
  249. #endif
  250. serv_addr4.sin_port = htons(port);
  251. } /* ipv4 */
  252. /* just checking for the interface extant */
  253. if (sockfd == LWS_SOCK_INVALID)
  254. return LWS_ITOSA_USABLE;
  255. n = bind(sockfd, v, n);
  256. #ifdef LWS_WITH_UNIX_SOCK
  257. if (n < 0 && LWS_UNIX_SOCK_ENABLED(vhost)) {
  258. lwsl_err("ERROR on binding fd %d to \"%s\" (%d %d)\n",
  259. sockfd, iface, n, LWS_ERRNO);
  260. return LWS_ITOSA_NOT_EXIST;
  261. } else
  262. #endif
  263. if (n < 0) {
  264. int _lws_errno = LWS_ERRNO;
  265. lwsl_err("ERROR on binding fd %d to port %d (%d %d)\n",
  266. sockfd, port, n, _lws_errno);
  267. /* if something already listening, tell caller to fail permanently */
  268. if (_lws_errno == LWS_EADDRINUSE)
  269. return LWS_ITOSA_BUSY;
  270. /* otherwise ask caller to retry later */
  271. return LWS_ITOSA_NOT_EXIST;
  272. }
  273. #if defined(LWS_WITH_UNIX_SOCK) && !defined(WIN32)
  274. if (!port && LWS_UNIX_SOCK_ENABLED(vhost)) {
  275. uid_t uid = vhost->context->uid;
  276. gid_t gid = vhost->context->gid;
  277. if (vhost->unix_socket_perms) {
  278. if (lws_plat_user_colon_group_to_ids(
  279. vhost->unix_socket_perms, &uid, &gid)) {
  280. lwsl_err("%s: Failed to translate %s\n",
  281. __func__, vhost->unix_socket_perms);
  282. return LWS_ITOSA_NOT_EXIST;
  283. }
  284. }
  285. if (iface && iface[0] != '@' && uid && gid) {
  286. if (chown(iface, uid, gid)) {
  287. lwsl_err("%s: failed to set %s perms %u:%u\n",
  288. __func__, iface,
  289. (unsigned int)uid, (unsigned int)gid);
  290. return LWS_ITOSA_NOT_EXIST;
  291. }
  292. lwsl_notice("%s: vh %s unix skt %s perms %u:%u\n",
  293. __func__, vhost->name, iface,
  294. (unsigned int)uid, (unsigned int)gid);
  295. if (chmod(iface, 0660)) {
  296. lwsl_err("%s: failed to set %s to 0600 mode\n",
  297. __func__, iface);
  298. return LWS_ITOSA_NOT_EXIST;
  299. }
  300. }
  301. }
  302. #endif
  303. #ifndef LWS_PLAT_OPTEE
  304. if (getsockname(sockfd, (struct sockaddr *)&sin, &len) == -1)
  305. lwsl_warn("getsockname: %s\n", strerror(LWS_ERRNO));
  306. else
  307. #endif
  308. #if defined(LWS_WITH_IPV6)
  309. port = (sin.ss_family == AF_INET6) ?
  310. ntohs(((struct sockaddr_in6 *) &sin)->sin6_port) :
  311. ntohs(((struct sockaddr_in *) &sin)->sin_port);
  312. #else
  313. {
  314. struct sockaddr_in sain;
  315. memcpy(&sain, &sin, sizeof(sain));
  316. port = ntohs(sain.sin_port);
  317. }
  318. #endif
  319. return port;
  320. }
  321. unsigned int
  322. lws_retry_get_delay_ms(struct lws_context *context,
  323. const lws_retry_bo_t *retry, uint16_t *ctry,
  324. char *conceal)
  325. {
  326. uint64_t ms = 3000, pc = 30; /* sane-ish defaults if no retry table */
  327. uint16_t ra;
  328. if (conceal)
  329. *conceal = 0;
  330. if (retry) {
  331. if (*ctry < retry->retry_ms_table_count)
  332. ms = retry->retry_ms_table[*ctry];
  333. else
  334. ms = retry->retry_ms_table[
  335. retry->retry_ms_table_count - 1];
  336. /* if no percent given, use the default 30% */
  337. if (retry->jitter_percent)
  338. pc = retry->jitter_percent;
  339. }
  340. if (lws_get_random(context, &ra, sizeof(ra)) == sizeof(ra))
  341. ms += ((ms * pc * ra) >> 16) / 100;
  342. else
  343. assert(0);
  344. if (*ctry < 0xffff)
  345. (*ctry)++;
  346. if (retry && conceal)
  347. *conceal = (int)*ctry <= retry->conceal_count;
  348. return (unsigned int)ms;
  349. }
  350. int
  351. lws_retry_sul_schedule(struct lws_context *context, int tid,
  352. lws_sorted_usec_list_t *sul,
  353. const lws_retry_bo_t *retry, sul_cb_t cb, uint16_t *ctry)
  354. {
  355. char conceal;
  356. uint64_t ms = lws_retry_get_delay_ms(context, retry, ctry, &conceal);
  357. if (!conceal)
  358. return 1;
  359. lwsl_info("%s: sul %p: scheduling retry in %dms\n", __func__, sul,
  360. (int)ms);
  361. lws_sul_schedule(context, tid, sul, cb, ms * 1000);
  362. return 0;
  363. }
  364. int
  365. lws_retry_sul_schedule_retry_wsi(struct lws *wsi, lws_sorted_usec_list_t *sul,
  366. sul_cb_t cb, uint16_t *ctry)
  367. {
  368. return lws_retry_sul_schedule(wsi->a.context, wsi->tsi, sul,
  369. wsi->retry_policy, cb, ctry);
  370. }
  371. #if defined(LWS_WITH_IPV6)
  372. unsigned long
  373. lws_get_addr_scope(const char *ifname_or_ipaddr)
  374. {
  375. unsigned long scope;
  376. char ip[NI_MAXHOST];
  377. unsigned int i;
  378. #if !defined(WIN32)
  379. struct ifaddrs *addrs, *addr;
  380. #else
  381. PIP_ADAPTER_ADDRESSES adapter, addrs = NULL;
  382. PIP_ADAPTER_UNICAST_ADDRESS addr;
  383. struct sockaddr_in6 *sockaddr;
  384. ULONG size = 0;
  385. int found = 0;
  386. DWORD ret;
  387. #endif
  388. /*
  389. * First see if we can look the string up as a network interface name...
  390. * windows vista+ also has this
  391. */
  392. scope = if_nametoindex(ifname_or_ipaddr);
  393. if (scope > 0)
  394. /* we found it from the interface name lookup */
  395. return scope;
  396. /*
  397. * if not, try to look it up as an IP -> interface -> interface index
  398. */
  399. scope = 0;
  400. #if !defined(WIN32)
  401. getifaddrs(&addrs);
  402. for (addr = addrs; addr; addr = addr->ifa_next) {
  403. if (!addr->ifa_addr ||
  404. addr->ifa_addr->sa_family != AF_INET6)
  405. continue;
  406. ip[0] = '\0';
  407. getnameinfo(addr->ifa_addr,
  408. sizeof(struct sockaddr_in6),
  409. ip, sizeof(ip),
  410. NULL, 0, NI_NUMERICHOST);
  411. i = 0;
  412. while (ip[i])
  413. if (ip[i++] == '%') {
  414. ip[i - 1] = '\0';
  415. break;
  416. }
  417. if (!strcmp(ip, ifname_or_ipaddr)) {
  418. scope = if_nametoindex(addr->ifa_name);
  419. break;
  420. }
  421. }
  422. freeifaddrs(addrs);
  423. #else
  424. for (i = 0; i < 5; i++)
  425. {
  426. ret = GetAdaptersAddresses(AF_INET6, GAA_FLAG_INCLUDE_PREFIX,
  427. NULL, addrs, &size);
  428. if ((ret == NO_ERROR) || (ret == ERROR_NO_DATA)) {
  429. break;
  430. } else if (ret == ERROR_BUFFER_OVERFLOW)
  431. {
  432. if (addrs)
  433. free(addrs);
  434. addrs = (IP_ADAPTER_ADDRESSES *)malloc(size);
  435. } else
  436. {
  437. if (addrs)
  438. {
  439. free(addrs);
  440. addrs = NULL;
  441. }
  442. lwsl_err("Failed to get IPv6 address table (%d)", ret);
  443. break;
  444. }
  445. }
  446. if ((ret == NO_ERROR) && (addrs)) {
  447. adapter = addrs;
  448. while (adapter && !found) {
  449. addr = adapter->FirstUnicastAddress;
  450. while (addr && !found) {
  451. if (addr->Address.lpSockaddr->sa_family ==
  452. AF_INET6) {
  453. sockaddr = (struct sockaddr_in6 *)
  454. (addr->Address.lpSockaddr);
  455. lws_plat_inet_ntop(sockaddr->sin6_family,
  456. &sockaddr->sin6_addr,
  457. ip, sizeof(ip));
  458. if (!strcmp(ip, ifname_or_ipaddr)) {
  459. scope = sockaddr->sin6_scope_id;
  460. found = 1;
  461. break;
  462. }
  463. }
  464. addr = addr->Next;
  465. }
  466. adapter = adapter->Next;
  467. }
  468. }
  469. if (addrs)
  470. free(addrs);
  471. #endif
  472. return scope;
  473. }
  474. #endif
  475. /*
  476. * https://en.wikipedia.org/wiki/IPv6_address
  477. *
  478. * An IPv6 address is represented as eight groups of four hexadecimal digits,
  479. * each group representing 16 bits (two octets, a group sometimes also called a
  480. * hextet[6][7]). The groups are separated by colons (:). An example of an IPv6
  481. * address is:
  482. *
  483. * 2001:0db8:85a3:0000:0000:8a2e:0370:7334
  484. *
  485. * The hexadecimal digits are case-insensitive, but IETF recommendations suggest
  486. * the use of lower case letters. The full representation of eight 4-digit
  487. * groups may be simplified by several techniques, eliminating parts of the
  488. * representation.
  489. *
  490. * Leading zeroes in a group may be omitted, but each group must retain at least
  491. * one hexadecimal digit.[1] Thus, the example address may be written as:
  492. *
  493. * 2001:db8:85a3:0:0:8a2e:370:7334
  494. *
  495. * One or more consecutive groups containing zeros only may be replaced with a
  496. * single empty group, using two consecutive colons (::).[1] The substitution
  497. * may only be applied once in the address, however, because multiple
  498. * occurrences would create an ambiguous representation. Thus, the example
  499. * address can be further simplified:
  500. *
  501. * 2001:db8:85a3::8a2e:370:7334
  502. *
  503. * The localhost (loopback) address, 0:0:0:0:0:0:0:1, and the IPv6 unspecified
  504. * address, 0:0:0:0:0:0:0:0, are reduced to ::1 and ::, respectively.
  505. *
  506. * During the transition of the Internet from IPv4 to IPv6, it is typical to
  507. * operate in a mixed addressing environment. For such use cases, a special
  508. * notation has been introduced, which expresses IPv4-mapped and IPv4-compatible
  509. * IPv6 addresses by writing the least-significant 32 bits of an address in the
  510. * familiar IPv4 dot-decimal notation, whereas the other 96 (most significant)
  511. * bits are written in IPv6 format. For example, the IPv4-mapped IPv6 address
  512. * ::ffff:c000:0280 is written as ::ffff:192.0.2.128, thus expressing clearly
  513. * the original IPv4 address that was mapped to IPv6.
  514. */
  515. int
  516. lws_parse_numeric_address(const char *ads, uint8_t *result, size_t max_len)
  517. {
  518. struct lws_tokenize ts;
  519. uint8_t *orig = result, temp[16];
  520. int sects = 0, ipv6 = !!strchr(ads, ':'), skip_point = -1, dm = 0;
  521. char t[5];
  522. size_t n;
  523. long u;
  524. lws_tokenize_init(&ts, ads, LWS_TOKENIZE_F_NO_INTEGERS |
  525. LWS_TOKENIZE_F_MINUS_NONTERM);
  526. ts.len = strlen(ads);
  527. if (!ipv6 && ts.len < 7)
  528. return -1;
  529. if (ipv6 && ts.len < 2)
  530. return -2;
  531. if (!ipv6 && max_len < 4)
  532. return -3;
  533. if (ipv6 && max_len < 16)
  534. return -4;
  535. if (ipv6)
  536. memset(result, 0, max_len);
  537. do {
  538. ts.e = lws_tokenize(&ts);
  539. switch (ts.e) {
  540. case LWS_TOKZE_TOKEN:
  541. dm = 0;
  542. if (ipv6) {
  543. if (ts.token_len > 4)
  544. return -1;
  545. memcpy(t, ts.token, ts.token_len);
  546. t[ts.token_len] = '\0';
  547. for (n = 0; n < ts.token_len; n++)
  548. if (t[n] < '0' || t[n] > 'f' ||
  549. (t[n] > '9' && t[n] < 'A') ||
  550. (t[n] > 'F' && t[n] < 'a'))
  551. return -1;
  552. u = strtol(t, NULL, 16);
  553. if (u > 0xffff)
  554. return -5;
  555. *result++ = (uint8_t)(u >> 8);
  556. } else {
  557. if (ts.token_len > 3)
  558. return -1;
  559. memcpy(t, ts.token, ts.token_len);
  560. t[ts.token_len] = '\0';
  561. for (n = 0; n < ts.token_len; n++)
  562. if (t[n] < '0' || t[n] > '9')
  563. return -1;
  564. u = strtol(t, NULL, 10);
  565. if (u > 0xff)
  566. return -6;
  567. }
  568. if (u < 0)
  569. return -7;
  570. *result++ = (uint8_t)u;
  571. sects++;
  572. break;
  573. case LWS_TOKZE_DELIMITER:
  574. if (dm++) {
  575. if (dm > 2)
  576. return -8;
  577. if (*ts.token != ':')
  578. return -9;
  579. /* back to back : */
  580. *result++ = 0;
  581. *result++ = 0;
  582. skip_point = lws_ptr_diff(result, orig);
  583. break;
  584. }
  585. if (ipv6 && orig[2] == 0xff && orig[3] == 0xff &&
  586. skip_point == 2) {
  587. /* ipv4 backwards compatible format */
  588. ipv6 = 0;
  589. memset(orig, 0, max_len);
  590. orig[10] = 0xff;
  591. orig[11] = 0xff;
  592. skip_point = -1;
  593. result = &orig[12];
  594. sects = 0;
  595. break;
  596. }
  597. if (ipv6 && *ts.token != ':')
  598. return -10;
  599. if (!ipv6 && *ts.token != '.')
  600. return -11;
  601. break;
  602. case LWS_TOKZE_ENDED:
  603. if (!ipv6 && sects == 4)
  604. return lws_ptr_diff(result, orig);
  605. if (ipv6 && sects == 8)
  606. return lws_ptr_diff(result, orig);
  607. if (skip_point != -1) {
  608. int ow = lws_ptr_diff(result, orig);
  609. /*
  610. * contains ...::...
  611. */
  612. if (ow == 16)
  613. return 16;
  614. memcpy(temp, &orig[skip_point], ow - skip_point);
  615. memset(&orig[skip_point], 0, 16 - skip_point);
  616. memcpy(&orig[16 - (ow - skip_point)], temp,
  617. ow - skip_point);
  618. return 16;
  619. }
  620. return -12;
  621. default: /* includes ENDED */
  622. lwsl_err("%s: malformed ip address\n",
  623. __func__);
  624. return -13;
  625. }
  626. } while (ts.e > 0 && result - orig <= (int)max_len);
  627. lwsl_err("%s: ended on e %d\n", __func__, ts.e);
  628. return -14;
  629. }
  630. int
  631. lws_sa46_parse_numeric_address(const char *ads, lws_sockaddr46 *sa46)
  632. {
  633. uint8_t a[16];
  634. int n;
  635. n = lws_parse_numeric_address(ads, a, sizeof(a));
  636. if (n < 0)
  637. return -1;
  638. #if defined(LWS_WITH_IPV6)
  639. if (n == 16) {
  640. sa46->sa6.sin6_family = AF_INET6;
  641. memcpy(sa46->sa6.sin6_addr.s6_addr, a,
  642. sizeof(sa46->sa6.sin6_addr.s6_addr));
  643. return 0;
  644. }
  645. #endif
  646. if (n != 4)
  647. return -1;
  648. sa46->sa4.sin_family = AF_INET;
  649. memcpy(&sa46->sa4.sin_addr.s_addr, a,
  650. sizeof(sa46->sa4.sin_addr.s_addr));
  651. return 0;
  652. }
  653. int
  654. lws_write_numeric_address(const uint8_t *ads, int size, char *buf, size_t len)
  655. {
  656. char c, elided = 0, soe = 0, zb = -1, n, ipv4 = 0;
  657. const char *e = buf + len;
  658. char *obuf = buf;
  659. int q = 0;
  660. if (size == 4)
  661. return lws_snprintf(buf, len, "%u.%u.%u.%u",
  662. ads[0], ads[1], ads[2], ads[3]);
  663. if (size != 16)
  664. return -1;
  665. for (c = 0; c < (char)size / 2; c++) {
  666. uint16_t v = (ads[q] << 8) | ads[q + 1];
  667. if (buf + 8 > e)
  668. return -1;
  669. q += 2;
  670. if (soe) {
  671. if (v)
  672. *buf++ = ':';
  673. /* fall thru to print hex value */
  674. } else
  675. if (!elided && !soe && !v) {
  676. elided = soe = 1;
  677. zb = c;
  678. continue;
  679. }
  680. if (ipv4) {
  681. n = lws_snprintf(buf, e - buf, "%u.%u",
  682. ads[q - 2], ads[q - 1]);
  683. buf += n;
  684. if (c == 6)
  685. *buf++ = '.';
  686. } else {
  687. if (soe && !v)
  688. continue;
  689. if (c)
  690. *buf++ = ':';
  691. buf += lws_snprintf(buf, e - buf, "%x", v);
  692. if (soe && v) {
  693. soe = 0;
  694. if (c == 5 && v == 0xffff && !zb) {
  695. ipv4 = 1;
  696. *buf++ = ':';
  697. }
  698. }
  699. }
  700. }
  701. if (buf + 3 > e)
  702. return -1;
  703. if (soe) { /* as is the case for all zeros */
  704. *buf++ = ':';
  705. *buf++ = ':';
  706. *buf = '\0';
  707. }
  708. return lws_ptr_diff(buf, obuf);
  709. }
  710. int
  711. lws_sa46_write_numeric_address(lws_sockaddr46 *sa46, char *buf, size_t len)
  712. {
  713. *buf = '\0';
  714. #if defined(LWS_WITH_IPV6)
  715. if (sa46->sa4.sin_family == AF_INET6)
  716. return lws_write_numeric_address(
  717. (uint8_t *)&sa46->sa6.sin6_addr, 16, buf, len);
  718. #endif
  719. if (sa46->sa4.sin_family == AF_INET)
  720. return lws_write_numeric_address(
  721. (uint8_t *)&sa46->sa4.sin_addr, 4, buf, len);
  722. return -1;
  723. }
  724. int
  725. lws_sa46_compare_ads(const lws_sockaddr46 *sa46a, const lws_sockaddr46 *sa46b)
  726. {
  727. if (sa46a->sa4.sin_family != sa46b->sa4.sin_family)
  728. return 1;
  729. #if defined(LWS_WITH_IPV6)
  730. if (sa46a->sa4.sin_family == AF_INET6)
  731. return memcmp(&sa46a->sa6.sin6_addr, &sa46b->sa6.sin6_addr, 16);
  732. #endif
  733. return sa46a->sa4.sin_addr.s_addr != sa46b->sa4.sin_addr.s_addr;
  734. }
  735. #if defined(LWS_WITH_SYS_STATE)
  736. lws_state_manager_t *
  737. lws_system_get_state_manager(struct lws_context *context)
  738. {
  739. return &context->mgr_system;
  740. }
  741. #endif