v = (struct sockaddr *)&serv_addr6;
n = sizeof(struct sockaddr_in6);
bzero((char *) &serv_addr6, sizeof(serv_addr6));
- if (iface &&
- interface_to_sa(vhost, iface,
- (struct sockaddr_in *)v, n) < 0) {
- lwsl_err("Unable to find interface %s\n", iface);
- return -1;
- }
-
-#ifndef WIN32
if (iface) {
- struct ifaddrs *addrs, *addr;
- char ip[NI_MAXHOST];
- unsigned int i;
-
- getifaddrs(&addrs);
- for (addr = addrs; addr; addr = addr->ifa_next) {
- if (!addr->ifa_addr ||
- addr->ifa_addr->sa_family != AF_INET6)
- continue;
-
- getnameinfo(addr->ifa_addr,
- sizeof(struct sockaddr_in6),
- ip, sizeof(ip),
- NULL, 0, NI_NUMERICHOST);
-
- i = 0;
- while (ip[i])
- if (ip[i++] == '%') {
- ip[i - 1] = '\0';
- break;
- }
-
- if (!strcmp(ip, iface)) {
- serv_addr6.sin6_scope_id =
- if_nametoindex(addr->ifa_name);
- break;
- }
+ if (interface_to_sa(vhost, iface,
+ (struct sockaddr_in *)v, n) < 0) {
+ lwsl_err("Unable to find interface %s\n", iface);
+ return -1;
}
- freeifaddrs(addrs);
+ serv_addr6.sin6_scope_id = lws_get_addr_scope(iface);
}
-#endif
serv_addr6.sin6_family = AF_INET6;
serv_addr6.sin6_port = htons(port);
return port;
}
+#if defined(LWS_USE_IPV6)
+LWS_EXTERN unsigned long
+lws_get_addr_scope(const char *ipaddr)
+{
+ unsigned long scope = 0;
+
+#ifndef WIN32
+ struct ifaddrs *addrs, *addr;
+ char ip[NI_MAXHOST];
+ unsigned int i;
+
+ getifaddrs(&addrs);
+ for (addr = addrs; addr; addr = addr->ifa_next) {
+ if (!addr->ifa_addr ||
+ addr->ifa_addr->sa_family != AF_INET6)
+ continue;
+
+ getnameinfo(addr->ifa_addr,
+ sizeof(struct sockaddr_in6),
+ ip, sizeof(ip),
+ NULL, 0, NI_NUMERICHOST);
+
+ i = 0;
+ while (ip[i])
+ if (ip[i++] == '%') {
+ ip[i - 1] = '\0';
+ break;
+ }
+
+ if (!strcmp(ip, ipaddr)) {
+ scope = if_nametoindex(addr->ifa_name);
+ break;
+ }
+ }
+ freeifaddrs(addrs);
+#else
+ PIP_ADAPTER_ADDRESSES adapter, addrs = NULL;
+ PIP_ADAPTER_UNICAST_ADDRESS addr;
+ ULONG size = 0;
+ DWORD ret;
+ struct sockaddr_in6 *sockaddr;
+ char ip[NI_MAXHOST];
+ unsigned int i;
+ int found = 0;
+
+ for (i = 0; i < 5; i++)
+ {
+ ret = GetAdaptersAddresses(AF_INET6, GAA_FLAG_INCLUDE_PREFIX,
+ NULL, addrs, &size);
+ if ((ret == NO_ERROR) || (ret == ERROR_NO_DATA)) {
+ break;
+ } else if (ret == ERROR_BUFFER_OVERFLOW)
+ {
+ if (addrs)
+ free(addrs);
+ addrs = (IP_ADAPTER_ADDRESSES *) malloc(size);
+ } else
+ {
+ if (addrs)
+ {
+ free(addrs);
+ addrs = NULL;
+ }
+ lwsl_err("Failed to get IPv6 address table (%d)", ret);
+ break;
+ }
+ }
+
+ if ((ret == NO_ERROR) && (addrs))
+ {
+ adapter = addrs;
+ while ((adapter) && (!found))
+ {
+ addr = adapter->FirstUnicastAddress;
+ while ((addr) && (!found))
+ {
+ if (addr->Address.lpSockaddr->sa_family == AF_INET6)
+ {
+ sockaddr = (struct sockaddr_in6 *) (addr->Address.lpSockaddr);
+
+ lws_plat_inet_ntop(sockaddr->sin6_family, &sockaddr->sin6_addr,
+ ip, sizeof(ip));
+
+ if (!strcmp(ip, ipaddr)) {
+ scope = sockaddr->sin6_scope_id;
+ found = 1;
+ break;
+ }
+ }
+ addr = addr->Next;
+ }
+ adapter = adapter->Next;
+ }
+ }
+ if (addrs)
+ free(addrs);
+#endif
+
+ return scope;
+}
+#endif
+
LWS_EXTERN void
lws_restart_ws_ping_pong_timer(struct lws *wsi)
{
return inet_ntop(af, src, dst, cnt);
}
+LWS_VISIBLE int
+lws_plat_inet_pton(int af, const char *src, void *dst)
+{
+ return 1; // inet_pton(af, src, dst);
+}
+
LWS_VISIBLE lws_fop_fd_t IRAM_ATTR
_lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
const char *vpath, lws_fop_flags_t *flags)
}
LWS_VISIBLE int
+lws_plat_inet_pton(int af, const char *src, void *dst)
+{
+ //return inet_pton(af, src, dst);
+ return 1;
+}
+
+LWS_VISIBLE int
lws_plat_init(struct lws_context *context,
struct lws_context_creation_info *info)
{
return "lws_plat_inet_ntop";
}
+LWS_VISIBLE int
+lws_plat_inet_pton(int af, const char *src, void *dst)
+{
+ //return inet_pton(af, src, dst);
+ return 1;
+}
+
LWS_VISIBLE lws_fop_fd_t
_lws_plat_file_open(lws_plat_file_open(struct lws_plat_file_ops *fops,
const char *filename, lws_fop_flags_t *flags)
return inet_ntop(af, src, dst, cnt);
}
+LWS_VISIBLE int
+lws_plat_inet_pton(int af, const char *src, void *dst)
+{
+ return inet_pton(af, src, dst);
+}
+
LWS_VISIBLE lws_fop_fd_t
_lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
const char *vpath, lws_fop_flags_t *flags)
lws_interface_to_sa(int ipv6,
const char *ifname, struct sockaddr_in *addr, size_t addrlen)
{
+#ifdef LWS_USE_IPV6
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
+
+ if (ipv6) {
+ if (lws_plat_inet_pton(AF_INET6, ifname, &addr6->sin6_addr) == 1) {
+ return 0;
+ }
+ }
+#endif
+
long long address = inet_addr(ifname);
if (address == INADDR_NONE) {
return ok ? dst : NULL;
}
+LWS_VISIBLE int
+lws_plat_inet_pton(int af, const char *src, void *dst)
+{
+ WCHAR *buffer;
+ DWORD bufferlen = strlen(src) + 1;
+ BOOL ok = FALSE;
+
+ buffer = lws_malloc(bufferlen * 2);
+ if (!buffer) {
+ lwsl_err("Out of memory\n");
+ return -1;
+ }
+
+ if (MultiByteToWideChar(CP_ACP, 0, src, bufferlen, buffer, bufferlen) <= 0) {
+ lwsl_err("Failed to convert multi byte to wide char\n");
+ lws_free(buffer);
+ return -1;
+ }
+
+ if (af == AF_INET) {
+ struct sockaddr_in dstaddr;
+ int dstaddrlen = sizeof(dstaddr);
+ bzero(&dstaddr, sizeof(dstaddr));
+ dstaddr.sin_family = AF_INET;
+
+ if (!WSAStringToAddressW(buffer, af, 0, (struct sockaddr *) &dstaddr, &dstaddrlen)) {
+ ok = TRUE;
+ memcpy(dst, &dstaddr.sin_addr, sizeof(dstaddr.sin_addr));
+ }
+#ifdef LWS_USE_IPV6
+ } else if (af == AF_INET6) {
+ struct sockaddr_in6 dstaddr;
+ int dstaddrlen = sizeof(dstaddr);
+ bzero(&dstaddr, sizeof(dstaddr));
+ dstaddr.sin6_family = AF_INET6;
+
+ if (!WSAStringToAddressW(buffer, af, 0, (struct sockaddr *) &dstaddr, &dstaddrlen)) {
+ ok = TRUE;
+ memcpy(dst, &dstaddr.sin6_addr, sizeof(dstaddr.sin6_addr));
+ }
+#endif
+ } else
+ lwsl_err("Unsupported type\n");
+
+ if (!ok) {
+ int rv = WSAGetLastError();
+ lwsl_err("WSAAddressToString() : %d\n", rv);
+ }
+
+ lws_free(buffer);
+ return ok ? 1 : -1;
+}
+
LWS_VISIBLE lws_fop_fd_t
_lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
const char *vpath, lws_fop_flags_t *flags)
lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port,
const char *iface);
+#if defined(LWS_USE_IPV6)
+LWS_EXTERN unsigned long
+lws_get_addr_scope(const char *ipaddr);
+#endif
+
LWS_EXTERN void
lws_close_free_wsi(struct lws *wsi, enum lws_close_status);
time_in_microseconds(void);
LWS_EXTERN const char * LWS_WARN_UNUSED_RESULT
lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt);
+LWS_EXTERN int LWS_WARN_UNUSED_RESULT
+lws_plat_inet_pton(int af, const char *src, void *dst);
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
lws_check_utf8(unsigned char *state, unsigned char *buf, size_t len);