about summary refs log tree commit diff
path: root/resolv
diff options
context:
space:
mode:
Diffstat (limited to 'resolv')
-rw-r--r--resolv/Versions2
-rw-r--r--resolv/res_data.c4
-rw-r--r--resolv/res_init.c31
-rw-r--r--resolv/res_libc.c16
-rw-r--r--resolv/res_send.c46
5 files changed, 47 insertions, 52 deletions
diff --git a/resolv/Versions b/resolv/Versions
index 2a67677d8e..7016365be5 100644
--- a/resolv/Versions
+++ b/resolv/Versions
@@ -39,7 +39,7 @@ libc {
     h_errno; __resp;
 %endif
 
-    __res_maybe_init;
+    __res_maybe_init; __res_iclose;
   }
 }
 
diff --git a/resolv/res_data.c b/resolv/res_data.c
index adadcdcd7a..1beea1dc4f 100644
--- a/resolv/res_data.c
+++ b/resolv/res_data.c
@@ -246,7 +246,9 @@ res_close(void) {
 	if ((_res.options & RES_INIT) == 0)
 	  return;
 #endif
-	res_nclose(&_res);
+	/* We don't free the name server addresses because we never
+	   did it and it would be done implicitly on shutdown.  */
+	__res_iclose(&_res, false);
 }
 
 #ifdef BIND_UPDATE
diff --git a/resolv/res_init.c b/resolv/res_init.c
index 731c784e17..f881060d58 100644
--- a/resolv/res_init.c
+++ b/resolv/res_init.c
@@ -555,7 +555,7 @@ libc_hidden_def (__res_randomid)
  * This routine is not expected to be user visible.
  */
 void
-res_nclose(res_state statp) {
+__res_iclose(res_state statp, bool free_addr) {
 	int ns;
 
 	if (statp->_vcsock >= 0) {
@@ -568,13 +568,25 @@ res_nclose(res_state statp) {
 #else
 	for (ns = 0; ns < statp->_u._ext.nscount; ns++)
 #endif
-		if (statp->_u._ext.nsaddrs[ns]
-		    && statp->_u._ext.nssocks[ns] != -1) {
-			close_not_cancel_no_status(statp->_u._ext.nssocks[ns]);
-			statp->_u._ext.nssocks[ns] = -1;
+		if (statp->_u._ext.nsaddrs[ns]) {
+			if (statp->_u._ext.nssocks[ns] != -1) {
+				close_not_cancel_no_status(statp->_u._ext.nssocks[ns]);
+				statp->_u._ext.nssocks[ns] = -1;
+			}
+			if (free_addr) {
+				free (statp->_u._ext.nsaddrs[ns]);
+				statp->_u._ext.nsaddrs[ns] = NULL;
+			}
 		}
 	statp->_u._ext.nsinit = 0;
 }
+libc_hidden_def (__res_iclose)
+
+void
+res_nclose(res_state statp)
+{
+  __res_iclose (statp, true);
+}
 #ifdef _LIBC
 libc_hidden_def (__res_nclose)
 #endif
@@ -589,14 +601,7 @@ res_thread_freeres (void)
     /* Never called res_ninit.  */
     return;
 
-  __res_nclose (&_res);		/* Close any VC sockets.  */
-
-  for (int ns = 0; ns < MAXNS; ns++)
-    if (_res._u._ext.nsaddrs[ns] != NULL)
-      {
-	free (_res._u._ext.nsaddrs[ns]);
-	_res._u._ext.nsaddrs[ns] = NULL;
-      }
+  __res_iclose (&_res, true);		/* Close any VC sockets.  */
 
   /* Make sure we do a full re-initialization the next time.  */
   _res.options = 0;
diff --git a/resolv/res_libc.c b/resolv/res_libc.c
index 76abca8442..834773c32f 100644
--- a/resolv/res_libc.c
+++ b/resolv/res_libc.c
@@ -70,14 +70,8 @@ res_init(void) {
 		_res.retry = 4;
 	if (!(_res.options & RES_INIT))
 		_res.options = RES_DEFAULT;
-	else if (_res.nscount > 0) {
-		__res_nclose (&_res);	/* Close any VC sockets.  */
-
-		for (int ns = 0; ns < MAXNS; ns++) {
-			free (_res._u._ext.nsaddrs[ns]);
-			_res._u._ext.nsaddrs[ns] = NULL;
-		}
-	}
+	else if (_res.nscount > 0)
+		__res_iclose (&_res, true);	/* Close any VC sockets.  */
 
 	/*
 	 * This one used to initialize implicitly to zero, so unless the app
@@ -103,11 +97,7 @@ __res_maybe_init (res_state resp, int preinit)
 	if (resp->options & RES_INIT) {
 		if (__res_initstamp != resp->_u._ext.initstamp) {
 			if (resp->nscount > 0) {
-				__res_nclose (resp);
-				for (int ns = 0; ns < MAXNS; ns++) {
-					free (resp->_u._ext.nsaddrs[ns]);
-					resp->_u._ext.nsaddrs[ns] = NULL;
-				}
+				__res_iclose (resp, true);
 				return __res_vinit (resp, 1);
 			}
 		}
diff --git a/resolv/res_send.c b/resolv/res_send.c
index e62cde2360..ff7be11509 100644
--- a/resolv/res_send.c
+++ b/resolv/res_send.c
@@ -381,7 +381,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
 				}
 			}
 		if (needclose)
-			res_nclose(statp);
+			__res_iclose(statp, false);
 	}
 
 	/*
@@ -488,7 +488,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
 					done = 1;
 					break;
 				case res_nextns:
-					res_nclose(statp);
+					__res_iclose(statp, false);
 					goto next_ns;
 				case res_done:
 					return (resplen);
@@ -553,7 +553,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
 		 */
 		if ((v_circuit && (statp->options & RES_USEVC) == 0) ||
 		    (statp->options & RES_STAYOPEN) == 0) {
-			res_nclose(statp);
+			__res_iclose(statp, false);
 		}
 		if (statp->rhook) {
 			int done = 0, loops = 0;
@@ -570,7 +570,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
 					done = 1;
 					break;
 				case res_nextns:
-					res_nclose(statp);
+					__res_iclose(statp, false);
 					goto next_ns;
 				case res_modified:
 					/* give the hook another try */
@@ -589,7 +589,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
  next_ns: ;
 	   } /*foreach ns*/
 	} /*foreach retry*/
-	res_nclose(statp);
+	__res_iclose(statp, false);
 	if (!v_circuit) {
 		if (!gotsomewhere)
 			__set_errno (ECONNREFUSED);	/* no nameservers found */
@@ -637,14 +637,14 @@ send_vc(res_state statp,
 		if (getpeername(statp->_vcsock,
 				(struct sockaddr *)&peer, &size) < 0 ||
 		    !sock_eq(&peer, nsap)) {
-			res_nclose(statp);
+		  __res_iclose(statp, false);
 			statp->_flags &= ~RES_F_VC;
 		}
 	}
 
 	if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
 		if (statp->_vcsock >= 0)
-			res_nclose(statp);
+		  __res_iclose(statp, false);
 
 		statp->_vcsock = socket(nsap->sin6_family, SOCK_STREAM, 0);
 		if (statp->_vcsock < 0) {
@@ -660,7 +660,7 @@ send_vc(res_state statp,
 			*terrno = errno;
 			Aerror(statp, stderr, "connect/vc", errno,
 			       (struct sockaddr *) nsap);
-			res_nclose(statp);
+			__res_iclose(statp, false);
 			return (0);
 		}
 		statp->_flags |= RES_F_VC;
@@ -676,7 +676,7 @@ send_vc(res_state statp,
 	    != (INT16SZ + buflen)) {
 		*terrno = errno;
 		Perror(statp, stderr, "write failed", errno);
-		res_nclose(statp);
+		__res_iclose(statp, false);
 		return (0);
 	}
 	/*
@@ -694,7 +694,7 @@ send_vc(res_state statp,
 	if (n <= 0) {
 		*terrno = errno;
 		Perror(statp, stderr, "read failed", errno);
-		res_nclose(statp);
+		__res_iclose(statp, false);
 		/*
 		 * A long running process might get its TCP
 		 * connection reset if the remote server was
@@ -706,10 +706,8 @@ send_vc(res_state statp,
 		 */
 		if (*terrno == ECONNRESET && !connreset) {
 			connreset = 1;
-			res_nclose(statp);
 			goto same_ns;
 		}
-		res_nclose(statp);
 		return (0);
 	}
 	resplen = ns_get16(ans);
@@ -718,7 +716,7 @@ send_vc(res_state statp,
 			ans = malloc (MAXPACKET);
 			if (ans == NULL) {
 				*terrno = ENOMEM;
-				res_nclose(statp);
+				__res_iclose(statp, false);
 				return (0);
 			}
 			anssiz = MAXPACKET;
@@ -743,7 +741,7 @@ send_vc(res_state statp,
 		Dprint(statp->options & RES_DEBUG,
 		       (stdout, ";; undersized: %d\n", len));
 		*terrno = EMSGSIZE;
-		res_nclose(statp);
+		__res_iclose(statp, false);
 		return (0);
 	}
 	cp = ans;
@@ -754,7 +752,7 @@ send_vc(res_state statp,
 	if (n <= 0) {
 		*terrno = errno;
 		Perror(statp, stderr, "read(vc)", errno);
-		res_nclose(statp);
+		__res_iclose(statp, false);
 		return (0);
 	}
 	if (truncating) {
@@ -847,7 +845,7 @@ send_dg(res_state statp,
 			    sizeof *nsap) < 0) {
 			Aerror(statp, stderr, "connect(dg)", errno,
 			       (struct sockaddr *) nsap);
-			res_nclose(statp);
+			__res_iclose(statp, false);
 			return (0);
 		}
 		/* Make socket non-blocking.  */
@@ -879,7 +877,7 @@ send_dg(res_state statp,
 		evNowTime(&now);
 		if (evCmpTime(finish, now) <= 0) {
 			Perror(statp, stderr, "select", errno);
-			res_nclose(statp);
+			__res_iclose(statp, false);
 			return (0);
 		}
 		evSubTime(&timeout, &finish, &now);
@@ -910,7 +908,7 @@ send_dg(res_state statp,
 			}
 		}
 		Perror(statp, stderr, "poll", errno);
-		res_nclose(statp);
+		__res_iclose(statp, false);
 		return (0);
 	}
 	__set_errno (0);
@@ -919,7 +917,7 @@ send_dg(res_state statp,
 			if (errno == EINTR || errno == EAGAIN)
 				goto recompute_resend;
 			Perror(statp, stderr, "send", errno);
-			res_nclose(statp);
+			__res_iclose(statp, false);
 			return (0);
 		}
 		pfd[0].events = POLLIN;
@@ -950,7 +948,7 @@ send_dg(res_state statp,
 				goto wait;
 			}
 			Perror(statp, stderr, "recvfrom", errno);
-			res_nclose(statp);
+			__res_iclose(statp, false);
 			return (0);
 		}
 		*gotsomewhere = 1;
@@ -962,7 +960,7 @@ send_dg(res_state statp,
 			       (stdout, ";; undersized: %d\n",
 				resplen));
 			*terrno = EMSGSIZE;
-			res_nclose(statp);
+			__res_iclose(statp, false);
 			return (0);
 		}
 		if (hp->id != anhp->id) {
@@ -1011,7 +1009,7 @@ send_dg(res_state statp,
 				(stdout, "server rejected query:\n"),
 				ans, (resplen > anssiz) ? anssiz : resplen);
 		next_ns:
-			res_nclose(statp);
+			__res_iclose(statp, false);
 			/* don't retry if called from dig */
 			if (!statp->pfcode)
 				return (0);
@@ -1031,7 +1029,7 @@ send_dg(res_state statp,
 			Dprint(statp->options & RES_DEBUG,
 			       (stdout, ";; truncated answer\n"));
 			*v_circuit = 1;
-			res_nclose(statp);
+			__res_iclose(statp, false);
 			return (1);
 		}
 		/*
@@ -1041,7 +1039,7 @@ send_dg(res_state statp,
 		return (resplen);
 	} else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
 		/* Something went wrong.  We can stop trying.  */
-		res_nclose(statp);
+	  __res_iclose(statp, false);
 		return (0);
 	}
 	else {