mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-14 23:05:03 -04:00
Let evdns keep working when our IP changes. Fix by Christopher Davis; backported by nickm.
svn:r1328
This commit is contained in:
parent
b99254ac22
commit
763391947c
@ -4,6 +4,7 @@ Changes in 1.4.12-stable:
|
|||||||
o Use __VA_ARGS__ syntax for varargs macros in event_rpcgen when compiler is not GCC.
|
o Use __VA_ARGS__ syntax for varargs macros in event_rpcgen when compiler is not GCC.
|
||||||
o Activate fd events in a pseudorandom order with O(N) backends, so that we don't systematically favor low fds (select) or earlier-added fds (poll, win32).
|
o Activate fd events in a pseudorandom order with O(N) backends, so that we don't systematically favor low fds (select) or earlier-added fds (poll, win32).
|
||||||
o Fix another pair of fencepost bugs in epoll.c. [Patch from Adam Langley.]
|
o Fix another pair of fencepost bugs in epoll.c. [Patch from Adam Langley.]
|
||||||
|
o Do not break evdns connections to nameservers when our IP changes.
|
||||||
|
|
||||||
Changes in 1.4.11-stable:
|
Changes in 1.4.11-stable:
|
||||||
o Fix a bug when removing a timeout from the heap. [Patch from Marko Kreen]
|
o Fix a bug when removing a timeout from the heap. [Patch from Marko Kreen]
|
||||||
|
41
evdns.c
41
evdns.c
@ -209,6 +209,7 @@ struct reply {
|
|||||||
struct nameserver {
|
struct nameserver {
|
||||||
int socket; /* a connected UDP socket */
|
int socket; /* a connected UDP socket */
|
||||||
u32 address;
|
u32 address;
|
||||||
|
u16 port;
|
||||||
int failed_times; /* number of times which we have given this server a chance */
|
int failed_times; /* number of times which we have given this server a chance */
|
||||||
int timedout; /* number of times in a row a request has timed out */
|
int timedout; /* number of times in a row a request has timed out */
|
||||||
struct event event;
|
struct event event;
|
||||||
@ -1150,19 +1151,38 @@ nameserver_pick(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
address_is_correct(struct nameserver *ns, struct sockaddr *sa, socklen_t slen)
|
||||||
|
{
|
||||||
|
struct sockaddr_in *sin = (struct sockaddr_in*) sa;
|
||||||
|
if (sa->sa_family != AF_INET || slen != sizeof(struct sockaddr_in))
|
||||||
|
return 0;
|
||||||
|
if (sin->sin_addr.s_addr != ns->address)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* this is called when a namesever socket is ready for reading */
|
/* this is called when a namesever socket is ready for reading */
|
||||||
static void
|
static void
|
||||||
nameserver_read(struct nameserver *ns) {
|
nameserver_read(struct nameserver *ns) {
|
||||||
u8 packet[1500];
|
u8 packet[1500];
|
||||||
|
struct sockaddr_storage ss;
|
||||||
|
socklen_t addrlen = sizeof(ss);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const int r = recv(ns->socket, packet, sizeof(packet), 0);
|
const int r = recvfrom(ns->socket, packet, sizeof(packet), 0,
|
||||||
|
(struct sockaddr*)&ss, &addrlen);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
int err = last_error(ns->socket);
|
int err = last_error(ns->socket);
|
||||||
if (error_is_eagain(err)) return;
|
if (error_is_eagain(err)) return;
|
||||||
nameserver_failed(ns, strerror(err));
|
nameserver_failed(ns, strerror(err));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!address_is_correct(ns, (struct sockaddr*)&ss, addrlen)) {
|
||||||
|
log(EVDNS_LOG_WARN, "Address mismatch on received "
|
||||||
|
"DNS packet.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
ns->timedout = 0;
|
ns->timedout = 0;
|
||||||
reply_parse(packet, r);
|
reply_parse(packet, r);
|
||||||
}
|
}
|
||||||
@ -1890,7 +1910,15 @@ evdns_request_timeout_callback(int fd, short events, void *arg) {
|
|||||||
/* 2 other failure */
|
/* 2 other failure */
|
||||||
static int
|
static int
|
||||||
evdns_request_transmit_to(struct request *req, struct nameserver *server) {
|
evdns_request_transmit_to(struct request *req, struct nameserver *server) {
|
||||||
const int r = send(server->socket, req->request, req->request_len, 0);
|
struct sockaddr_in sin;
|
||||||
|
int r;
|
||||||
|
memset(&sin, 0, sizeof(sin));
|
||||||
|
sin.sin_addr.s_addr = req->ns->address;
|
||||||
|
sin.sin_port = req->ns->port;
|
||||||
|
sin.sin_family = AF_INET;
|
||||||
|
|
||||||
|
r = sendto(server->socket, req->request, req->request_len, 0,
|
||||||
|
(struct sockaddr*)&sin, sizeof(sin));
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
int err = last_error(server->socket);
|
int err = last_error(server->socket);
|
||||||
if (error_is_eagain(err)) return 1;
|
if (error_is_eagain(err)) return 1;
|
||||||
@ -2085,7 +2113,6 @@ _evdns_nameserver_add_impl(unsigned long int address, int port) {
|
|||||||
|
|
||||||
const struct nameserver *server = server_head, *const started_at = server_head;
|
const struct nameserver *server = server_head, *const started_at = server_head;
|
||||||
struct nameserver *ns;
|
struct nameserver *ns;
|
||||||
struct sockaddr_in sin;
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
if (server) {
|
if (server) {
|
||||||
do {
|
do {
|
||||||
@ -2104,15 +2131,9 @@ _evdns_nameserver_add_impl(unsigned long int address, int port) {
|
|||||||
ns->socket = socket(PF_INET, SOCK_DGRAM, 0);
|
ns->socket = socket(PF_INET, SOCK_DGRAM, 0);
|
||||||
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);
|
||||||
sin.sin_addr.s_addr = address;
|
|
||||||
sin.sin_port = htons(port);
|
|
||||||
sin.sin_family = AF_INET;
|
|
||||||
if (connect(ns->socket, (struct sockaddr *) &sin, sizeof(sin)) != 0) {
|
|
||||||
err = 2;
|
|
||||||
goto out2;
|
|
||||||
}
|
|
||||||
|
|
||||||
ns->address = address;
|
ns->address = address;
|
||||||
|
ns->port = htons(port);
|
||||||
ns->state = 1;
|
ns->state = 1;
|
||||||
event_set(&ns->event, ns->socket, EV_READ | EV_PERSIST, nameserver_ready_callback, ns);
|
event_set(&ns->event, ns->socket, EV_READ | EV_PERSIST, nameserver_ready_callback, ns);
|
||||||
if (event_add(&ns->event, NULL) < 0) {
|
if (event_add(&ns->event, NULL) < 0) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user