[Feature][ZXW-130]merge P50U02 version

Only Configure: No
Affected branch: master
Affected module: unknow
Is it affected on both ZXIC and MTK: only ZXIC
Self-test: Yes
Doc Update: No

Change-Id: I4f29ec5bb7c59385f23738d2b7ca84e67c100f69
diff --git a/ap/lib/libsoftap/netotherapi.c b/ap/lib/libsoftap/netotherapi.c
index 62edaaf..4fb37f5 100755
--- a/ap/lib/libsoftap/netotherapi.c
+++ b/ap/lib/libsoftap/netotherapi.c
@@ -1242,6 +1242,7 @@
 #define DNS_SERVER_NUM 2
 
 #define T_A 1 //Ipv4 address
+#define T_AAAA 28 //Ipv6 address
 #define T_NS 2 //Nameserver
 #define T_CNAME 5 // canonical name
 #define T_SOA 6 /* start of authority zone */
@@ -1374,7 +1375,7 @@
 	
 	struct sockaddr_in a;
 
-	struct RES_RECORD answers[20], auth[20], addit[20]; //the replies from the DNS server
+	struct RES_RECORD answers[20]; //the replies from the DNS server
 	struct sockaddr_in dest;
 
 	struct DNS_HEADER *dns = NULL;
@@ -1434,7 +1435,7 @@
 	qinfo->qtype = htons(query_type); //type of the query , A , MX , CNAME , NS etc
 	qinfo->qclass = htons(1); //its internet (lol)
 
-	printf("\nSending Packet...");
+	printf("\nSending Packet to %s...", dns_server);
 	if (sendto(s, (char*) buf,
 			sizeof(struct DNS_HEADER) + (strlen((const char*) qname) + 1)
 					+ sizeof(struct QUESTION), 0, (struct sockaddr*) &dest,
@@ -1487,7 +1488,7 @@
 		answers[i].resource = (struct R_DATA*) (reader);
 		reader = reader + sizeof(struct R_DATA);
 
-		if (ntohs(answers[i].resource->type) == 1) //if its an ipv4 address
+		if (ntohs(answers[i].resource->type) == T_A) //if its an ipv4 address
 				{
 			answers[i].rdata = (unsigned char*) malloc(
 					ntohs(answers[i].resource->data_len));
@@ -1528,15 +1529,15 @@
 			//Canonical name for an alias
 			printf("has alias name : %s", answers[i].rdata);
 		}
-
 		printf("\n");
+		free(answers[i].name);
+		free(answers[i].rdata);
 	}
 out:
 	close(s);
 	return ret;
 }
 
-
 unsigned long gethostbyname_l(char *hostname,char* dev_name) 
 {
 	int i = 0;
@@ -1547,13 +1548,13 @@
 	char nv_dns[32]	= {0};
 	char ip_dns[32]	= {0};
 	
-    sprintf(nv_dns, "%s_pridns", dev_name);
+    snprintf(nv_dns, sizeof(nv_dns), "%s_pridns", dev_name);
 	sc_cfg_get(nv_dns, ip_dns, sizeof(ip_dns));
 	strcpy(dns_servers[0], ip_dns);
 
 	memset(nv_dns,0,sizeof(nv_dns));
 	memset(ip_dns,0,sizeof(ip_dns));
-	sprintf(nv_dns, "%s_secdns", dev_name);
+	snprintf(nv_dns, sizeof(nv_dns), "%s_secdns", dev_name);
 	sc_cfg_get(nv_dns, ip_dns, sizeof(ip_dns));
 	strcpy(dns_servers[1], ip_dns);
 
@@ -1569,7 +1570,217 @@
 	return ret;
 }
 
+int my_gethostbyname6(unsigned char *host, char *dev_name, char* dns_server, int query_type, struct in6_addr* ip6)
+{
+	unsigned char buf[1025], *qname, *reader;
+	int i, j, stop, s, ans_max, ret = 0;
+	struct timeval tv;
+	struct ifreq ifr = {0};
+	struct RES_RECORD answers[20]; //the replies from the DNS server
+	struct sockaddr_in6 dest = {0};
+	struct in6_addr a = {0};
+	struct DNS_HEADER *dns = NULL;
+	struct QUESTION *qinfo = NULL;
+	char nv_cmd[64] = {0};
+	char ip_src[64] = {0};
+	struct sockaddr_in6 src = {0};
 
+	printf("Resolving %s", host);
+
+	s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); //UDP packet for DNS queries
+	if(s < 0)
+    {
+        printf("socket return fail \n");
+        return ret;
+    }   
+	
+	memset(&ifr,0,sizeof(ifr));    
+	strncpy(ifr.ifr_name, dev_name, sizeof(ifr.ifr_name)-1);
+	if(setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, (char*)&ifr, sizeof(ifr)) < 0){
+		printf("SO_BINDTODEVICE fail \n");
+		goto out;
+	}
+	tv.tv_sec = 5;
+	tv.tv_usec = 0;
+	if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
+		printf("socket option  SO_RCVTIMEO not support\n");
+		goto out;
+	}
+	snprintf(nv_cmd, sizeof(nv_cmd), "%s_ipv6_ip", dev_name);
+	sc_cfg_get(nv_cmd, ip_src, sizeof(ip_src));
+	src.sin6_family = AF_INET6;
+	if(inet_pton(AF_INET6, ip_src, &src.sin6_addr) <= 0){
+		printf("inet_pton fail1 \n");
+		goto out;
+	}
+	if (bind(s, (struct sockaddr*)&src, sizeof(src)) < 0) {
+		printf("bind fail \n");
+		goto out;
+	}
+	dest.sin6_family = AF_INET6;
+	dest.sin6_port = htons(53);
+	if(inet_pton(AF_INET6, dns_server, &dest.sin6_addr) <= 0){
+		printf("inet_pton fail2 \n");
+		goto out;
+	}
+	//Set the DNS structure to standard queries
+	dns = (struct DNS_HEADER *) &buf;
+
+	dns->id = (unsigned short) htons(getpid());
+	dns->qr = 0; //This is a query
+	dns->opcode = 0; //This is a standard query
+	dns->aa = 0; //Not Authoritative
+	dns->tc = 0; //This message is not truncated
+	dns->rd = 1; //Recursion Desired
+	dns->ra = 0; //Recursion not available! hey we dont have it (lol)
+	dns->z = 0;
+	dns->ad = 0;
+	dns->cd = 0;
+	dns->rcode = 0;
+	dns->q_count = htons(1); //we have only 1 question
+	dns->ans_count = 0;
+	dns->auth_count = 0;
+	dns->add_count = 0;
+
+	//point to the query portion
+	qname = (unsigned char*) &buf[sizeof(struct DNS_HEADER)];
+
+	ChangetoDnsNameFormat(qname, host);
+	qinfo = (struct QUESTION*) &buf[sizeof(struct DNS_HEADER)
+			+ (strlen((const char*) qname) + 1)]; //fill it
+
+	qinfo->qtype = htons(query_type); //type of the query , A , MX , CNAME , NS etc
+	qinfo->qclass = htons(1); //its internet (lol)
+
+	printf("\nSending Packet to %s...", dns_server);
+	if (sendto(s, (char*) buf,
+			sizeof(struct DNS_HEADER) + (strlen((const char*) qname) + 1)
+					+ sizeof(struct QUESTION), 0, (struct sockaddr*) &dest,
+			sizeof(dest)) < 0) {
+		perror("sendto failed");
+	}
+	printf("Done");
+
+	//Receive the answer
+	i = sizeof dest;
+	printf("\nReceiving answer...");
+	if (recvfrom(s, (char*) buf, sizeof(buf)-1, 0, (struct sockaddr*) &dest,
+			(socklen_t*) &i) < 0) {
+		perror("recvfrom failed");
+	}
+	*(buf+sizeof(buf)-1) = 0;
+	printf("Done");
+
+	dns = (struct DNS_HEADER*) buf;
+	if((sizeof(struct DNS_HEADER) + 
+		(strlen((const char*) qname) + 1)+ 
+		sizeof(struct QUESTION)) >= sizeof(buf))
+	{
+		perror("my_gethostbyname error");
+		goto out;
+	}
+	
+	//move ahead of the dns header and the query field
+	reader = &buf[sizeof(struct DNS_HEADER) + (strlen((const char*) qname) + 1)
+			+ sizeof(struct QUESTION)];
+
+	//printf("\nThe response contains : ");
+	//printf("\n %d Questions.", ntohs(dns->q_count));
+	//printf("\n %d Answers.", ntohs(dns->ans_count));
+	//printf("\n %d Authoritative Servers.", ntohs(dns->auth_count));
+	//printf("\n %d Additional records.\n\n", ntohs(dns->add_count));
+
+	//Start reading answers
+	stop = 0;
+	ans_max = ntohs(dns->ans_count);
+	if (ans_max > (sizeof(answers)/sizeof(answers[0])))
+		ans_max = (sizeof(answers)/sizeof(answers[0]));
+	for (i = 0; i < ans_max; i++) 
+	{
+		answers[i].name = ReadName(reader, buf, &stop);
+		reader = reader + stop;
+
+		answers[i].resource = (struct R_DATA*) (reader);
+		reader = reader + sizeof(struct R_DATA);
+
+		if (ntohs(answers[i].resource->type) == T_AAAA) //if its an ipv6 address
+				{
+			answers[i].rdata = (unsigned char*) malloc(
+					ntohs(answers[i].resource->data_len));
+
+			for (j = 0; j < ntohs(answers[i].resource->data_len); j++) {
+				answers[i].rdata[j] = reader[j];
+			}
+
+			answers[i].rdata[ntohs(answers[i].resource->data_len)] = '\0';
+
+			reader = reader + ntohs(answers[i].resource->data_len);
+		} else {
+			answers[i].rdata = ReadName(reader, buf, &stop);
+			reader = reader + stop;
+		}
+	}
+
+	//print answers
+	printf("\nAnswer Records : %d \n", ntohs(dns->ans_count));
+	for (i = 0; i < ans_max; i++) {
+		printf("Name : %s ", answers[i].name);
+
+		if (ntohs(answers[i].resource->type) == T_AAAA) //IPv6 address
+		{
+			char ip6_addr[IPV6ADDLEN_MAX] = {0};
+			memcpy(&a, answers[i].rdata, sizeof(struct in6_addr));
+			if(inet_ntop(AF_INET6, &a, ip6_addr, sizeof(ip6_addr))){
+				if(ip6)
+					memcpy(ip6, &a, sizeof(struct in6_addr));
+				printf("%p has IPv6 address : %s", ip6, ip6_addr);
+				ret = 1;
+			}else
+				printf("nohas IPv6 address len:%d", answers[i].resource->data_len);
+		}
+
+		if (ntohs(answers[i].resource->type) == 5) {
+			//Canonical name for an alias
+			printf("has alias name : %s", answers[i].rdata);
+		}
+		printf("\n");
+		free(answers[i].name);
+		free(answers[i].rdata);
+	}
+out:
+	close(s);
+	return ret;
+}
+
+int gethostbyname6_l(char *hostname,char* dev_name, struct in6_addr* ip6) 
+{
+	int i = 0;
+	unsigned long ret = 0;
+	char dns_servers[DNS_SERVER_NUM][64] = {0};
+
+	//Get the DNS servers from the resolv.conf file
+	char nv_dns[64]	= {0};
+	char ip_dns[64]	= {0};
+	
+    sprintf(nv_dns, "%s_ipv6_pridns_auto", dev_name);
+	sc_cfg_get(nv_dns, ip_dns, sizeof(ip_dns));
+	strcpy(dns_servers[0], ip_dns);
+
+	memset(nv_dns,0,sizeof(nv_dns));
+	memset(ip_dns,0,sizeof(ip_dns));
+	sprintf(nv_dns, "%s_ipv6_secdns_auto", dev_name);
+	sc_cfg_get(nv_dns, ip_dns, sizeof(ip_dns));
+	strcpy(dns_servers[1], ip_dns);
+
+	
+	//Now get the ip of this hostname , A record
+	for(i=0;i<DNS_SERVER_NUM;i++)
+	{
+		if(my_gethostbyname6(hostname, dev_name , dns_servers[i], T_AAAA, ip6))
+			return 0;
+	}
+	return -1;
+}
 
 
 /******************************************************************************/