瀏覽代碼

__dns_lookup: document and optimize a bit

    text           data     bss     dec     hex filename
-   1545              2       4    1551     60f libc/inet/dnslookup.o
+   1528              2       4    1534     5fe libc/inet/dnslookup.o
Denis Vlasenko 17 年之前
父節點
當前提交
2ac83a8051
共有 1 個文件被更改,包括 45 次插入33 次删除
  1. 45 33
      libc/inet/resolv.c

+ 45 - 33
libc/inet/resolv.c

@@ -742,8 +742,25 @@ static int static_ns = 0;
  * rw data costs more. */
 static uint16_t static_id = 1;
 
-int attribute_hidden __dns_lookup(const char *name, int type, int nscount, char **nsip,
-			   unsigned char **outpacket, struct resolv_answer *a)
+/* On entry:
+ *  a.buf(len) = auxiliary buffer for IP addresses after first one
+ *  a.add_count = how many additional addresses are there already
+ *  outpacket = where to save ptr to raw packet? can be NULL
+ * On exit:
+ *  ret < 0: error, all other data is not valid
+ *  a.add_count & a.buf: updated
+ *  a.rdlength: length of addresses (4 bytes for IPv4)
+ *  *outpacket: updated (packet is malloced, you need to free it)
+ *  a.rdata: points into *outpacket to 1st IP addr
+ *      NB: don't pass outpacket == NULL if you need to use a.rdata!
+ *  a.atype: type of query?
+ *  a.dotted: numeric IP as a string (malloced, may be NULL if strdup failed)
+ *      (which one of potentially many??)
+ */
+int attribute_hidden __dns_lookup(const char *name, int type,
+			int nscount, char **nsip,
+			unsigned char **outpacket,
+			struct resolv_answer *a)
 {
 	int i, j, len, fd, pos, rc;
 #ifdef USE_SELECT
@@ -762,13 +779,15 @@ int attribute_hidden __dns_lookup(const char *name, int type, int nscount, char
 	int variant = -1;  /* search domain to append, -1 - none */
 	int local_ns = -1, local_id = -1;
 	bool ends_with_dot;
-#ifdef __UCLIBC_HAS_IPV6__
-	bool v6;
-	struct sockaddr_in6 sa6;
-#endif
+	union {
+		struct sockaddr sa;
 #ifdef __UCLIBC_HAS_IPV4__
-	struct sockaddr_in sa;
+		struct sockaddr_in sa4;
 #endif
+#ifdef __UCLIBC_HAS_IPV6__
+		struct sockaddr_in6 sa6;
+#endif
+	} sa;
 
 	fd = -1;
 
@@ -841,43 +860,38 @@ int attribute_hidden __dns_lookup(const char *name, int type, int nscount, char
 		DPRINTF("On try %d, sending query to port %d of machine %s\n",
 				retries+1, NAMESERVER_PORT, dns);
 
+		sa.sa.sa_family = AF_INET;
 #ifdef __UCLIBC_HAS_IPV6__
 		//__UCLIBC_MUTEX_LOCK(__resolv_lock);
 		///* 'dns' is really __nameserver[] which is a global that
 		//   needs to hold __resolv_lock before access!! */
-		v6 = inet_pton(AF_INET6, dns, &sa6.sin6_addr) > 0;
+		if (inet_pton(AF_INET6, dns, &sa.sa6.sin6_addr) > 0)
+			sa.sa.sa_family = AF_INET6;
 		//__UCLIBC_MUTEX_UNLOCK(__resolv_lock);
-		fd = socket(v6 ? AF_INET6 : AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-#else
-		fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 #endif
-		if (fd < 0) {
-			retries++;
-			continue;
-		}
-
 		/* Connect to the UDP socket so that asyncronous errors are returned */
 #ifdef __UCLIBC_HAS_IPV6__
-		if (v6) {
-			sa6.sin6_family = AF_INET6;
-			sa6.sin6_port = htons(NAMESERVER_PORT);
+		if (sa.sa.sa_family == AF_INET6) {
+			sa.sa6.sin6_port = htons(NAMESERVER_PORT);
 			/* sa6.sin6_addr is already here */
-			rc = connect(fd, (struct sockaddr *) &sa6, sizeof(sa6));
-		} else {
+		} else
 #endif
 #ifdef __UCLIBC_HAS_IPV4__
-			sa.sin_family = AF_INET;
-			sa.sin_port = htons(NAMESERVER_PORT);
+		{
+			sa.sa4.sin_port = htons(NAMESERVER_PORT);
 			//__UCLIBC_MUTEX_LOCK(__resolv_lock);
 			///* 'dns' is really __nameserver[] which is a global that
 			//   needs to hold __resolv_lock before access!! */
-			sa.sin_addr.s_addr = inet_addr(dns);
+			sa.sa4.sin_addr.s_addr = inet_addr(dns);
 			//__UCLIBC_MUTEX_UNLOCK(__resolv_lock);
-			rc = connect(fd, (struct sockaddr *) &sa, sizeof(sa));
-#endif
-#ifdef __UCLIBC_HAS_IPV6__
 		}
 #endif
+		fd = socket(sa.sa.sa_family, SOCK_DGRAM, IPPROTO_UDP);
+		if (fd < 0) {
+			retries++;
+			continue;
+		}
+		rc = connect(fd, &sa.sa, sizeof(sa));
 		if (rc < 0) {
 			if (errno == ENETUNREACH) {
 				/* routing error, presume not transient */
@@ -900,7 +914,6 @@ int attribute_hidden __dns_lookup(const char *name, int type, int nscount, char
 		tv.tv_usec = 0;
 		if (select(fd + 1, &fds, NULL, NULL, &tv) <= 0) {
 			DPRINTF("Timeout\n");
-
 			/* timed out, so retry send and receive,
 			 * to next nameserver on queue */
 			goto tryall;
@@ -910,7 +923,6 @@ int attribute_hidden __dns_lookup(const char *name, int type, int nscount, char
 		fds.events = POLLIN;
 		if (poll(&fds, 1, REPLY_TIMEOUT * 1000) <= 0) {
 			DPRINTF("Timeout\n");
-
 			/* timed out, so retry send and receive,
 			 * to next nameserver on queue */
 			goto tryall;
@@ -967,9 +979,8 @@ int attribute_hidden __dns_lookup(const char *name, int type, int nscount, char
 		DPRINTF("Decoding answer at pos %d\n", pos);
 
 		first_answer = 1;
-		for (j = 0; j < h.ancount && pos < len; j++, pos += i) {
+		for (j = 0; j < h.ancount && pos < len; j++) {
 			i = __decode_answer(packet, pos, len, &ma);
-
 			if (i < 0) {
 				DPRINTF("failed decode %d\n", i);
 				/* if the message was truncated and we have
@@ -978,13 +989,14 @@ int attribute_hidden __dns_lookup(const char *name, int type, int nscount, char
 					break;
 				goto again;
 			}
+			pos += i;
 
 			if (first_answer) {
 				ma.buf = a->buf;
 				ma.buflen = a->buflen;
 				ma.add_count = a->add_count;
 				memcpy(a, &ma, sizeof(ma));
-				if (a->atype != T_SIG && (0 == a->buf || (type != T_A && type != T_AAAA)))
+				if (a->atype != T_SIG && (NULL == a->buf || (type != T_A && type != T_AAAA)))
 					break;
 				if (a->atype != type) {
 					free(a->dotted);
@@ -1288,7 +1300,7 @@ int res_query(const char *dname, int class, int type,
               unsigned char *answer, int anslen)
 {
 	int i;
-	unsigned char * packet = 0;
+	unsigned char * packet = NULL;
 	struct resolv_answer a;
 	int __nameserversXX;
 	char ** __nameserverXX;