summaryrefslogtreecommitdiff
path: root/evutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'evutil.c')
-rw-r--r--evutil.c54
1 files changed, 50 insertions, 4 deletions
diff --git a/evutil.c b/evutil.c
index 3412c2ae..9817f086 100644
--- a/evutil.c
+++ b/evutil.c
@@ -41,6 +41,7 @@
/* For structs needed by GetAdaptersAddresses */
#define _WIN32_WINNT 0x0501
#include <iphlpapi.h>
+#include <netioapi.h>
#endif
#include <sys/types.h>
@@ -74,6 +75,9 @@
#endif
#include <time.h>
#include <sys/stat.h>
+#ifndef _WIN32
+#include <net/if.h>
+#endif
#ifdef EVENT__HAVE_IFADDRS_H
#include <ifaddrs.h>
#endif
@@ -694,7 +698,7 @@ evutil_check_ifaddrs(void)
"GetAdaptersInfo", but that's deprecated; let's just try
GetAdaptersAddresses and fall back to connect+getsockname.
*/
- HMODULE lib = evutil_load_windows_system_library_(TEXT("ihplapi.dll"));
+ HMODULE lib = evutil_load_windows_system_library_(TEXT("iphlpapi.dll"));
GetAdaptersAddresses_fn_t fn;
ULONG size, res;
IP_ADAPTER_ADDRESSES *addresses = NULL, *address;
@@ -990,6 +994,7 @@ evutil_getaddrinfo_common_(const char *nodename, const char *servname,
struct evutil_addrinfo *hints, struct evutil_addrinfo **res, int *portnum)
{
int port = 0;
+ unsigned int if_index;
const char *pname;
if (nodename == NULL && servname == NULL)
@@ -1063,10 +1068,12 @@ evutil_getaddrinfo_common_(const char *nodename, const char *servname,
if (hints->ai_family == PF_INET6 || hints->ai_family == PF_UNSPEC) {
struct sockaddr_in6 sin6;
memset(&sin6, 0, sizeof(sin6));
- if (1==evutil_inet_pton(AF_INET6, nodename, &sin6.sin6_addr)) {
+ if (1 == evutil_inet_pton_scope(
+ AF_INET6, nodename, &sin6.sin6_addr, &if_index)) {
/* Got an ipv6 address. */
sin6.sin6_family = AF_INET6;
sin6.sin6_port = htons(port);
+ sin6.sin6_scope_id = if_index;
*res = evutil_new_addrinfo_((struct sockaddr*)&sin6,
sizeof(sin6), hints);
if (!*res)
@@ -1982,6 +1989,41 @@ evutil_inet_ntop(int af, const void *src, char *dst, size_t len)
}
int
+evutil_inet_pton_scope(int af, const char *src, void *dst, unsigned *indexp)
+{
+ int r;
+ unsigned if_index;
+ char *check, *cp, *tmp_src;
+
+ *indexp = 0; /* Reasonable default */
+
+ /* Bail out if not IPv6 */
+ if (af != AF_INET6)
+ return evutil_inet_pton(af, src, dst);
+
+ cp = strchr(src, '%');
+
+ /* Bail out if no zone ID */
+ if (cp == NULL)
+ return evutil_inet_pton(af, src, dst);
+
+ if_index = if_nametoindex(cp + 1);
+ if (if_index == 0) {
+ /* Could be numeric */
+ if_index = strtoul(cp + 1, &check, 10);
+ if (check[0] != '\0')
+ return 0;
+ }
+ *indexp = if_index;
+ tmp_src = mm_strdup(src);
+ cp = strchr(tmp_src, '%');
+ *cp = '\0';
+ r = evutil_inet_pton(af, tmp_src, dst);
+ free(tmp_src);
+ return r;
+}
+
+int
evutil_inet_pton(int af, const char *src, void *dst)
{
#if defined(EVENT__HAVE_INET_PTON) && !defined(USE_INTERNAL_PTON)
@@ -2097,6 +2139,7 @@ int
evutil_parse_sockaddr_port(const char *ip_as_string, struct sockaddr *out, int *outlen)
{
int port;
+ unsigned int if_index;
char buf[128];
const char *cp, *addr_part, *port_part;
int is_ipv6;
@@ -2166,10 +2209,13 @@ evutil_parse_sockaddr_port(const char *ip_as_string, struct sockaddr *out, int *
#endif
sin6.sin6_family = AF_INET6;
sin6.sin6_port = htons(port);
- if (1 != evutil_inet_pton(AF_INET6, addr_part, &sin6.sin6_addr))
+ if (1 != evutil_inet_pton_scope(
+ AF_INET6, addr_part, &sin6.sin6_addr, &if_index)) {
return -1;
+ }
if ((int)sizeof(sin6) > *outlen)
return -1;
+ sin6.sin6_scope_id = if_index;
memset(out, 0, *outlen);
memcpy(out, &sin6, sizeof(sin6));
*outlen = sizeof(sin6);
@@ -2323,7 +2369,7 @@ static const unsigned char EVUTIL_TOLOWER_TABLE[256] = {
#define IMPL_CTYPE_FN(name) \
int EVUTIL_##name##_(char c) { \
ev_uint8_t u = c; \
- return !!(EVUTIL_##name##_TABLE[(u >> 5) & 7] & (1 << (u & 31))); \
+ return !!(EVUTIL_##name##_TABLE[(u >> 5) & 7] & (1U << (u & 31))); \
}
IMPL_CTYPE_FN(ISALPHA)
IMPL_CTYPE_FN(ISALNUM)