mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-16 07:45:23 -04:00
Don't use a bind address for nameservers on loopback
If the user sets a bind address to use for nameservers, and a nameserver happens to be on 127.0.0.1, the nameserver will generally fail. This patch alters this behavior so that the bind address is only applied when the nameserver is on a non-loopback address.
This commit is contained in:
parent
0683950384
commit
8d4aaf9086
3
evdns.c
3
evdns.c
@ -2448,7 +2448,8 @@ _evdns_nameserver_add_impl(struct evdns_base *base, const struct sockaddr *addre
|
|||||||
if (ns->socket < 0) { err = 1; goto out1; }
|
if (ns->socket < 0) { err = 1; goto out1; }
|
||||||
evutil_make_socket_nonblocking(ns->socket);
|
evutil_make_socket_nonblocking(ns->socket);
|
||||||
|
|
||||||
if (base->global_outgoing_addrlen) {
|
if (base->global_outgoing_addrlen &&
|
||||||
|
!evutil_sockaddr_is_loopback(address)) {
|
||||||
if (bind(ns->socket,
|
if (bind(ns->socket,
|
||||||
(struct sockaddr*)&base->global_outgoing_address,
|
(struct sockaddr*)&base->global_outgoing_address,
|
||||||
base->global_outgoing_addrlen) < 0) {
|
base->global_outgoing_addrlen) < 0) {
|
||||||
|
22
evutil.c
22
evutil.c
@ -1849,3 +1849,25 @@ _evutil_weakrand(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
evutil_sockaddr_is_loopback(const struct sockaddr *addr)
|
||||||
|
{
|
||||||
|
static const char LOOPBACK_S6[16] =
|
||||||
|
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1";
|
||||||
|
if (addr->sa_family == AF_INET) {
|
||||||
|
struct sockaddr_in *sin = (struct sockaddr_in *)addr;
|
||||||
|
return (ntohl(sin->sin_addr.s_addr) & 0xff000000) == 0x7f000000;
|
||||||
|
} else if (addr->sa_family == AF_INET6) {
|
||||||
|
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
|
||||||
|
/*
|
||||||
|
int i;
|
||||||
|
for (i=0;i<14;++i)
|
||||||
|
if (sin6->sin6_addr.s6_addr[i] != 0)
|
||||||
|
return 1;
|
||||||
|
return sin6->sin6_addr.s6_addr[15] == 1;
|
||||||
|
*/
|
||||||
|
return !memcmp(sin6->sin6_addr.s6_addr, LOOPBACK_S6, 16);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -275,6 +275,50 @@ regress_sockaddr_port_parse(void *ptr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct sa_pred_ent {
|
||||||
|
const char *parse;
|
||||||
|
|
||||||
|
int is_loopback;
|
||||||
|
} sa_pred_entries[] = {
|
||||||
|
{ "127.0.0.1", 1 },
|
||||||
|
{ "127.0.3.2", 1 },
|
||||||
|
{ "128.1.2.3", 0 },
|
||||||
|
{ "18.0.0.1", 0 },
|
||||||
|
{ "129.168.1.1", 0 },
|
||||||
|
|
||||||
|
{ "::1", 1 },
|
||||||
|
{ "::0", 0 },
|
||||||
|
{ "f::1", 0 },
|
||||||
|
{ "::501", 0 },
|
||||||
|
{ NULL, 0 },
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_evutil_sockaddr_predicates(void *ptr)
|
||||||
|
{
|
||||||
|
struct sockaddr_storage ss;
|
||||||
|
int r, i;
|
||||||
|
|
||||||
|
for (i=0; sa_pred_entries[i].parse; ++i) {
|
||||||
|
struct sa_pred_ent *ent = &sa_pred_entries[i];
|
||||||
|
int len = sizeof(ss);
|
||||||
|
|
||||||
|
r = evutil_parse_sockaddr_port(ent->parse, (struct sockaddr*)&ss, &len);
|
||||||
|
|
||||||
|
if (r<0) {
|
||||||
|
TT_FAIL(("Couldn't parse %s!", ent->parse));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sockaddr_is_loopback */
|
||||||
|
if (ent->is_loopback != evutil_sockaddr_is_loopback((struct sockaddr*)&ss)) {
|
||||||
|
TT_FAIL(("evutil_sockaddr_loopback(%s) not as expected",
|
||||||
|
ent->parse));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_evutil_strtoll(void *ptr)
|
test_evutil_strtoll(void *ptr)
|
||||||
{
|
{
|
||||||
@ -758,6 +802,7 @@ 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 },
|
||||||
{ "sockaddr_port_parse", regress_sockaddr_port_parse, 0, NULL, NULL },
|
{ "sockaddr_port_parse", regress_sockaddr_port_parse, 0, NULL, NULL },
|
||||||
|
{ "sockaddr_predicates", test_evutil_sockaddr_predicates, 0,NULL,NULL },
|
||||||
{ "evutil_snprintf", test_evutil_snprintf, 0, NULL, NULL },
|
{ "evutil_snprintf", test_evutil_snprintf, 0, NULL, NULL },
|
||||||
{ "evutil_strtoll", test_evutil_strtoll, 0, NULL, NULL },
|
{ "evutil_strtoll", test_evutil_strtoll, 0, NULL, NULL },
|
||||||
{ "evutil_casecmp", test_evutil_casecmp, 0, NULL, NULL },
|
{ "evutil_casecmp", test_evutil_casecmp, 0, NULL, NULL },
|
||||||
|
@ -232,12 +232,15 @@ void evutil_adjust_hints_for_addrconfig(struct evutil_addrinfo *hints);
|
|||||||
int evutil_getaddrinfo_common(const char *nodename, const char *servname,
|
int evutil_getaddrinfo_common(const char *nodename, const char *servname,
|
||||||
struct evutil_addrinfo *hints, struct evutil_addrinfo **res, int *portnum);
|
struct evutil_addrinfo *hints, struct evutil_addrinfo **res, int *portnum);
|
||||||
|
|
||||||
int
|
int evutil_getaddrinfo_async(struct evdns_base *dns_base,
|
||||||
evutil_getaddrinfo_async(struct evdns_base *dns_base,
|
|
||||||
const char *nodename, const char *servname,
|
const char *nodename, const char *servname,
|
||||||
const struct evutil_addrinfo *hints_in,
|
const struct evutil_addrinfo *hints_in,
|
||||||
void (*cb)(int, struct evutil_addrinfo *, void *), void *arg);
|
void (*cb)(int, struct evutil_addrinfo *, void *), void *arg);
|
||||||
|
|
||||||
|
/** Return true iff sa is a looback address. (That is, it is 127.0.0.1/8, or
|
||||||
|
* ::1). */
|
||||||
|
int evutil_sockaddr_is_loopback(const struct sockaddr *sa);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user