mirror of
https://github.com/cuberite/libevent.git
synced 2025-08-03 17:26:24 -04:00
Merge branch 'evutil_found_ifaddr-dev'
* evutil_found_ifaddr-dev: Cover evutil_v4addr_is_local_()/evutil_v6addr_is_local_() Split evutil_found_ifaddr() into helpers (evutil_v{4,6}addr_is_local()) Use INADDR_ANY over 0 in evutil_found_ifaddr() Replace EVUTIL_V4ADDR_IS_*() macroses with static inline functions Filter link-local IPv4 addresses in evutil_found_ifaddr() (cherry picked from commit b2667b76969c2ea382373f885062b45e82d0ac59)
This commit is contained in:
parent
cdcfbafe40
commit
b07e43e607
64
evutil.c
64
evutil.c
@ -595,44 +595,56 @@ evutil_socket_finished_connecting_(evutil_socket_t fd)
|
|||||||
set by evutil_check_interfaces. */
|
set by evutil_check_interfaces. */
|
||||||
static int have_checked_interfaces, had_ipv4_address, had_ipv6_address;
|
static int have_checked_interfaces, had_ipv4_address, had_ipv6_address;
|
||||||
|
|
||||||
/* Macro: True iff the IPv4 address 'addr', in host order, is in 127.0.0.0/8
|
/* True iff the IPv4 address 'addr', in host order, is in 127.0.0.0/8 */
|
||||||
*/
|
static inline int evutil_v4addr_is_localhost(ev_uint32_t addr)
|
||||||
#define EVUTIL_V4ADDR_IS_LOCALHOST(addr) (((addr)>>24) == 127)
|
{ return addr>>24 == 127; }
|
||||||
|
|
||||||
/* Macro: True iff the IPv4 address 'addr', in host order, is a class D
|
/* True iff the IPv4 address 'addr', in host order, is link-local
|
||||||
* (multiclass) address.
|
* 169.254.0.0/16 (RFC3927) */
|
||||||
*/
|
static inline int evutil_v4addr_is_linklocal(ev_uint32_t addr)
|
||||||
#define EVUTIL_V4ADDR_IS_CLASSD(addr) ((((addr)>>24) & 0xf0) == 0xe0)
|
{ return ((addr & 0xffff0000U) == 0xa9fe0000U); }
|
||||||
|
|
||||||
|
/* True iff the IPv4 address 'addr', in host order, is a class D
|
||||||
|
* (multiclass) address. */
|
||||||
|
static inline int evutil_v4addr_is_classd(ev_uint32_t addr)
|
||||||
|
{ return ((addr>>24) & 0xf0) == 0xe0; }
|
||||||
|
|
||||||
|
int
|
||||||
|
evutil_v4addr_is_local_(const struct in_addr *in)
|
||||||
|
{
|
||||||
|
const ev_uint32_t addr = ntohl(in->s_addr);
|
||||||
|
return addr == INADDR_ANY ||
|
||||||
|
evutil_v4addr_is_localhost(addr) ||
|
||||||
|
evutil_v4addr_is_linklocal(addr) ||
|
||||||
|
evutil_v4addr_is_classd(addr);
|
||||||
|
}
|
||||||
|
int
|
||||||
|
evutil_v6addr_is_local_(const struct in6_addr *in)
|
||||||
|
{
|
||||||
|
static const char ZEROES[] =
|
||||||
|
"\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||||
|
"\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||||
|
|
||||||
|
const unsigned char *addr = (const unsigned char *)in->s6_addr;
|
||||||
|
return !memcmp(addr, ZEROES, 8) ||
|
||||||
|
((addr[0] & 0xfe) == 0xfc) ||
|
||||||
|
(addr[0] == 0xfe && (addr[1] & 0xc0) == 0x80) ||
|
||||||
|
(addr[0] == 0xfe && (addr[1] & 0xc0) == 0xc0) ||
|
||||||
|
(addr[0] == 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
evutil_found_ifaddr(const struct sockaddr *sa)
|
evutil_found_ifaddr(const struct sockaddr *sa)
|
||||||
{
|
{
|
||||||
const char ZEROES[] = "\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x00\x00\x00\x00";
|
|
||||||
|
|
||||||
if (sa->sa_family == AF_INET) {
|
if (sa->sa_family == AF_INET) {
|
||||||
const struct sockaddr_in *sin = (struct sockaddr_in *)sa;
|
const struct sockaddr_in *sin = (struct sockaddr_in *)sa;
|
||||||
ev_uint32_t addr = ntohl(sin->sin_addr.s_addr);
|
if (!evutil_v4addr_is_local_(&sin->sin_addr)) {
|
||||||
if (addr == 0 ||
|
|
||||||
EVUTIL_V4ADDR_IS_LOCALHOST(addr) ||
|
|
||||||
EVUTIL_V4ADDR_IS_CLASSD(addr)) {
|
|
||||||
/* Not actually a usable external address. */
|
|
||||||
} else {
|
|
||||||
event_debug(("Detected an IPv4 interface"));
|
event_debug(("Detected an IPv4 interface"));
|
||||||
had_ipv4_address = 1;
|
had_ipv4_address = 1;
|
||||||
}
|
}
|
||||||
} else if (sa->sa_family == AF_INET6) {
|
} else if (sa->sa_family == AF_INET6) {
|
||||||
const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
|
const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
|
||||||
const unsigned char *addr =
|
if (!evutil_v6addr_is_local_(&sin6->sin6_addr)) {
|
||||||
(unsigned char*)sin6->sin6_addr.s6_addr;
|
|
||||||
if (!memcmp(addr, ZEROES, 8) ||
|
|
||||||
((addr[0] & 0xfe) == 0xfc) ||
|
|
||||||
(addr[0] == 0xfe && (addr[1] & 0xc0) == 0x80) ||
|
|
||||||
(addr[0] == 0xfe && (addr[1] & 0xc0) == 0xc0) ||
|
|
||||||
(addr[0] == 0xff)) {
|
|
||||||
/* This is a reserved, ipv4compat, ipv4map, loopback,
|
|
||||||
* link-local, multicast, or unspecified address. */
|
|
||||||
} else {
|
|
||||||
event_debug(("Detected an IPv6 interface"));
|
event_debug(("Detected an IPv6 interface"));
|
||||||
had_ipv6_address = 1;
|
had_ipv6_address = 1;
|
||||||
}
|
}
|
||||||
|
@ -1455,6 +1455,83 @@ end:
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_evutil_v4addr_is_local(void *arg)
|
||||||
|
{
|
||||||
|
struct sockaddr_in sin;
|
||||||
|
sin.sin_family = AF_INET;
|
||||||
|
|
||||||
|
/* we use evutil_inet_pton() here to fill in network-byte order */
|
||||||
|
#define LOCAL(str, yes) do { \
|
||||||
|
tt_int_op(evutil_inet_pton(AF_INET, str, &sin.sin_addr), ==, 1); \
|
||||||
|
tt_int_op(evutil_v4addr_is_local_(&sin.sin_addr), ==, yes); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/** any */
|
||||||
|
sin.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
tt_int_op(evutil_v4addr_is_local_(&sin.sin_addr), ==, 1);
|
||||||
|
|
||||||
|
/** loopback */
|
||||||
|
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||||
|
tt_int_op(evutil_v4addr_is_local_(&sin.sin_addr), ==, 1);
|
||||||
|
LOCAL("127.0.0.1", 1);
|
||||||
|
LOCAL("127.255.255.255", 1);
|
||||||
|
LOCAL("121.0.0.1", 0);
|
||||||
|
|
||||||
|
/** link-local */
|
||||||
|
LOCAL("169.254.0.1", 1);
|
||||||
|
LOCAL("169.254.255.255", 1);
|
||||||
|
LOCAL("170.0.0.0", 0);
|
||||||
|
|
||||||
|
/** Multicast */
|
||||||
|
LOCAL("224.0.0.0", 1);
|
||||||
|
LOCAL("239.255.255.255", 1);
|
||||||
|
LOCAL("240.0.0.0", 0);
|
||||||
|
end:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_evutil_v6addr_is_local(void *arg)
|
||||||
|
{
|
||||||
|
struct sockaddr_in6 sin6;
|
||||||
|
struct in6_addr anyaddr = IN6ADDR_ANY_INIT;
|
||||||
|
struct in6_addr loopback = IN6ADDR_LOOPBACK_INIT;
|
||||||
|
|
||||||
|
sin6.sin6_family = AF_INET6;
|
||||||
|
#define LOCAL6(str, yes) do { \
|
||||||
|
tt_int_op(evutil_inet_pton(AF_INET6, str, &sin6.sin6_addr), ==, 1);\
|
||||||
|
tt_int_op(evutil_v6addr_is_local_(&sin6.sin6_addr), ==, yes); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/** any */
|
||||||
|
tt_int_op(evutil_v6addr_is_local_(&anyaddr), ==, 1);
|
||||||
|
LOCAL6("::0", 1);
|
||||||
|
|
||||||
|
/** loopback */
|
||||||
|
tt_int_op(evutil_v6addr_is_local_(&loopback), ==, 1);
|
||||||
|
LOCAL6("::1", 1);
|
||||||
|
|
||||||
|
/** IPV4 mapped */
|
||||||
|
LOCAL6("::ffff:0:0", 1);
|
||||||
|
/** IPv4 translated */
|
||||||
|
LOCAL6("::ffff:0:0:0", 1);
|
||||||
|
/** IPv4/IPv6 translation */
|
||||||
|
LOCAL6("64:ff9b::", 0);
|
||||||
|
/** Link-local */
|
||||||
|
LOCAL6("fe80::", 1);
|
||||||
|
/** Multicast */
|
||||||
|
LOCAL6("ff00::", 1);
|
||||||
|
/** Unspecified */
|
||||||
|
LOCAL6("::", 1);
|
||||||
|
|
||||||
|
/** Global Internet */
|
||||||
|
LOCAL6("2001::", 0);
|
||||||
|
LOCAL6("2001:4860:4802:32::1b", 0);
|
||||||
|
end:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
struct testcase_t util_testcases[] = {
|
struct testcase_t util_testcases[] = {
|
||||||
{ "ipv4_parse", regress_ipv4_parse, 0, NULL, NULL },
|
{ "ipv4_parse", regress_ipv4_parse, 0, NULL, NULL },
|
||||||
{ "ipv6_parse", regress_ipv6_parse, 0, NULL, NULL },
|
{ "ipv6_parse", regress_ipv6_parse, 0, NULL, NULL },
|
||||||
@ -1486,6 +1563,8 @@ struct testcase_t util_testcases[] = {
|
|||||||
{ "monotonic_prc_precise", test_evutil_monotonic_prc, 0, &basic_setup, (void*)"precise" },
|
{ "monotonic_prc_precise", test_evutil_monotonic_prc, 0, &basic_setup, (void*)"precise" },
|
||||||
{ "monotonic_prc_fallback", test_evutil_monotonic_prc, 0, &basic_setup, (void*)"fallback" },
|
{ "monotonic_prc_fallback", test_evutil_monotonic_prc, 0, &basic_setup, (void*)"fallback" },
|
||||||
{ "date_rfc1123", test_evutil_date_rfc1123, 0, NULL, NULL },
|
{ "date_rfc1123", test_evutil_date_rfc1123, 0, NULL, NULL },
|
||||||
|
{ "evutil_v4addr_is_local", test_evutil_v4addr_is_local, 0, NULL, NULL },
|
||||||
|
{ "evutil_v6addr_is_local", test_evutil_v6addr_is_local, 0, NULL, NULL },
|
||||||
END_OF_TESTCASES,
|
END_OF_TESTCASES,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -527,6 +527,17 @@ evutil_socket_t evutil_eventfd_(unsigned initval, int flags);
|
|||||||
|
|
||||||
void evutil_memclear_(void *mem, size_t len);
|
void evutil_memclear_(void *mem, size_t len);
|
||||||
|
|
||||||
|
struct in_addr;
|
||||||
|
struct in6_addr;
|
||||||
|
|
||||||
|
/* This is a any, loopback, link-local, multicast */
|
||||||
|
EVENT2_EXPORT_SYMBOL
|
||||||
|
int evutil_v4addr_is_local_(const struct in_addr *in);
|
||||||
|
/* This is a reserved, ipv4compat, ipv4map, loopback,
|
||||||
|
* link-local, multicast, or unspecified address. */
|
||||||
|
EVENT2_EXPORT_SYMBOL
|
||||||
|
int evutil_v6addr_is_local_(const struct in6_addr *in);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user