posix: upgrade libevent from 1.4.7 to 1.4.13

I took this opportunity to rejigger how we hacked around using an uninstalled
libevent, to remove a TODO that mentioned danger in the README.

Files to review: README.chromium and chromium.patch.
The rest are probably rubber-stampable.

Review URL: http://codereview.chromium.org/412006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@32656 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/third_party/libevent/evdns.c b/third_party/libevent/evdns.c
index 6861161..f07ecc98 100644
--- a/third_party/libevent/evdns.c
+++ b/third_party/libevent/evdns.c
@@ -74,7 +74,9 @@
 #include <openssl/rand.h>
 #endif
 
+#ifndef _FORTIFY_SOURCE
 #define _FORTIFY_SOURCE 3
+#endif
 
 #include <string.h>
 #include <fcntl.h>
@@ -209,6 +211,7 @@
 struct nameserver {
 	int socket;  /* a connected UDP socket */
 	u32 address;
+	u16 port;
 	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 */
 	struct event event;
@@ -469,7 +472,6 @@
 					  global_nameserver_timeouts_length - 1)];
 	ns->failed_times++;
 
-	evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns);
 	if (evtimer_add(&ns->timeout_event, (struct timeval *) timeout) < 0) {
           log(EVDNS_LOG_WARN,
               "Error from libevent when adding timer event for %s",
@@ -498,7 +500,6 @@
 	ns->state = 0;
 	ns->failed_times = 1;
 
-	evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns);
 	if (evtimer_add(&ns->timeout_event, (struct timeval *) &global_nameserver_timeouts[0]) < 0) {
 		log(EVDNS_LOG_WARN,
 		    "Error from libevent when adding timer event for %s",
@@ -680,7 +681,10 @@
 static void
 reply_handle(struct request *const req, u16 flags, u32 ttl, struct reply *reply) {
 	int error;
-	static const int error_codes[] = {DNS_ERR_FORMAT, DNS_ERR_SERVERFAILED, DNS_ERR_NOTEXIST, DNS_ERR_NOTIMPL, DNS_ERR_REFUSED};
+	static const int error_codes[] = {
+		DNS_ERR_FORMAT, DNS_ERR_SERVERFAILED, DNS_ERR_NOTEXIST,
+		DNS_ERR_NOTIMPL, DNS_ERR_REFUSED
+	};
 
 	if (flags & 0x020f || !reply || !reply->have_answer) {
 		/* there was an error */
@@ -709,9 +713,10 @@
 			}
 			break;
 		case DNS_ERR_SERVERFAILED:
-			/* rcode 2 (servfailed) sometimes means "we are broken" and
-			 * sometimes (with some binds) means "that request was very
-			 * confusing."  Treat this as a timeout, not a failure. 
+			/* rcode 2 (servfailed) sometimes means "we
+			 * are broken" and sometimes (with some binds)
+			 * means "that request was very confusing."
+			 * Treat this as a timeout, not a failure.
 			 */
 			log(EVDNS_LOG_DEBUG, "Got a SERVERFAILED from nameserver %s; "
 				"will allow the request to time out.",
@@ -723,10 +728,13 @@
 		}
 
 		if (req->search_state && req->request_type != TYPE_PTR) {
-			/* if we have a list of domains to search in, try the next one */
+			/* if we have a list of domains to search in,
+			 * try the next one */
 			if (!search_try_next(req)) {
-				/* a new request was issued so this request is finished and */
-				/* the user callback will be made when that request (or a */
+				/* a new request was issued so this
+				 * request is finished and */
+				/* the user callback will be made when
+				 * that request (or a */
 				/* child of it) finishes. */
 				request_finished(req, &req_head);
 				return;
@@ -803,10 +811,10 @@
 /* parses a raw request from a nameserver */
 static int
 reply_parse(u8 *packet, int length) {
-	int j = 0;  /* index into packet */
+	int j = 0, k = 0;  /* index into packet */
 	u16 _t;  /* used by the macros */
 	u32 _t32;  /* used by the macros */
-	char tmp_name[256]; /* used by the macros */
+	char tmp_name[256], cmp_name[256]; /* used by the macros */
 
 	u16 trans_id, questions, answers, authority, additional, datalength;
         u16 flags = 0;
@@ -839,10 +847,21 @@
 
 	/* This macro skips a name in the DNS reply. */
 #define SKIP_NAME \
-	do { tmp_name[0] = '\0';					\
-		if (name_parse(packet, length, &j, tmp_name, sizeof(tmp_name))<0) \
-			goto err;													\
-	} while(0);
+	do { tmp_name[0] = '\0';				\
+		if (name_parse(packet, length, &j, tmp_name, sizeof(tmp_name))<0)\
+			goto err;				\
+	} while(0)
+#define TEST_NAME \
+	do { tmp_name[0] = '\0';				\
+		cmp_name[0] = '\0';				\
+		k = j;						\
+		if (name_parse(packet, length, &j, tmp_name, sizeof(tmp_name))<0)\
+			goto err;					\
+		if (name_parse(req->request, req->request_len, &k, cmp_name, sizeof(cmp_name))<0)	\
+			goto err;				\
+		if (memcmp(tmp_name, cmp_name, strlen (tmp_name)) != 0)	\
+			return (-1); /* we ignore mismatching names */	\
+	} while(0)
 
 	reply.type = req->request_type;
 
@@ -851,7 +870,7 @@
 		/* the question looks like
 		 *   <label:name><u16:type><u16:class>
 		 */
-		SKIP_NAME;
+		TEST_NAME;
 		j += 4;
 		if (j > length) goto err;
 	}
@@ -1134,19 +1153,38 @@
 	}
 }
 
+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 */
 static void
 nameserver_read(struct nameserver *ns) {
 	u8 packet[1500];
+	struct sockaddr_storage ss;
+	socklen_t addrlen = sizeof(ss);
 
 	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) {
 			int err = last_error(ns->socket);
 			if (error_is_eagain(err)) return;
 			nameserver_failed(ns, strerror(err));
 			return;
 		}
+		if (!address_is_correct(ns, (struct sockaddr*)&ss, addrlen)) {
+			log(EVDNS_LOG_WARN, "Address mismatch on received "
+			    "DNS packet.");
+			return;
+		}
 		ns->timedout = 0;
 		reply_parse(packet, r);
 	}
@@ -1667,7 +1705,7 @@
 	if (j > 512) {
 overflow:
 		j = 512;
-		buf[3] |= 0x02; /* set the truncated bit. */
+		buf[2] |= 0x02; /* set the truncated bit. */
 	}
 
 	req->response_len = j;
@@ -1874,7 +1912,15 @@
 /*   2 other failure */
 static int
 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) {
 		int err = last_error(server->socket);
 		if (error_is_eagain(err)) return 1;
@@ -1923,7 +1969,6 @@
 		/* all ok */
 		log(EVDNS_LOG_DEBUG,
 		    "Setting timeout for request %lx", (unsigned long) req);
-		evtimer_set(&req->timeout_event, evdns_request_timeout_callback, req);
 		if (evtimer_add(&req->timeout_event, &global_timeout) < 0) {
                   log(EVDNS_LOG_WARN,
 		      "Error from libevent when adding timer for request %lx",
@@ -2070,7 +2115,6 @@
 
 	const struct nameserver *server = server_head, *const started_at = server_head;
 	struct nameserver *ns;
-	struct sockaddr_in sin;
 	int err = 0;
 	if (server) {
 		do {
@@ -2084,18 +2128,14 @@
 
 	memset(ns, 0, sizeof(struct nameserver));
 
+	evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns);
+
 	ns->socket = socket(PF_INET, SOCK_DGRAM, 0);
 	if (ns->socket < 0) { err = 1; goto out1; }
         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->port = htons(port);
 	ns->state = 1;
 	event_set(&ns->event, ns->socket, EV_READ | EV_PERSIST, nameserver_ready_callback, ns);
 	if (event_add(&ns->event, NULL) < 0) {
@@ -2208,6 +2248,8 @@
         if (!req) return NULL;
 	memset(req, 0, sizeof(struct request));
 
+	evtimer_set(&req->timeout_event, evdns_request_timeout_callback, req);
+
 	/* request data lives just after the header */
 	req->request = ((u8 *) req) + sizeof(struct request);
 	/* denotes that the request data shouldn't be free()ed */
@@ -2277,7 +2319,7 @@
 	}
 }
 
-int evdns_resolve_reverse(struct in_addr *in, int flags, evdns_callback_type callback, void *ptr) {
+int evdns_resolve_reverse(const struct in_addr *in, int flags, evdns_callback_type callback, void *ptr) {
 	char buf[32];
 	struct request *req;
 	u32 a;
@@ -2295,7 +2337,7 @@
 	return 0;
 }
 
-int evdns_resolve_reverse_ipv6(struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr) {
+int evdns_resolve_reverse_ipv6(const struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr) {
 	/* 32 nybbles, 32 periods, "ip6.arpa", NUL. */
 	char buf[73];
 	char *cp;
@@ -2947,7 +2989,7 @@
 #undef TRY
 }
 
-static int
+int
 evdns_config_windows_nameservers(void)
 {
 	if (load_nameservers_with_getnetworkparams() == 0)