mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
iface: score binds
Choose the best fit for iface ip addresses by scoring the unsorted results from getifaddrs()
This commit is contained in:
parent
c11311ff5a
commit
5ddb03d146
2 changed files with 46 additions and 19 deletions
|
@ -260,6 +260,7 @@ lws_socket_bind(struct lws_vhost *vhost, struct lws *wsi,
|
|||
n = sizeof(struct sockaddr_in6);
|
||||
|
||||
memset(&serv_addr6, 0, sizeof(serv_addr6));
|
||||
serv_addr6.sin6_family = AF_INET6;
|
||||
if (iface) {
|
||||
m = interface_to_sa(vhost, iface,
|
||||
(struct sockaddr_in *)v, (unsigned int)n, 1);
|
||||
|
@ -273,16 +274,11 @@ lws_socket_bind(struct lws_vhost *vhost, struct lws *wsi,
|
|||
iface);
|
||||
return m;
|
||||
}
|
||||
if (serv_addr6.sin6_family == AF_INET6)
|
||||
serv_addr6.sin6_scope_id = (unsigned int)
|
||||
lws_get_addr_scope(wsi, iface);
|
||||
} else
|
||||
serv_addr6.sin6_family = AF_INET6;
|
||||
serv_addr6.sin6_scope_id = (unsigned int)htonl((uint32_t)
|
||||
lws_get_addr_scope(wsi, iface));
|
||||
}
|
||||
|
||||
if (serv_addr6.sin6_family == AF_INET6)
|
||||
serv_addr6.sin6_port = (uint16_t)htons((uint16_t)port);
|
||||
else
|
||||
((struct sockaddr_in *)v)->sin_port = (uint16_t)htons((uint16_t)port);
|
||||
serv_addr6.sin6_port = (uint16_t)htons((uint16_t)port);
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -277,6 +277,14 @@ lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags)
|
|||
|
||||
/* cast a struct sockaddr_in6 * into addr for ipv6 */
|
||||
|
||||
enum {
|
||||
IP_SCORE_NONE,
|
||||
IP_SCORE_NONNATIVE,
|
||||
IP_SCORE_IPV6_SCOPE_BASE,
|
||||
/* ipv6 scopes */
|
||||
IP_SCORE_GLOBAL_NATIVE = 18
|
||||
};
|
||||
|
||||
int
|
||||
lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr,
|
||||
size_t addrlen)
|
||||
|
@ -285,8 +293,11 @@ lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr,
|
|||
|
||||
struct ifaddrs *ifr;
|
||||
struct ifaddrs *ifc;
|
||||
#ifdef LWS_WITH_IPV6
|
||||
#if defined(LWS_WITH_IPV6)
|
||||
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
|
||||
unsigned long sco = IP_SCORE_NONE;
|
||||
unsigned long ts;
|
||||
const uint8_t *p;
|
||||
#endif
|
||||
|
||||
if (getifaddrs(&ifr)) {
|
||||
|
@ -294,7 +305,7 @@ lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr,
|
|||
|
||||
return LWS_ITOSA_USABLE;
|
||||
}
|
||||
for (ifc = ifr; ifc != NULL && rc; ifc = ifc->ifa_next) {
|
||||
for (ifc = ifr; ifc != NULL; ifc = ifc->ifa_next) {
|
||||
if (!ifc->ifa_addr || !ifc->ifa_name)
|
||||
continue;
|
||||
|
||||
|
@ -309,13 +320,19 @@ lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr,
|
|||
#if defined(AF_PACKET)
|
||||
case AF_PACKET:
|
||||
/* interface exists but is not usable */
|
||||
rc = LWS_ITOSA_NOT_USABLE;
|
||||
if (rc == LWS_ITOSA_NOT_EXIST)
|
||||
rc = LWS_ITOSA_NOT_USABLE;
|
||||
continue;
|
||||
#endif
|
||||
|
||||
case AF_INET:
|
||||
#ifdef LWS_WITH_IPV6
|
||||
#if defined(LWS_WITH_IPV6)
|
||||
if (ipv6) {
|
||||
/* any existing solution is better than this */
|
||||
if (sco != IP_SCORE_NONE)
|
||||
break;
|
||||
sco = IP_SCORE_NONNATIVE;
|
||||
rc = LWS_ITOSA_USABLE;
|
||||
/* map IPv4 to IPv6 */
|
||||
memset((char *)&addr6->sin6_addr, 0,
|
||||
sizeof(struct in6_addr));
|
||||
|
@ -325,23 +342,37 @@ lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr,
|
|||
&((struct sockaddr_in *)ifc->ifa_addr)->sin_addr,
|
||||
sizeof(struct in_addr));
|
||||
lwsl_debug("%s: uplevelling ipv4 bind to ipv6\n", __func__);
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
sco = IP_SCORE_GLOBAL_NATIVE;
|
||||
#endif
|
||||
memcpy(addr,
|
||||
(struct sockaddr_in *)ifc->ifa_addr,
|
||||
rc = LWS_ITOSA_USABLE;
|
||||
memcpy(addr, (struct sockaddr_in *)ifc->ifa_addr,
|
||||
sizeof(struct sockaddr_in));
|
||||
break;
|
||||
#ifdef LWS_WITH_IPV6
|
||||
#if defined(LWS_WITH_IPV6)
|
||||
case AF_INET6:
|
||||
p = (const uint8_t *)
|
||||
&((struct sockaddr_in6 *)ifc->ifa_addr)->sin6_addr;
|
||||
ts = IP_SCORE_IPV6_SCOPE_BASE;
|
||||
if (p[0] == 0xff)
|
||||
ts = (unsigned long)(IP_SCORE_IPV6_SCOPE_BASE + (p[1] & 0xf));
|
||||
|
||||
if (sco >= ts)
|
||||
break;
|
||||
|
||||
sco = ts;
|
||||
rc = LWS_ITOSA_USABLE;
|
||||
|
||||
memcpy(&addr6->sin6_addr,
|
||||
&((struct sockaddr_in6 *)ifc->ifa_addr)->sin6_addr,
|
||||
&((struct sockaddr_in6 *)ifc->ifa_addr)->sin6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
rc = LWS_ITOSA_USABLE;
|
||||
}
|
||||
|
||||
freeifaddrs(ifr);
|
||||
|
|
Loading…
Add table
Reference in a new issue