1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to 8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the 9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions: 12d4afb5ceSopenharmony_ci * 13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in 14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software. 15d4afb5ceSopenharmony_ci * 16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22d4afb5ceSopenharmony_ci * IN THE SOFTWARE. 23d4afb5ceSopenharmony_ci */ 24d4afb5ceSopenharmony_ci 25d4afb5ceSopenharmony_ci#include "private-lib-core.h" 26d4afb5ceSopenharmony_ci#include <errno.h> 27d4afb5ceSopenharmony_ci 28d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE) 29d4afb5ceSopenharmony_cistatic int 30d4afb5ceSopenharmony_ciinterface_to_sa(struct lws_vhost *vh, const char *ifname, 31d4afb5ceSopenharmony_ci struct sockaddr_in *addr, size_t addrlen, int allow_ipv6) 32d4afb5ceSopenharmony_ci{ 33d4afb5ceSopenharmony_ci int ipv6 = 0; 34d4afb5ceSopenharmony_ci#ifdef LWS_WITH_IPV6 35d4afb5ceSopenharmony_ci if (allow_ipv6) 36d4afb5ceSopenharmony_ci ipv6 = LWS_IPV6_ENABLED(vh); 37d4afb5ceSopenharmony_ci#endif 38d4afb5ceSopenharmony_ci (void)vh; 39d4afb5ceSopenharmony_ci 40d4afb5ceSopenharmony_ci return lws_interface_to_sa(ipv6, ifname, addr, addrlen); 41d4afb5ceSopenharmony_ci} 42d4afb5ceSopenharmony_ci#endif 43d4afb5ceSopenharmony_ci 44d4afb5ceSopenharmony_ci#ifndef LWS_PLAT_OPTEE 45d4afb5ceSopenharmony_cistatic int 46d4afb5ceSopenharmony_cilws_get_addresses(struct lws_vhost *vh, void *ads, char *name, 47d4afb5ceSopenharmony_ci int name_len, char *rip, int rip_len) 48d4afb5ceSopenharmony_ci{ 49d4afb5ceSopenharmony_ci struct addrinfo ai, *res; 50d4afb5ceSopenharmony_ci struct sockaddr_in addr4; 51d4afb5ceSopenharmony_ci 52d4afb5ceSopenharmony_ci rip[0] = '\0'; 53d4afb5ceSopenharmony_ci name[0] = '\0'; 54d4afb5ceSopenharmony_ci addr4.sin_family = AF_UNSPEC; 55d4afb5ceSopenharmony_ci 56d4afb5ceSopenharmony_ci#ifdef LWS_WITH_IPV6 57d4afb5ceSopenharmony_ci if (LWS_IPV6_ENABLED(vh)) { 58d4afb5ceSopenharmony_ci if (!lws_plat_inet_ntop(AF_INET6, 59d4afb5ceSopenharmony_ci &((struct sockaddr_in6 *)ads)->sin6_addr, 60d4afb5ceSopenharmony_ci rip, (socklen_t)rip_len)) { 61d4afb5ceSopenharmony_ci lwsl_vhost_err(vh, "inet_ntop: %s", strerror(LWS_ERRNO)); 62d4afb5ceSopenharmony_ci return -1; 63d4afb5ceSopenharmony_ci } 64d4afb5ceSopenharmony_ci 65d4afb5ceSopenharmony_ci // Strip off the IPv4 to IPv6 header if one exists 66d4afb5ceSopenharmony_ci if (strncmp(rip, "::ffff:", 7) == 0) 67d4afb5ceSopenharmony_ci memmove(rip, rip + 7, strlen(rip) - 6); 68d4afb5ceSopenharmony_ci 69d4afb5ceSopenharmony_ci getnameinfo((struct sockaddr *)ads, sizeof(struct sockaddr_in6), 70d4afb5ceSopenharmony_ci name, 71d4afb5ceSopenharmony_ci#if defined(__ANDROID__) 72d4afb5ceSopenharmony_ci (size_t)name_len, 73d4afb5ceSopenharmony_ci#else 74d4afb5ceSopenharmony_ci (socklen_t)name_len, 75d4afb5ceSopenharmony_ci#endif 76d4afb5ceSopenharmony_ci NULL, 0, 0); 77d4afb5ceSopenharmony_ci 78d4afb5ceSopenharmony_ci return 0; 79d4afb5ceSopenharmony_ci } else 80d4afb5ceSopenharmony_ci#endif 81d4afb5ceSopenharmony_ci { 82d4afb5ceSopenharmony_ci struct addrinfo *result; 83d4afb5ceSopenharmony_ci 84d4afb5ceSopenharmony_ci memset(&ai, 0, sizeof ai); 85d4afb5ceSopenharmony_ci ai.ai_family = PF_UNSPEC; 86d4afb5ceSopenharmony_ci ai.ai_socktype = SOCK_STREAM; 87d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_FREERTOS) 88d4afb5ceSopenharmony_ci if (getnameinfo((struct sockaddr *)ads, 89d4afb5ceSopenharmony_ci sizeof(struct sockaddr_in), 90d4afb5ceSopenharmony_ci name, 91d4afb5ceSopenharmony_ci#if defined(__ANDROID__) 92d4afb5ceSopenharmony_ci (size_t)name_len, 93d4afb5ceSopenharmony_ci#else 94d4afb5ceSopenharmony_ci (socklen_t)name_len, 95d4afb5ceSopenharmony_ci#endif 96d4afb5ceSopenharmony_ci NULL, 0, 0)) 97d4afb5ceSopenharmony_ci return -1; 98d4afb5ceSopenharmony_ci#endif 99d4afb5ceSopenharmony_ci 100d4afb5ceSopenharmony_ci if (getaddrinfo(name, NULL, &ai, &result)) 101d4afb5ceSopenharmony_ci return -1; 102d4afb5ceSopenharmony_ci 103d4afb5ceSopenharmony_ci res = result; 104d4afb5ceSopenharmony_ci while (addr4.sin_family == AF_UNSPEC && res) { 105d4afb5ceSopenharmony_ci switch (res->ai_family) { 106d4afb5ceSopenharmony_ci case AF_INET: 107d4afb5ceSopenharmony_ci addr4.sin_addr = 108d4afb5ceSopenharmony_ci ((struct sockaddr_in *)res->ai_addr)->sin_addr; 109d4afb5ceSopenharmony_ci addr4.sin_family = AF_INET; 110d4afb5ceSopenharmony_ci break; 111d4afb5ceSopenharmony_ci } 112d4afb5ceSopenharmony_ci 113d4afb5ceSopenharmony_ci res = res->ai_next; 114d4afb5ceSopenharmony_ci } 115d4afb5ceSopenharmony_ci freeaddrinfo(result); 116d4afb5ceSopenharmony_ci } 117d4afb5ceSopenharmony_ci 118d4afb5ceSopenharmony_ci if (addr4.sin_family == AF_UNSPEC) 119d4afb5ceSopenharmony_ci return -1; 120d4afb5ceSopenharmony_ci 121d4afb5ceSopenharmony_ci if (lws_plat_inet_ntop(AF_INET, &addr4.sin_addr, rip, 122d4afb5ceSopenharmony_ci (socklen_t)rip_len) == NULL) 123d4afb5ceSopenharmony_ci return -1; 124d4afb5ceSopenharmony_ci 125d4afb5ceSopenharmony_ci return 0; 126d4afb5ceSopenharmony_ci} 127d4afb5ceSopenharmony_ci 128d4afb5ceSopenharmony_ciconst char * 129d4afb5ceSopenharmony_cilws_get_peer_simple_fd(lws_sockfd_type fd, char *name, size_t namelen) 130d4afb5ceSopenharmony_ci{ 131d4afb5ceSopenharmony_ci lws_sockaddr46 sa46; 132d4afb5ceSopenharmony_ci socklen_t len = sizeof(sa46); 133d4afb5ceSopenharmony_ci 134d4afb5ceSopenharmony_ci if (getpeername(fd, (struct sockaddr *)&sa46, &len) < 0) { 135d4afb5ceSopenharmony_ci lws_snprintf(name, namelen, "getpeername: %s", 136d4afb5ceSopenharmony_ci strerror(LWS_ERRNO)); 137d4afb5ceSopenharmony_ci return name; 138d4afb5ceSopenharmony_ci } 139d4afb5ceSopenharmony_ci 140d4afb5ceSopenharmony_ci lws_sa46_write_numeric_address(&sa46, name, namelen); 141d4afb5ceSopenharmony_ci 142d4afb5ceSopenharmony_ci return name; 143d4afb5ceSopenharmony_ci} 144d4afb5ceSopenharmony_ci 145d4afb5ceSopenharmony_ciconst char * 146d4afb5ceSopenharmony_cilws_get_peer_simple(struct lws *wsi, char *name, size_t namelen) 147d4afb5ceSopenharmony_ci{ 148d4afb5ceSopenharmony_ci wsi = lws_get_network_wsi(wsi); 149d4afb5ceSopenharmony_ci return lws_get_peer_simple_fd(wsi->desc.sockfd, name, namelen); 150d4afb5ceSopenharmony_ci} 151d4afb5ceSopenharmony_ci#endif 152d4afb5ceSopenharmony_ci 153d4afb5ceSopenharmony_civoid 154d4afb5ceSopenharmony_cilws_get_peer_addresses(struct lws *wsi, lws_sockfd_type fd, char *name, 155d4afb5ceSopenharmony_ci int name_len, char *rip, int rip_len) 156d4afb5ceSopenharmony_ci{ 157d4afb5ceSopenharmony_ci#ifndef LWS_PLAT_OPTEE 158d4afb5ceSopenharmony_ci socklen_t len; 159d4afb5ceSopenharmony_ci#ifdef LWS_WITH_IPV6 160d4afb5ceSopenharmony_ci struct sockaddr_in6 sin6; 161d4afb5ceSopenharmony_ci#endif 162d4afb5ceSopenharmony_ci struct sockaddr_in sin4; 163d4afb5ceSopenharmony_ci void *p; 164d4afb5ceSopenharmony_ci 165d4afb5ceSopenharmony_ci rip[0] = '\0'; 166d4afb5ceSopenharmony_ci name[0] = '\0'; 167d4afb5ceSopenharmony_ci 168d4afb5ceSopenharmony_ci#ifdef LWS_WITH_IPV6 169d4afb5ceSopenharmony_ci if (LWS_IPV6_ENABLED(wsi->a.vhost)) { 170d4afb5ceSopenharmony_ci len = sizeof(sin6); 171d4afb5ceSopenharmony_ci p = &sin6; 172d4afb5ceSopenharmony_ci } else 173d4afb5ceSopenharmony_ci#endif 174d4afb5ceSopenharmony_ci { 175d4afb5ceSopenharmony_ci len = sizeof(sin4); 176d4afb5ceSopenharmony_ci p = &sin4; 177d4afb5ceSopenharmony_ci } 178d4afb5ceSopenharmony_ci 179d4afb5ceSopenharmony_ci if (getpeername(fd, p, &len) < 0) { 180d4afb5ceSopenharmony_ci lwsl_wsi_warn(wsi, "getpeername: %s", strerror(LWS_ERRNO)); 181d4afb5ceSopenharmony_ci goto bail; 182d4afb5ceSopenharmony_ci } 183d4afb5ceSopenharmony_ci 184d4afb5ceSopenharmony_ci lws_get_addresses(wsi->a.vhost, p, name, name_len, rip, rip_len); 185d4afb5ceSopenharmony_ci 186d4afb5ceSopenharmony_cibail: 187d4afb5ceSopenharmony_ci#endif 188d4afb5ceSopenharmony_ci (void)wsi; 189d4afb5ceSopenharmony_ci (void)fd; 190d4afb5ceSopenharmony_ci (void)name; 191d4afb5ceSopenharmony_ci (void)name_len; 192d4afb5ceSopenharmony_ci (void)rip; 193d4afb5ceSopenharmony_ci (void)rip_len; 194d4afb5ceSopenharmony_ci} 195d4afb5ceSopenharmony_ci 196d4afb5ceSopenharmony_ci 197d4afb5ceSopenharmony_ci 198d4afb5ceSopenharmony_ci/* note: this returns a random port, or one of these <= 0 return codes: 199d4afb5ceSopenharmony_ci * 200d4afb5ceSopenharmony_ci * LWS_ITOSA_USABLE: the interface is usable, returned if so and sockfd invalid 201d4afb5ceSopenharmony_ci * LWS_ITOSA_NOT_EXIST: the requested iface does not even exist 202d4afb5ceSopenharmony_ci * LWS_ITOSA_NOT_USABLE: the requested iface exists but is not usable (eg, no IP) 203d4afb5ceSopenharmony_ci * LWS_ITOSA_BUSY: the port at the requested iface + port is already in use 204d4afb5ceSopenharmony_ci */ 205d4afb5ceSopenharmony_ci 206d4afb5ceSopenharmony_ciint 207d4afb5ceSopenharmony_cilws_socket_bind(struct lws_vhost *vhost, struct lws *wsi, 208d4afb5ceSopenharmony_ci lws_sockfd_type sockfd, int port, const char *iface, 209d4afb5ceSopenharmony_ci int af) 210d4afb5ceSopenharmony_ci{ 211d4afb5ceSopenharmony_ci#ifdef LWS_WITH_UNIX_SOCK 212d4afb5ceSopenharmony_ci struct sockaddr_un serv_unix; 213d4afb5ceSopenharmony_ci#endif 214d4afb5ceSopenharmony_ci#ifdef LWS_WITH_IPV6 215d4afb5ceSopenharmony_ci struct sockaddr_in6 serv_addr6; 216d4afb5ceSopenharmony_ci#endif 217d4afb5ceSopenharmony_ci struct sockaddr_in serv_addr4; 218d4afb5ceSopenharmony_ci#ifndef LWS_PLAT_OPTEE 219d4afb5ceSopenharmony_ci socklen_t len = sizeof(struct sockaddr_storage); 220d4afb5ceSopenharmony_ci#endif 221d4afb5ceSopenharmony_ci int n = 0; 222d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE) 223d4afb5ceSopenharmony_ci int m; 224d4afb5ceSopenharmony_ci#endif 225d4afb5ceSopenharmony_ci struct sockaddr_storage sin, *psin = &sin; 226d4afb5ceSopenharmony_ci struct sockaddr *v; 227d4afb5ceSopenharmony_ci 228d4afb5ceSopenharmony_ci memset(&sin, 0, sizeof(sin)); 229d4afb5ceSopenharmony_ci 230d4afb5ceSopenharmony_ci /* if there's a wsi, we want to mark it with our source ads:port */ 231d4afb5ceSopenharmony_ci if (wsi) 232d4afb5ceSopenharmony_ci psin = (struct sockaddr_storage *)&wsi->sa46_local; 233d4afb5ceSopenharmony_ci 234d4afb5ceSopenharmony_ci switch (af) { 235d4afb5ceSopenharmony_ci#if defined(LWS_WITH_UNIX_SOCK) 236d4afb5ceSopenharmony_ci case AF_UNIX: 237d4afb5ceSopenharmony_ci v = (struct sockaddr *)&serv_unix; 238d4afb5ceSopenharmony_ci memset(&serv_unix, 0, sizeof(serv_unix)); 239d4afb5ceSopenharmony_ci serv_unix.sun_family = AF_UNIX; 240d4afb5ceSopenharmony_ci if (!iface) 241d4afb5ceSopenharmony_ci return LWS_ITOSA_NOT_EXIST; 242d4afb5ceSopenharmony_ci if (sizeof(serv_unix.sun_path) <= strlen(iface)) { 243d4afb5ceSopenharmony_ci lwsl_wsi_err(wsi, "\"%s\" too long for UNIX domain socket", 244d4afb5ceSopenharmony_ci iface); 245d4afb5ceSopenharmony_ci return LWS_ITOSA_NOT_EXIST; 246d4afb5ceSopenharmony_ci } 247d4afb5ceSopenharmony_ci n = (int)(sizeof(uint16_t) + strlen(iface)); 248d4afb5ceSopenharmony_ci strcpy(serv_unix.sun_path, iface); 249d4afb5ceSopenharmony_ci if (serv_unix.sun_path[0] == '@') 250d4afb5ceSopenharmony_ci serv_unix.sun_path[0] = '\0'; 251d4afb5ceSopenharmony_ci else 252d4afb5ceSopenharmony_ci unlink(serv_unix.sun_path); 253d4afb5ceSopenharmony_ci 254d4afb5ceSopenharmony_ci // lwsl_hexdump_notice(v, n); 255d4afb5ceSopenharmony_ci break; 256d4afb5ceSopenharmony_ci#endif 257d4afb5ceSopenharmony_ci#if defined(LWS_WITH_IPV6) && !defined(LWS_PLAT_FREERTOS) 258d4afb5ceSopenharmony_ci case AF_INET6: 259d4afb5ceSopenharmony_ci v = (struct sockaddr *)&serv_addr6; 260d4afb5ceSopenharmony_ci n = sizeof(struct sockaddr_in6); 261d4afb5ceSopenharmony_ci 262d4afb5ceSopenharmony_ci memset(&serv_addr6, 0, sizeof(serv_addr6)); 263d4afb5ceSopenharmony_ci serv_addr6.sin6_family = AF_INET6; 264d4afb5ceSopenharmony_ci if (iface) { 265d4afb5ceSopenharmony_ci m = interface_to_sa(vhost, iface, 266d4afb5ceSopenharmony_ci (struct sockaddr_in *)v, (unsigned int)n, 1); 267d4afb5ceSopenharmony_ci if (m == LWS_ITOSA_NOT_USABLE) { 268d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "netif %s: Not usable", 269d4afb5ceSopenharmony_ci iface); 270d4afb5ceSopenharmony_ci return m; 271d4afb5ceSopenharmony_ci } 272d4afb5ceSopenharmony_ci if (m == LWS_ITOSA_NOT_EXIST) { 273d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "netif %s: Does not exist", 274d4afb5ceSopenharmony_ci iface); 275d4afb5ceSopenharmony_ci return m; 276d4afb5ceSopenharmony_ci } 277d4afb5ceSopenharmony_ci serv_addr6.sin6_scope_id = (unsigned int)htonl((uint32_t) 278d4afb5ceSopenharmony_ci lws_get_addr_scope(wsi, iface)); 279d4afb5ceSopenharmony_ci } 280d4afb5ceSopenharmony_ci 281d4afb5ceSopenharmony_ci serv_addr6.sin6_port = (uint16_t)htons((uint16_t)port); 282d4afb5ceSopenharmony_ci break; 283d4afb5ceSopenharmony_ci#endif 284d4afb5ceSopenharmony_ci 285d4afb5ceSopenharmony_ci case AF_INET: 286d4afb5ceSopenharmony_ci v = (struct sockaddr *)&serv_addr4; 287d4afb5ceSopenharmony_ci n = sizeof(serv_addr4); 288d4afb5ceSopenharmony_ci memset(&serv_addr4, 0, sizeof(serv_addr4)); 289d4afb5ceSopenharmony_ci serv_addr4.sin_addr.s_addr = INADDR_ANY; 290d4afb5ceSopenharmony_ci serv_addr4.sin_family = AF_INET; 291d4afb5ceSopenharmony_ci 292d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE) 293d4afb5ceSopenharmony_ci if (iface) { 294d4afb5ceSopenharmony_ci m = interface_to_sa(vhost, iface, 295d4afb5ceSopenharmony_ci (struct sockaddr_in *)v, (unsigned int)n, 0); 296d4afb5ceSopenharmony_ci if (m == LWS_ITOSA_NOT_USABLE) { 297d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "netif %s: Not usable", 298d4afb5ceSopenharmony_ci iface); 299d4afb5ceSopenharmony_ci return m; 300d4afb5ceSopenharmony_ci } 301d4afb5ceSopenharmony_ci if (m == LWS_ITOSA_NOT_EXIST) { 302d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "netif %s: Does not exist", 303d4afb5ceSopenharmony_ci iface); 304d4afb5ceSopenharmony_ci return m; 305d4afb5ceSopenharmony_ci } 306d4afb5ceSopenharmony_ci } 307d4afb5ceSopenharmony_ci#endif 308d4afb5ceSopenharmony_ci serv_addr4.sin_port = htons((uint16_t)(unsigned int)port); 309d4afb5ceSopenharmony_ci break; 310d4afb5ceSopenharmony_ci default: 311d4afb5ceSopenharmony_ci return -1; 312d4afb5ceSopenharmony_ci } /* switch */ 313d4afb5ceSopenharmony_ci 314d4afb5ceSopenharmony_ci /* just checking for the interface extant */ 315d4afb5ceSopenharmony_ci if (sockfd == LWS_SOCK_INVALID) 316d4afb5ceSopenharmony_ci return LWS_ITOSA_USABLE; 317d4afb5ceSopenharmony_ci 318d4afb5ceSopenharmony_ci n = bind(sockfd, v, (socklen_t)n); 319d4afb5ceSopenharmony_ci#ifdef LWS_WITH_UNIX_SOCK 320d4afb5ceSopenharmony_ci if (n < 0 && af == AF_UNIX) { 321d4afb5ceSopenharmony_ci lwsl_wsi_err(wsi, "ERROR on binding fd %d to \"%s\" (%d %d)", 322d4afb5ceSopenharmony_ci sockfd, iface, n, LWS_ERRNO); 323d4afb5ceSopenharmony_ci 324d4afb5ceSopenharmony_ci return LWS_ITOSA_NOT_EXIST; 325d4afb5ceSopenharmony_ci } else 326d4afb5ceSopenharmony_ci#endif 327d4afb5ceSopenharmony_ci if (n < 0) { 328d4afb5ceSopenharmony_ci int _lws_errno = LWS_ERRNO; 329d4afb5ceSopenharmony_ci 330d4afb5ceSopenharmony_ci lwsl_wsi_err(wsi, "ERROR on binding fd %d to port %d (%d %d)", 331d4afb5ceSopenharmony_ci sockfd, port, n, _lws_errno); 332d4afb5ceSopenharmony_ci 333d4afb5ceSopenharmony_ci /* if something already listening, tell caller to fail permanently */ 334d4afb5ceSopenharmony_ci 335d4afb5ceSopenharmony_ci if (_lws_errno == LWS_EADDRINUSE) 336d4afb5ceSopenharmony_ci return LWS_ITOSA_BUSY; 337d4afb5ceSopenharmony_ci 338d4afb5ceSopenharmony_ci /* otherwise ask caller to retry later */ 339d4afb5ceSopenharmony_ci 340d4afb5ceSopenharmony_ci return LWS_ITOSA_NOT_EXIST; 341d4afb5ceSopenharmony_ci } 342d4afb5ceSopenharmony_ci 343d4afb5ceSopenharmony_ci#if defined(LWS_WITH_UNIX_SOCK) && !defined(WIN32) 344d4afb5ceSopenharmony_ci if (af == AF_UNIX) { 345d4afb5ceSopenharmony_ci uid_t uid = vhost->context->uid; 346d4afb5ceSopenharmony_ci gid_t gid = vhost->context->gid; 347d4afb5ceSopenharmony_ci 348d4afb5ceSopenharmony_ci if (vhost->unix_socket_perms) { 349d4afb5ceSopenharmony_ci if (lws_plat_user_colon_group_to_ids( 350d4afb5ceSopenharmony_ci vhost->unix_socket_perms, &uid, &gid)) { 351d4afb5ceSopenharmony_ci lwsl_wsi_err(wsi, "Failed to translate %s", 352d4afb5ceSopenharmony_ci vhost->unix_socket_perms); 353d4afb5ceSopenharmony_ci return LWS_ITOSA_NOT_EXIST; 354d4afb5ceSopenharmony_ci } 355d4afb5ceSopenharmony_ci } 356d4afb5ceSopenharmony_ci if (iface && iface[0] != '@' && uid && gid) { 357d4afb5ceSopenharmony_ci if (chown(iface, uid, gid)) { 358d4afb5ceSopenharmony_ci lwsl_wsi_err(wsi, "failed to set %s perms %u:%u", 359d4afb5ceSopenharmony_ci iface, (unsigned int)uid, 360d4afb5ceSopenharmony_ci (unsigned int)gid); 361d4afb5ceSopenharmony_ci 362d4afb5ceSopenharmony_ci return LWS_ITOSA_NOT_EXIST; 363d4afb5ceSopenharmony_ci } 364d4afb5ceSopenharmony_ci lwsl_wsi_notice(wsi, "vh %s unix skt %s perms %u:%u", 365d4afb5ceSopenharmony_ci vhost->name, iface, 366d4afb5ceSopenharmony_ci (unsigned int)uid, 367d4afb5ceSopenharmony_ci (unsigned int)gid); 368d4afb5ceSopenharmony_ci 369d4afb5ceSopenharmony_ci if (chmod(iface, 0660)) { 370d4afb5ceSopenharmony_ci lwsl_wsi_err(wsi, "0600 mode on %s fail", iface); 371d4afb5ceSopenharmony_ci 372d4afb5ceSopenharmony_ci return LWS_ITOSA_NOT_EXIST; 373d4afb5ceSopenharmony_ci } 374d4afb5ceSopenharmony_ci } 375d4afb5ceSopenharmony_ci } 376d4afb5ceSopenharmony_ci#endif 377d4afb5ceSopenharmony_ci 378d4afb5ceSopenharmony_ci#ifndef LWS_PLAT_OPTEE 379d4afb5ceSopenharmony_ci if (getsockname(sockfd, (struct sockaddr *)psin, &len) == -1) 380d4afb5ceSopenharmony_ci lwsl_wsi_warn(wsi, "getsockname: %s", strerror(LWS_ERRNO)); 381d4afb5ceSopenharmony_ci else 382d4afb5ceSopenharmony_ci#endif 383d4afb5ceSopenharmony_ci#if defined(LWS_WITH_IPV6) 384d4afb5ceSopenharmony_ci port = (sin.ss_family == AF_INET6) ? 385d4afb5ceSopenharmony_ci ntohs(((struct sockaddr_in6 *)psin)->sin6_port) : 386d4afb5ceSopenharmony_ci ntohs(((struct sockaddr_in *)psin)->sin_port); 387d4afb5ceSopenharmony_ci#else 388d4afb5ceSopenharmony_ci { 389d4afb5ceSopenharmony_ci struct sockaddr_in sain; 390d4afb5ceSopenharmony_ci memcpy(&sain, psin, sizeof(sain)); 391d4afb5ceSopenharmony_ci port = ntohs(sain.sin_port); 392d4afb5ceSopenharmony_ci } 393d4afb5ceSopenharmony_ci#endif 394d4afb5ceSopenharmony_ci 395d4afb5ceSopenharmony_ci { 396d4afb5ceSopenharmony_ci char buf[72]; 397d4afb5ceSopenharmony_ci lws_sa46_write_numeric_address((lws_sockaddr46 *)psin, 398d4afb5ceSopenharmony_ci buf, sizeof(buf)); 399d4afb5ceSopenharmony_ci 400d4afb5ceSopenharmony_ci lwsl_vhost_notice(vhost, "source ads %s", buf); 401d4afb5ceSopenharmony_ci } 402d4afb5ceSopenharmony_ci 403d4afb5ceSopenharmony_ci return port; 404d4afb5ceSopenharmony_ci} 405d4afb5ceSopenharmony_ci 406d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT) 407d4afb5ceSopenharmony_ci 408d4afb5ceSopenharmony_ciunsigned int 409d4afb5ceSopenharmony_cilws_retry_get_delay_ms(struct lws_context *context, 410d4afb5ceSopenharmony_ci const lws_retry_bo_t *retry, uint16_t *ctry, 411d4afb5ceSopenharmony_ci char *conceal) 412d4afb5ceSopenharmony_ci{ 413d4afb5ceSopenharmony_ci uint64_t ms = 3000, pc = 30; /* sane-ish defaults if no retry table */ 414d4afb5ceSopenharmony_ci uint16_t ra; 415d4afb5ceSopenharmony_ci 416d4afb5ceSopenharmony_ci if (conceal) 417d4afb5ceSopenharmony_ci *conceal = 0; 418d4afb5ceSopenharmony_ci 419d4afb5ceSopenharmony_ci if (retry) { 420d4afb5ceSopenharmony_ci if (retry->retry_ms_table_count) { 421d4afb5ceSopenharmony_ci if (*ctry < retry->retry_ms_table_count) 422d4afb5ceSopenharmony_ci ms = retry->retry_ms_table[*ctry]; 423d4afb5ceSopenharmony_ci else 424d4afb5ceSopenharmony_ci ms = retry->retry_ms_table[ 425d4afb5ceSopenharmony_ci retry->retry_ms_table_count - 1]; 426d4afb5ceSopenharmony_ci } 427d4afb5ceSopenharmony_ci 428d4afb5ceSopenharmony_ci /* if no percent given, use the default 30% */ 429d4afb5ceSopenharmony_ci if (retry->jitter_percent) 430d4afb5ceSopenharmony_ci pc = retry->jitter_percent; 431d4afb5ceSopenharmony_ci } 432d4afb5ceSopenharmony_ci 433d4afb5ceSopenharmony_ci if (lws_get_random(context, &ra, sizeof(ra)) == sizeof(ra)) 434d4afb5ceSopenharmony_ci ms += ((ms * pc * ra) >> 16) / 100; 435d4afb5ceSopenharmony_ci else 436d4afb5ceSopenharmony_ci assert(0); 437d4afb5ceSopenharmony_ci 438d4afb5ceSopenharmony_ci if (*ctry < 0xffff) 439d4afb5ceSopenharmony_ci (*ctry)++; 440d4afb5ceSopenharmony_ci 441d4afb5ceSopenharmony_ci if (retry && conceal) 442d4afb5ceSopenharmony_ci *conceal = (int)*ctry <= retry->conceal_count; 443d4afb5ceSopenharmony_ci 444d4afb5ceSopenharmony_ci return (unsigned int)ms; 445d4afb5ceSopenharmony_ci} 446d4afb5ceSopenharmony_ci 447d4afb5ceSopenharmony_ciint 448d4afb5ceSopenharmony_cilws_retry_sul_schedule(struct lws_context *context, int tid, 449d4afb5ceSopenharmony_ci lws_sorted_usec_list_t *sul, 450d4afb5ceSopenharmony_ci const lws_retry_bo_t *retry, sul_cb_t cb, uint16_t *ctry) 451d4afb5ceSopenharmony_ci{ 452d4afb5ceSopenharmony_ci char conceal; 453d4afb5ceSopenharmony_ci uint64_t ms = lws_retry_get_delay_ms(context, retry, ctry, &conceal); 454d4afb5ceSopenharmony_ci 455d4afb5ceSopenharmony_ci if (!conceal) 456d4afb5ceSopenharmony_ci return 1; 457d4afb5ceSopenharmony_ci 458d4afb5ceSopenharmony_ci lwsl_cx_info(context, "sul %p: scheduling retry in %dms", sul, (int)ms); 459d4afb5ceSopenharmony_ci 460d4afb5ceSopenharmony_ci lws_sul_schedule(context, tid, sul, cb, (int64_t)(ms * 1000)); 461d4afb5ceSopenharmony_ci 462d4afb5ceSopenharmony_ci return 0; 463d4afb5ceSopenharmony_ci} 464d4afb5ceSopenharmony_ci 465d4afb5ceSopenharmony_ciint 466d4afb5ceSopenharmony_cilws_retry_sul_schedule_retry_wsi(struct lws *wsi, lws_sorted_usec_list_t *sul, 467d4afb5ceSopenharmony_ci sul_cb_t cb, uint16_t *ctry) 468d4afb5ceSopenharmony_ci{ 469d4afb5ceSopenharmony_ci char conceal; 470d4afb5ceSopenharmony_ci lws_usec_t us = lws_retry_get_delay_ms(wsi->a.context, 471d4afb5ceSopenharmony_ci wsi->retry_policy, ctry, 472d4afb5ceSopenharmony_ci &conceal) * LWS_US_PER_MS; 473d4afb5ceSopenharmony_ci 474d4afb5ceSopenharmony_ci if (!conceal) 475d4afb5ceSopenharmony_ci /* if our reties are up, they're up... */ 476d4afb5ceSopenharmony_ci return 1; 477d4afb5ceSopenharmony_ci 478d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) 479d4afb5ceSopenharmony_ci if ( 480d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H1) 481d4afb5ceSopenharmony_ci wsi->role_ops == &role_ops_h1 482d4afb5ceSopenharmony_ci#endif 483d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H1) && defined(LWS_ROLE_H2) 484d4afb5ceSopenharmony_ci || 485d4afb5ceSopenharmony_ci#endif 486d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H2) 487d4afb5ceSopenharmony_ci wsi->role_ops == &role_ops_h2 488d4afb5ceSopenharmony_ci#endif 489d4afb5ceSopenharmony_ci ) 490d4afb5ceSopenharmony_ci /* 491d4afb5ceSopenharmony_ci * Since we're doing it by wsi, we're in a position to check for 492d4afb5ceSopenharmony_ci * http retry-after, it will increase us accordingly if found 493d4afb5ceSopenharmony_ci */ 494d4afb5ceSopenharmony_ci lws_http_check_retry_after(wsi, &us); 495d4afb5ceSopenharmony_ci#endif 496d4afb5ceSopenharmony_ci lws_sul_schedule(wsi->a.context, wsi->tsi, sul, cb, us); 497d4afb5ceSopenharmony_ci 498d4afb5ceSopenharmony_ci return 0; 499d4afb5ceSopenharmony_ci} 500d4afb5ceSopenharmony_ci 501d4afb5ceSopenharmony_ci#endif 502d4afb5ceSopenharmony_ci 503d4afb5ceSopenharmony_ci#if defined(LWS_WITH_IPV6) 504d4afb5ceSopenharmony_ciunsigned long 505d4afb5ceSopenharmony_cilws_get_addr_scope(struct lws *wsi, const char *ifname_or_ipaddr) 506d4afb5ceSopenharmony_ci{ 507d4afb5ceSopenharmony_ci unsigned long scope; 508d4afb5ceSopenharmony_ci char ip[NI_MAXHOST]; 509d4afb5ceSopenharmony_ci unsigned int i; 510d4afb5ceSopenharmony_ci#if !defined(WIN32) 511d4afb5ceSopenharmony_ci struct ifaddrs *addrs, *addr; 512d4afb5ceSopenharmony_ci#else 513d4afb5ceSopenharmony_ci PIP_ADAPTER_ADDRESSES adapter, addrs = NULL; 514d4afb5ceSopenharmony_ci PIP_ADAPTER_UNICAST_ADDRESS addr; 515d4afb5ceSopenharmony_ci struct sockaddr_in6 *sockaddr; 516d4afb5ceSopenharmony_ci ULONG size = 0; 517d4afb5ceSopenharmony_ci int found = 0; 518d4afb5ceSopenharmony_ci DWORD ret; 519d4afb5ceSopenharmony_ci#endif 520d4afb5ceSopenharmony_ci 521d4afb5ceSopenharmony_ci /* 522d4afb5ceSopenharmony_ci * First see if we can look the string up as a network interface name... 523d4afb5ceSopenharmony_ci * windows vista+ also has this 524d4afb5ceSopenharmony_ci */ 525d4afb5ceSopenharmony_ci 526d4afb5ceSopenharmony_ci scope = if_nametoindex(ifname_or_ipaddr); 527d4afb5ceSopenharmony_ci if (scope > 0) 528d4afb5ceSopenharmony_ci /* we found it from the interface name lookup */ 529d4afb5ceSopenharmony_ci return scope; 530d4afb5ceSopenharmony_ci 531d4afb5ceSopenharmony_ci /* 532d4afb5ceSopenharmony_ci * if not, try to look it up as an IP -> interface -> interface index 533d4afb5ceSopenharmony_ci */ 534d4afb5ceSopenharmony_ci 535d4afb5ceSopenharmony_ci scope = 0; 536d4afb5ceSopenharmony_ci 537d4afb5ceSopenharmony_ci#if !defined(WIN32) 538d4afb5ceSopenharmony_ci 539d4afb5ceSopenharmony_ci getifaddrs(&addrs); 540d4afb5ceSopenharmony_ci for (addr = addrs; addr; addr = addr->ifa_next) { 541d4afb5ceSopenharmony_ci if (!addr->ifa_addr || 542d4afb5ceSopenharmony_ci addr->ifa_addr->sa_family != AF_INET6) 543d4afb5ceSopenharmony_ci continue; 544d4afb5ceSopenharmony_ci 545d4afb5ceSopenharmony_ci ip[0] = '\0'; 546d4afb5ceSopenharmony_ci getnameinfo(addr->ifa_addr, sizeof(struct sockaddr_in6), 547d4afb5ceSopenharmony_ci ip, sizeof(ip), NULL, 0, NI_NUMERICHOST); 548d4afb5ceSopenharmony_ci 549d4afb5ceSopenharmony_ci i = 0; 550d4afb5ceSopenharmony_ci while (ip[i]) 551d4afb5ceSopenharmony_ci if (ip[i++] == '%') { 552d4afb5ceSopenharmony_ci ip[i - 1] = '\0'; 553d4afb5ceSopenharmony_ci break; 554d4afb5ceSopenharmony_ci } 555d4afb5ceSopenharmony_ci 556d4afb5ceSopenharmony_ci if (!strcmp(ip, ifname_or_ipaddr)) { 557d4afb5ceSopenharmony_ci scope = if_nametoindex(addr->ifa_name); 558d4afb5ceSopenharmony_ci break; 559d4afb5ceSopenharmony_ci } 560d4afb5ceSopenharmony_ci } 561d4afb5ceSopenharmony_ci freeifaddrs(addrs); 562d4afb5ceSopenharmony_ci#else 563d4afb5ceSopenharmony_ci 564d4afb5ceSopenharmony_ci for (i = 0; i < 5; i++) { 565d4afb5ceSopenharmony_ci ret = GetAdaptersAddresses(AF_INET6, GAA_FLAG_INCLUDE_PREFIX, 566d4afb5ceSopenharmony_ci NULL, addrs, &size); 567d4afb5ceSopenharmony_ci if (ret == NO_ERROR || ret == ERROR_NO_DATA) 568d4afb5ceSopenharmony_ci break; 569d4afb5ceSopenharmony_ci 570d4afb5ceSopenharmony_ci if (addrs) 571d4afb5ceSopenharmony_ci free(addrs); 572d4afb5ceSopenharmony_ci 573d4afb5ceSopenharmony_ci if (ret != ERROR_BUFFER_OVERFLOW) { 574d4afb5ceSopenharmony_ci addrs = NULL; 575d4afb5ceSopenharmony_ci lwsl_wsi_err(wsi, "Get IPv6 ads table fail (%d)", ret); 576d4afb5ceSopenharmony_ci break; 577d4afb5ceSopenharmony_ci } 578d4afb5ceSopenharmony_ci 579d4afb5ceSopenharmony_ci addrs = (IP_ADAPTER_ADDRESSES *)malloc(size); 580d4afb5ceSopenharmony_ci } 581d4afb5ceSopenharmony_ci 582d4afb5ceSopenharmony_ci if ((ret == NO_ERROR) && (addrs)) { 583d4afb5ceSopenharmony_ci adapter = addrs; 584d4afb5ceSopenharmony_ci while (adapter && !found) { 585d4afb5ceSopenharmony_ci addr = adapter->FirstUnicastAddress; 586d4afb5ceSopenharmony_ci while (addr && !found) { 587d4afb5ceSopenharmony_ci if (addr->Address.lpSockaddr->sa_family == 588d4afb5ceSopenharmony_ci AF_INET6) { 589d4afb5ceSopenharmony_ci sockaddr = (struct sockaddr_in6 *) 590d4afb5ceSopenharmony_ci (addr->Address.lpSockaddr); 591d4afb5ceSopenharmony_ci 592d4afb5ceSopenharmony_ci lws_plat_inet_ntop(sockaddr->sin6_family, 593d4afb5ceSopenharmony_ci &sockaddr->sin6_addr, 594d4afb5ceSopenharmony_ci ip, sizeof(ip)); 595d4afb5ceSopenharmony_ci 596d4afb5ceSopenharmony_ci if (!strcmp(ip, ifname_or_ipaddr)) { 597d4afb5ceSopenharmony_ci scope = sockaddr->sin6_scope_id; 598d4afb5ceSopenharmony_ci found = 1; 599d4afb5ceSopenharmony_ci break; 600d4afb5ceSopenharmony_ci } 601d4afb5ceSopenharmony_ci } 602d4afb5ceSopenharmony_ci addr = addr->Next; 603d4afb5ceSopenharmony_ci } 604d4afb5ceSopenharmony_ci adapter = adapter->Next; 605d4afb5ceSopenharmony_ci } 606d4afb5ceSopenharmony_ci } 607d4afb5ceSopenharmony_ci if (addrs) 608d4afb5ceSopenharmony_ci free(addrs); 609d4afb5ceSopenharmony_ci#endif 610d4afb5ceSopenharmony_ci 611d4afb5ceSopenharmony_ci return scope; 612d4afb5ceSopenharmony_ci} 613d4afb5ceSopenharmony_ci#endif 614d4afb5ceSopenharmony_ci 615d4afb5ceSopenharmony_ci/* 616d4afb5ceSopenharmony_ci * https://en.wikipedia.org/wiki/IPv6_address 617d4afb5ceSopenharmony_ci * 618d4afb5ceSopenharmony_ci * An IPv6 address is represented as eight groups of four hexadecimal digits, 619d4afb5ceSopenharmony_ci * each group representing 16 bits (two octets, a group sometimes also called a 620d4afb5ceSopenharmony_ci * hextet[6][7]). The groups are separated by colons (:). An example of an IPv6 621d4afb5ceSopenharmony_ci * address is: 622d4afb5ceSopenharmony_ci * 623d4afb5ceSopenharmony_ci * 2001:0db8:85a3:0000:0000:8a2e:0370:7334 624d4afb5ceSopenharmony_ci * 625d4afb5ceSopenharmony_ci * The hexadecimal digits are case-insensitive, but IETF recommendations suggest 626d4afb5ceSopenharmony_ci * the use of lower case letters. The full representation of eight 4-digit 627d4afb5ceSopenharmony_ci * groups may be simplified by several techniques, eliminating parts of the 628d4afb5ceSopenharmony_ci * representation. 629d4afb5ceSopenharmony_ci * 630d4afb5ceSopenharmony_ci * Leading zeroes in a group may be omitted, but each group must retain at least 631d4afb5ceSopenharmony_ci * one hexadecimal digit.[1] Thus, the example address may be written as: 632d4afb5ceSopenharmony_ci * 633d4afb5ceSopenharmony_ci * 2001:db8:85a3:0:0:8a2e:370:7334 634d4afb5ceSopenharmony_ci * 635d4afb5ceSopenharmony_ci * One or more consecutive groups containing zeros only may be replaced with a 636d4afb5ceSopenharmony_ci * single empty group, using two consecutive colons (::).[1] The substitution 637d4afb5ceSopenharmony_ci * may only be applied once in the address, however, because multiple 638d4afb5ceSopenharmony_ci * occurrences would create an ambiguous representation. Thus, the example 639d4afb5ceSopenharmony_ci * address can be further simplified: 640d4afb5ceSopenharmony_ci * 641d4afb5ceSopenharmony_ci * 2001:db8:85a3::8a2e:370:7334 642d4afb5ceSopenharmony_ci * 643d4afb5ceSopenharmony_ci * The localhost (loopback) address, 0:0:0:0:0:0:0:1, and the IPv6 unspecified 644d4afb5ceSopenharmony_ci * address, 0:0:0:0:0:0:0:0, are reduced to ::1 and ::, respectively. 645d4afb5ceSopenharmony_ci * 646d4afb5ceSopenharmony_ci * During the transition of the Internet from IPv4 to IPv6, it is typical to 647d4afb5ceSopenharmony_ci * operate in a mixed addressing environment. For such use cases, a special 648d4afb5ceSopenharmony_ci * notation has been introduced, which expresses IPv4-mapped and IPv4-compatible 649d4afb5ceSopenharmony_ci * IPv6 addresses by writing the least-significant 32 bits of an address in the 650d4afb5ceSopenharmony_ci * familiar IPv4 dot-decimal notation, whereas the other 96 (most significant) 651d4afb5ceSopenharmony_ci * bits are written in IPv6 format. For example, the IPv4-mapped IPv6 address 652d4afb5ceSopenharmony_ci * ::ffff:c000:0280 is written as ::ffff:192.0.2.128, thus expressing clearly 653d4afb5ceSopenharmony_ci * the original IPv4 address that was mapped to IPv6. 654d4afb5ceSopenharmony_ci */ 655d4afb5ceSopenharmony_ci 656d4afb5ceSopenharmony_ciint 657d4afb5ceSopenharmony_cilws_parse_numeric_address(const char *ads, uint8_t *result, size_t max_len) 658d4afb5ceSopenharmony_ci{ 659d4afb5ceSopenharmony_ci struct lws_tokenize ts; 660d4afb5ceSopenharmony_ci uint8_t *orig = result, temp[16]; 661d4afb5ceSopenharmony_ci int sects = 0, ipv6 = !!strchr(ads, ':'), skip_point = -1, dm = 0; 662d4afb5ceSopenharmony_ci char t[5]; 663d4afb5ceSopenharmony_ci size_t n; 664d4afb5ceSopenharmony_ci long u; 665d4afb5ceSopenharmony_ci 666d4afb5ceSopenharmony_ci lws_tokenize_init(&ts, ads, LWS_TOKENIZE_F_NO_INTEGERS | 667d4afb5ceSopenharmony_ci LWS_TOKENIZE_F_MINUS_NONTERM); 668d4afb5ceSopenharmony_ci ts.len = strlen(ads); 669d4afb5ceSopenharmony_ci if (!ipv6 && ts.len < 7) 670d4afb5ceSopenharmony_ci return -1; 671d4afb5ceSopenharmony_ci 672d4afb5ceSopenharmony_ci if (ipv6 && ts.len < 2) 673d4afb5ceSopenharmony_ci return -2; 674d4afb5ceSopenharmony_ci 675d4afb5ceSopenharmony_ci if (!ipv6 && max_len < 4) 676d4afb5ceSopenharmony_ci return -3; 677d4afb5ceSopenharmony_ci 678d4afb5ceSopenharmony_ci if (ipv6 && max_len < 16) 679d4afb5ceSopenharmony_ci return -4; 680d4afb5ceSopenharmony_ci 681d4afb5ceSopenharmony_ci if (ipv6) 682d4afb5ceSopenharmony_ci memset(result, 0, max_len); 683d4afb5ceSopenharmony_ci 684d4afb5ceSopenharmony_ci do { 685d4afb5ceSopenharmony_ci ts.e = (int8_t)lws_tokenize(&ts); 686d4afb5ceSopenharmony_ci switch (ts.e) { 687d4afb5ceSopenharmony_ci case LWS_TOKZE_TOKEN: 688d4afb5ceSopenharmony_ci dm = 0; 689d4afb5ceSopenharmony_ci if (ipv6) { 690d4afb5ceSopenharmony_ci if (ts.token_len > 4) 691d4afb5ceSopenharmony_ci return -1; 692d4afb5ceSopenharmony_ci memcpy(t, ts.token, ts.token_len); 693d4afb5ceSopenharmony_ci t[ts.token_len] = '\0'; 694d4afb5ceSopenharmony_ci for (n = 0; n < ts.token_len; n++) 695d4afb5ceSopenharmony_ci if (t[n] < '0' || t[n] > 'f' || 696d4afb5ceSopenharmony_ci (t[n] > '9' && t[n] < 'A') || 697d4afb5ceSopenharmony_ci (t[n] > 'F' && t[n] < 'a')) 698d4afb5ceSopenharmony_ci return -1; 699d4afb5ceSopenharmony_ci u = strtol(t, NULL, 16); 700d4afb5ceSopenharmony_ci if (u > 0xffff) 701d4afb5ceSopenharmony_ci return -5; 702d4afb5ceSopenharmony_ci *result++ = (uint8_t)(u >> 8); 703d4afb5ceSopenharmony_ci } else { 704d4afb5ceSopenharmony_ci if (ts.token_len > 3) 705d4afb5ceSopenharmony_ci return -1; 706d4afb5ceSopenharmony_ci memcpy(t, ts.token, ts.token_len); 707d4afb5ceSopenharmony_ci t[ts.token_len] = '\0'; 708d4afb5ceSopenharmony_ci for (n = 0; n < ts.token_len; n++) 709d4afb5ceSopenharmony_ci if (t[n] < '0' || t[n] > '9') 710d4afb5ceSopenharmony_ci return -1; 711d4afb5ceSopenharmony_ci u = strtol(t, NULL, 10); 712d4afb5ceSopenharmony_ci if (u > 0xff) 713d4afb5ceSopenharmony_ci return -6; 714d4afb5ceSopenharmony_ci } 715d4afb5ceSopenharmony_ci if (u < 0) 716d4afb5ceSopenharmony_ci return -7; 717d4afb5ceSopenharmony_ci *result++ = (uint8_t)u; 718d4afb5ceSopenharmony_ci sects++; 719d4afb5ceSopenharmony_ci break; 720d4afb5ceSopenharmony_ci 721d4afb5ceSopenharmony_ci case LWS_TOKZE_DELIMITER: 722d4afb5ceSopenharmony_ci if (dm++) { 723d4afb5ceSopenharmony_ci if (dm > 2) 724d4afb5ceSopenharmony_ci return -8; 725d4afb5ceSopenharmony_ci if (*ts.token != ':') 726d4afb5ceSopenharmony_ci return -9; 727d4afb5ceSopenharmony_ci /* back to back : */ 728d4afb5ceSopenharmony_ci *result++ = 0; 729d4afb5ceSopenharmony_ci *result++ = 0; 730d4afb5ceSopenharmony_ci skip_point = lws_ptr_diff(result, orig); 731d4afb5ceSopenharmony_ci break; 732d4afb5ceSopenharmony_ci } 733d4afb5ceSopenharmony_ci if (ipv6 && orig[2] == 0xff && orig[3] == 0xff && 734d4afb5ceSopenharmony_ci skip_point == 2) { 735d4afb5ceSopenharmony_ci /* ipv4 backwards compatible format */ 736d4afb5ceSopenharmony_ci ipv6 = 0; 737d4afb5ceSopenharmony_ci memset(orig, 0, max_len); 738d4afb5ceSopenharmony_ci orig[10] = 0xff; 739d4afb5ceSopenharmony_ci orig[11] = 0xff; 740d4afb5ceSopenharmony_ci skip_point = -1; 741d4afb5ceSopenharmony_ci result = &orig[12]; 742d4afb5ceSopenharmony_ci sects = 0; 743d4afb5ceSopenharmony_ci break; 744d4afb5ceSopenharmony_ci } 745d4afb5ceSopenharmony_ci if (ipv6 && *ts.token != ':') 746d4afb5ceSopenharmony_ci return -10; 747d4afb5ceSopenharmony_ci if (!ipv6 && *ts.token != '.') 748d4afb5ceSopenharmony_ci return -11; 749d4afb5ceSopenharmony_ci break; 750d4afb5ceSopenharmony_ci 751d4afb5ceSopenharmony_ci case LWS_TOKZE_ENDED: 752d4afb5ceSopenharmony_ci if (!ipv6 && sects == 4) 753d4afb5ceSopenharmony_ci return lws_ptr_diff(result, orig); 754d4afb5ceSopenharmony_ci if (ipv6 && sects == 8) 755d4afb5ceSopenharmony_ci return lws_ptr_diff(result, orig); 756d4afb5ceSopenharmony_ci if (skip_point != -1) { 757d4afb5ceSopenharmony_ci int ow = lws_ptr_diff(result, orig); 758d4afb5ceSopenharmony_ci /* 759d4afb5ceSopenharmony_ci * contains ...::... 760d4afb5ceSopenharmony_ci */ 761d4afb5ceSopenharmony_ci if (ow == 16) 762d4afb5ceSopenharmony_ci return 16; 763d4afb5ceSopenharmony_ci memcpy(temp, &orig[skip_point], (unsigned int)(ow - skip_point)); 764d4afb5ceSopenharmony_ci memset(&orig[skip_point], 0, (unsigned int)(16 - skip_point)); 765d4afb5ceSopenharmony_ci memcpy(&orig[16 - (ow - skip_point)], temp, 766d4afb5ceSopenharmony_ci (unsigned int)(ow - skip_point)); 767d4afb5ceSopenharmony_ci 768d4afb5ceSopenharmony_ci return 16; 769d4afb5ceSopenharmony_ci } 770d4afb5ceSopenharmony_ci return -12; 771d4afb5ceSopenharmony_ci 772d4afb5ceSopenharmony_ci default: /* includes ENDED */ 773d4afb5ceSopenharmony_ci lwsl_err("%s: malformed ip address\n", 774d4afb5ceSopenharmony_ci __func__); 775d4afb5ceSopenharmony_ci 776d4afb5ceSopenharmony_ci return -13; 777d4afb5ceSopenharmony_ci } 778d4afb5ceSopenharmony_ci } while (ts.e > 0 && result - orig <= (int)max_len); 779d4afb5ceSopenharmony_ci 780d4afb5ceSopenharmony_ci lwsl_err("%s: ended on e %d\n", __func__, ts.e); 781d4afb5ceSopenharmony_ci 782d4afb5ceSopenharmony_ci return -14; 783d4afb5ceSopenharmony_ci} 784d4afb5ceSopenharmony_ci 785d4afb5ceSopenharmony_ciint 786d4afb5ceSopenharmony_cilws_sa46_parse_numeric_address(const char *ads, lws_sockaddr46 *sa46) 787d4afb5ceSopenharmony_ci{ 788d4afb5ceSopenharmony_ci uint8_t a[16]; 789d4afb5ceSopenharmony_ci int n; 790d4afb5ceSopenharmony_ci 791d4afb5ceSopenharmony_ci n = lws_parse_numeric_address(ads, a, sizeof(a)); 792d4afb5ceSopenharmony_ci if (n < 0) 793d4afb5ceSopenharmony_ci return -1; 794d4afb5ceSopenharmony_ci 795d4afb5ceSopenharmony_ci#if defined(LWS_WITH_IPV6) 796d4afb5ceSopenharmony_ci if (n == 16) { 797d4afb5ceSopenharmony_ci sa46->sa6.sin6_family = AF_INET6; 798d4afb5ceSopenharmony_ci memcpy(sa46->sa6.sin6_addr.s6_addr, a, 799d4afb5ceSopenharmony_ci sizeof(sa46->sa6.sin6_addr.s6_addr)); 800d4afb5ceSopenharmony_ci 801d4afb5ceSopenharmony_ci return 0; 802d4afb5ceSopenharmony_ci } 803d4afb5ceSopenharmony_ci#endif 804d4afb5ceSopenharmony_ci 805d4afb5ceSopenharmony_ci if (n != 4) 806d4afb5ceSopenharmony_ci return -1; 807d4afb5ceSopenharmony_ci 808d4afb5ceSopenharmony_ci sa46->sa4.sin_family = AF_INET; 809d4afb5ceSopenharmony_ci memcpy(&sa46->sa4.sin_addr.s_addr, a, 810d4afb5ceSopenharmony_ci sizeof(sa46->sa4.sin_addr.s_addr)); 811d4afb5ceSopenharmony_ci 812d4afb5ceSopenharmony_ci return 0; 813d4afb5ceSopenharmony_ci} 814d4afb5ceSopenharmony_ci 815d4afb5ceSopenharmony_ciint 816d4afb5ceSopenharmony_cilws_write_numeric_address(const uint8_t *ads, int size, char *buf, size_t len) 817d4afb5ceSopenharmony_ci{ 818d4afb5ceSopenharmony_ci char c, elided = 0, soe = 0, zb = (char)-1, n, ipv4 = 0; 819d4afb5ceSopenharmony_ci const char *e = buf + len; 820d4afb5ceSopenharmony_ci char *obuf = buf; 821d4afb5ceSopenharmony_ci int q = 0; 822d4afb5ceSopenharmony_ci 823d4afb5ceSopenharmony_ci if (size == 4) 824d4afb5ceSopenharmony_ci return lws_snprintf(buf, len, "%u.%u.%u.%u", 825d4afb5ceSopenharmony_ci ads[0], ads[1], ads[2], ads[3]); 826d4afb5ceSopenharmony_ci 827d4afb5ceSopenharmony_ci if (size != 16) 828d4afb5ceSopenharmony_ci return -1; 829d4afb5ceSopenharmony_ci 830d4afb5ceSopenharmony_ci for (c = 0; c < (char)size / 2; c++) { 831d4afb5ceSopenharmony_ci uint16_t v = (uint16_t)((ads[q] << 8) | ads[q + 1]); 832d4afb5ceSopenharmony_ci 833d4afb5ceSopenharmony_ci if (buf + 8 > e) 834d4afb5ceSopenharmony_ci return -1; 835d4afb5ceSopenharmony_ci 836d4afb5ceSopenharmony_ci q += 2; 837d4afb5ceSopenharmony_ci if (soe) { 838d4afb5ceSopenharmony_ci if (v) 839d4afb5ceSopenharmony_ci *buf++ = ':'; 840d4afb5ceSopenharmony_ci /* fall thru to print hex value */ 841d4afb5ceSopenharmony_ci } else 842d4afb5ceSopenharmony_ci if (!elided && !soe && !v) { 843d4afb5ceSopenharmony_ci elided = soe = 1; 844d4afb5ceSopenharmony_ci zb = c; 845d4afb5ceSopenharmony_ci continue; 846d4afb5ceSopenharmony_ci } 847d4afb5ceSopenharmony_ci 848d4afb5ceSopenharmony_ci if (ipv4) { 849d4afb5ceSopenharmony_ci n = (char)lws_snprintf(buf, lws_ptr_diff_size_t(e, buf), "%u.%u", 850d4afb5ceSopenharmony_ci ads[q - 2], ads[q - 1]); 851d4afb5ceSopenharmony_ci buf += n; 852d4afb5ceSopenharmony_ci if (c == 6) 853d4afb5ceSopenharmony_ci *buf++ = '.'; 854d4afb5ceSopenharmony_ci } else { 855d4afb5ceSopenharmony_ci if (soe && !v) 856d4afb5ceSopenharmony_ci continue; 857d4afb5ceSopenharmony_ci if (c) 858d4afb5ceSopenharmony_ci *buf++ = ':'; 859d4afb5ceSopenharmony_ci 860d4afb5ceSopenharmony_ci buf += lws_snprintf(buf, lws_ptr_diff_size_t(e, buf), "%x", v); 861d4afb5ceSopenharmony_ci 862d4afb5ceSopenharmony_ci if (soe && v) { 863d4afb5ceSopenharmony_ci soe = 0; 864d4afb5ceSopenharmony_ci if (c == 5 && v == 0xffff && !zb) { 865d4afb5ceSopenharmony_ci ipv4 = 1; 866d4afb5ceSopenharmony_ci *buf++ = ':'; 867d4afb5ceSopenharmony_ci } 868d4afb5ceSopenharmony_ci } 869d4afb5ceSopenharmony_ci } 870d4afb5ceSopenharmony_ci } 871d4afb5ceSopenharmony_ci if (buf + 3 > e) 872d4afb5ceSopenharmony_ci return -1; 873d4afb5ceSopenharmony_ci 874d4afb5ceSopenharmony_ci if (soe) { /* as is the case for all zeros */ 875d4afb5ceSopenharmony_ci *buf++ = ':'; 876d4afb5ceSopenharmony_ci *buf++ = ':'; 877d4afb5ceSopenharmony_ci *buf = '\0'; 878d4afb5ceSopenharmony_ci } 879d4afb5ceSopenharmony_ci 880d4afb5ceSopenharmony_ci return lws_ptr_diff(buf, obuf); 881d4afb5ceSopenharmony_ci} 882d4afb5ceSopenharmony_ci 883d4afb5ceSopenharmony_ciint 884d4afb5ceSopenharmony_cilws_sa46_write_numeric_address(lws_sockaddr46 *sa46, char *buf, size_t len) 885d4afb5ceSopenharmony_ci{ 886d4afb5ceSopenharmony_ci *buf = '\0'; 887d4afb5ceSopenharmony_ci#if defined(LWS_WITH_IPV6) 888d4afb5ceSopenharmony_ci if (sa46->sa4.sin_family == AF_INET6) 889d4afb5ceSopenharmony_ci return lws_write_numeric_address( 890d4afb5ceSopenharmony_ci (uint8_t *)&sa46->sa6.sin6_addr, 16, buf, len); 891d4afb5ceSopenharmony_ci#endif 892d4afb5ceSopenharmony_ci if (sa46->sa4.sin_family == AF_INET) 893d4afb5ceSopenharmony_ci return lws_write_numeric_address( 894d4afb5ceSopenharmony_ci (uint8_t *)&sa46->sa4.sin_addr, 4, buf, len); 895d4afb5ceSopenharmony_ci 896d4afb5ceSopenharmony_ci#if defined(LWS_WITH_UNIX_SOCK) 897d4afb5ceSopenharmony_ci if (sa46->sa4.sin_family == AF_UNIX) 898d4afb5ceSopenharmony_ci return lws_snprintf(buf, len, "(unix skt)"); 899d4afb5ceSopenharmony_ci#endif 900d4afb5ceSopenharmony_ci 901d4afb5ceSopenharmony_ci if (!sa46->sa4.sin_family) 902d4afb5ceSopenharmony_ci return lws_snprintf(buf, len, "(unset)"); 903d4afb5ceSopenharmony_ci 904d4afb5ceSopenharmony_ci if (sa46->sa4.sin_family == AF_INET6) 905d4afb5ceSopenharmony_ci return lws_snprintf(buf, len, "(ipv6 unsupp)"); 906d4afb5ceSopenharmony_ci 907d4afb5ceSopenharmony_ci lws_snprintf(buf, len, "(AF%d unsupp)", (int)sa46->sa4.sin_family); 908d4afb5ceSopenharmony_ci 909d4afb5ceSopenharmony_ci return -1; 910d4afb5ceSopenharmony_ci} 911d4afb5ceSopenharmony_ci 912d4afb5ceSopenharmony_ciint 913d4afb5ceSopenharmony_cilws_sa46_compare_ads(const lws_sockaddr46 *sa46a, const lws_sockaddr46 *sa46b) 914d4afb5ceSopenharmony_ci{ 915d4afb5ceSopenharmony_ci if (sa46a->sa4.sin_family != sa46b->sa4.sin_family) 916d4afb5ceSopenharmony_ci return 1; 917d4afb5ceSopenharmony_ci 918d4afb5ceSopenharmony_ci#if defined(LWS_WITH_IPV6) 919d4afb5ceSopenharmony_ci if (sa46a->sa4.sin_family == AF_INET6) 920d4afb5ceSopenharmony_ci return memcmp(&sa46a->sa6.sin6_addr, &sa46b->sa6.sin6_addr, 16); 921d4afb5ceSopenharmony_ci#endif 922d4afb5ceSopenharmony_ci 923d4afb5ceSopenharmony_ci if (sa46a->sa4.sin_family == AF_INET) 924d4afb5ceSopenharmony_ci return sa46a->sa4.sin_addr.s_addr != sa46b->sa4.sin_addr.s_addr; 925d4afb5ceSopenharmony_ci 926d4afb5ceSopenharmony_ci return 0; 927d4afb5ceSopenharmony_ci} 928d4afb5ceSopenharmony_ci 929d4afb5ceSopenharmony_civoid 930d4afb5ceSopenharmony_cilws_4to6(uint8_t *v6addr, const uint8_t *v4addr) 931d4afb5ceSopenharmony_ci{ 932d4afb5ceSopenharmony_ci v6addr[12] = v4addr[0]; 933d4afb5ceSopenharmony_ci v6addr[13] = v4addr[1]; 934d4afb5ceSopenharmony_ci v6addr[14] = v4addr[2]; 935d4afb5ceSopenharmony_ci v6addr[15] = v4addr[3]; 936d4afb5ceSopenharmony_ci 937d4afb5ceSopenharmony_ci memset(v6addr, 0, 10); 938d4afb5ceSopenharmony_ci 939d4afb5ceSopenharmony_ci v6addr[10] = v6addr[11] = 0xff; 940d4afb5ceSopenharmony_ci} 941d4afb5ceSopenharmony_ci 942d4afb5ceSopenharmony_ci#if defined(LWS_WITH_IPV6) 943d4afb5ceSopenharmony_civoid 944d4afb5ceSopenharmony_cilws_sa46_4to6(lws_sockaddr46 *sa46, const uint8_t *v4addr, uint16_t port) 945d4afb5ceSopenharmony_ci{ 946d4afb5ceSopenharmony_ci sa46->sa4.sin_family = AF_INET6; 947d4afb5ceSopenharmony_ci 948d4afb5ceSopenharmony_ci lws_4to6((uint8_t *)&sa46->sa6.sin6_addr.s6_addr[0], v4addr); 949d4afb5ceSopenharmony_ci 950d4afb5ceSopenharmony_ci sa46->sa6.sin6_port = htons(port); 951d4afb5ceSopenharmony_ci} 952d4afb5ceSopenharmony_ci#endif 953d4afb5ceSopenharmony_ci 954d4afb5ceSopenharmony_ciint 955d4afb5ceSopenharmony_cilws_sa46_on_net(const lws_sockaddr46 *sa46a, const lws_sockaddr46 *sa46_net, 956d4afb5ceSopenharmony_ci int net_len) 957d4afb5ceSopenharmony_ci{ 958d4afb5ceSopenharmony_ci uint8_t mask = 0xff, norm[16]; 959d4afb5ceSopenharmony_ci const uint8_t *p1, *p2; 960d4afb5ceSopenharmony_ci 961d4afb5ceSopenharmony_ci if (sa46a->sa4.sin_family == AF_INET) { 962d4afb5ceSopenharmony_ci p1 = (uint8_t *)&sa46a->sa4.sin_addr; 963d4afb5ceSopenharmony_ci if (sa46_net->sa4.sin_family == AF_INET6) { 964d4afb5ceSopenharmony_ci /* ip is v4, net is v6, promote ip to v6 */ 965d4afb5ceSopenharmony_ci 966d4afb5ceSopenharmony_ci lws_4to6(norm, p1); 967d4afb5ceSopenharmony_ci p1 = norm; 968d4afb5ceSopenharmony_ci } 969d4afb5ceSopenharmony_ci#if defined(LWS_WITH_IPV6) 970d4afb5ceSopenharmony_ci } else 971d4afb5ceSopenharmony_ci if (sa46a->sa4.sin_family == AF_INET6) { 972d4afb5ceSopenharmony_ci p1 = (uint8_t *)&sa46a->sa6.sin6_addr; 973d4afb5ceSopenharmony_ci#endif 974d4afb5ceSopenharmony_ci } else 975d4afb5ceSopenharmony_ci return 1; 976d4afb5ceSopenharmony_ci 977d4afb5ceSopenharmony_ci if (sa46_net->sa4.sin_family == AF_INET) { 978d4afb5ceSopenharmony_ci p2 = (uint8_t *)&sa46_net->sa4.sin_addr; 979d4afb5ceSopenharmony_ci if (sa46a->sa4.sin_family == AF_INET6) { 980d4afb5ceSopenharmony_ci /* ip is v6, net is v4, promote net to v6 */ 981d4afb5ceSopenharmony_ci 982d4afb5ceSopenharmony_ci lws_4to6(norm, p2); 983d4afb5ceSopenharmony_ci p2 = norm; 984d4afb5ceSopenharmony_ci /* because the mask length is for net v4 address */ 985d4afb5ceSopenharmony_ci net_len += 12 * 8; 986d4afb5ceSopenharmony_ci } 987d4afb5ceSopenharmony_ci#if defined(LWS_WITH_IPV6) 988d4afb5ceSopenharmony_ci } else 989d4afb5ceSopenharmony_ci if (sa46a->sa4.sin_family == AF_INET6) { 990d4afb5ceSopenharmony_ci p2 = (uint8_t *)&sa46_net->sa6.sin6_addr; 991d4afb5ceSopenharmony_ci#endif 992d4afb5ceSopenharmony_ci } else 993d4afb5ceSopenharmony_ci return 1; 994d4afb5ceSopenharmony_ci 995d4afb5ceSopenharmony_ci while (net_len > 0) { 996d4afb5ceSopenharmony_ci if (net_len < 8) 997d4afb5ceSopenharmony_ci mask = (uint8_t)(mask << (8 - net_len)); 998d4afb5ceSopenharmony_ci 999d4afb5ceSopenharmony_ci if (((*p1++) & mask) != ((*p2++) & mask)) 1000d4afb5ceSopenharmony_ci return 1; 1001d4afb5ceSopenharmony_ci 1002d4afb5ceSopenharmony_ci net_len -= 8; 1003d4afb5ceSopenharmony_ci } 1004d4afb5ceSopenharmony_ci 1005d4afb5ceSopenharmony_ci return 0; 1006d4afb5ceSopenharmony_ci} 1007d4afb5ceSopenharmony_ci 1008d4afb5ceSopenharmony_civoid 1009d4afb5ceSopenharmony_cilws_sa46_copy_address(lws_sockaddr46 *sa46a, const void *in, int af) 1010d4afb5ceSopenharmony_ci{ 1011d4afb5ceSopenharmony_ci sa46a->sa4.sin_family = (sa_family_t)af; 1012d4afb5ceSopenharmony_ci 1013d4afb5ceSopenharmony_ci if (af == AF_INET) 1014d4afb5ceSopenharmony_ci memcpy(&sa46a->sa4.sin_addr, in, 4); 1015d4afb5ceSopenharmony_ci#if defined(LWS_WITH_IPV6) 1016d4afb5ceSopenharmony_ci else if (af == AF_INET6) 1017d4afb5ceSopenharmony_ci memcpy(&sa46a->sa6.sin6_addr, in, sizeof(sa46a->sa6.sin6_addr)); 1018d4afb5ceSopenharmony_ci#endif 1019d4afb5ceSopenharmony_ci} 1020d4afb5ceSopenharmony_ci 1021d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_STATE) 1022d4afb5ceSopenharmony_cilws_state_manager_t * 1023d4afb5ceSopenharmony_cilws_system_get_state_manager(struct lws_context *context) 1024d4afb5ceSopenharmony_ci{ 1025d4afb5ceSopenharmony_ci return &context->mgr_system; 1026d4afb5ceSopenharmony_ci} 1027d4afb5ceSopenharmony_ci#endif 1028