[Bugfix][API-465][wifi] connman add hostname cache

Change-Id: Ia05ce523ff702beb6672e96adfe88b044b2442b8
diff --git a/meta/meta-mediatek-mt2735/recipes-connectivity/connman/connman/lynq_ap_cache_hostname.patch b/meta/meta-mediatek-mt2735/recipes-connectivity/connman/connman/lynq_ap_cache_hostname.patch
new file mode 100755
index 0000000..8cd4ca2
--- /dev/null
+++ b/meta/meta-mediatek-mt2735/recipes-connectivity/connman/connman/lynq_ap_cache_hostname.patch
@@ -0,0 +1,249 @@
+--- connman-1.41/src/dnsproxy.c	2022-01-28 22:48:01.000000000 +0800
++++ connman-1.41/src/dnsproxy_new.c	2022-08-27 15:39:40.864223400 +0800
+@@ -41,6 +41,7 @@
+ 
+ #include "connman.h"
+ 
++#include <gdhcp/gdhcp.h>
+ #define debug(fmt...) do { } while (0)
+ 
+ #if __BYTE_ORDER == __LITTLE_ENDIAN
+@@ -514,6 +515,47 @@
+ 	}
+ }
+ 
++static void send_ok_response(int sk, unsigned char *buf, size_t len,
++                const struct sockaddr *to, socklen_t tolen,
++                const char *hostname)
++{
++    struct domain_hdr *hdr;
++    int err,hostname_len;
++
++    debug("sk %d", sk);
++    hdr = (void *) (buf);
++
++    debug("cy----id 0x%04x qr %d opcode %d", hdr->id, hdr->qr, hdr->opcode);
++
++    hdr->qr = 1;
++    hdr->aa = 1;
++    hdr->rcode = ns_r_noerror;
++
++//    hdr->qdcount = 1;
++//    hdr->ancount = 1;
++    buf[5] = 1;
++    buf[7] = 1;
++    hdr->nscount = 0;
++    hdr->arcount = 0;
++
++    hdr->ra = 1;
++    hdr->aa = 1;
++    memcpy(buf + len, "\xc0\x0c\x00\x0c\x00\x01\x00\x00\x00\x00\x00", 11);
++    len += 11;
++    hostname_len = strlen(hostname);
++    buf[len++] =  hostname_len+ 1;
++    buf[len++] = hostname_len;
++    memcpy(buf + len, hostname, hostname_len);
++    len += hostname_len;
++    buf[len++] = 0;
++    err = sendto(sk, buf, len, MSG_NOSIGNAL, to, tolen);
++    if (err < 0) {
++        connman_error("Failed to send DNS response to %d: %s",
++                sk, strerror(errno));
++        return;
++    }
++}
++
+ static int get_req_udp_socket(struct request_data *req)
+ {
+ 	GIOChannel *channel;
+@@ -3560,6 +3602,41 @@
+ 				&ifdata->tcp6_listener_watch);
+ }
+ 
++static const char * get_inner_ip(char* ip, char *query) {
++    int len[4]= {0};
++    char *p = query;
++    char *ret = ip;
++    char *ptr[4] = {0};
++    int i;
++    for(i=0;i<4;i++) {
++        ptr[3-i] = p;
++        p = strstr(ptr[3-i], ".");
++        if (p == NULL) {
++            break;
++        }
++        len[3-i] = p - ptr[3-i];
++        if (len[3-i] > 3) {
++            return NULL;
++        }
++        p ++;
++    }
++
++    for(i=0;i<4;i++) {
++        if (len[i] == 0)
++            return NULL;
++    }
++
++    for(i=0;i<4;i++) {
++        memcpy(ip, ptr[i], len[i]);
++        ip += len[i];
++        *ip++ = '.';
++    }
++
++    ip[-1] = '\0';
++
++    return ret;
++}
++
+ static bool udp_listener_event(GIOChannel *channel, GIOCondition condition,
+ 				struct listener_data *ifdata, int family,
+ 				guint *listener_watch)
+@@ -3574,6 +3651,7 @@
+ 	void *client_addr;
+ 	socklen_t *client_addr_len;
+ 	int sk, err, len;
++    char ip[16], *hostname;
+ 
+ 	if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
+ 		connman_error("Error with UDP listener channel");
+@@ -3599,6 +3677,16 @@
+ 	debug("Received %d bytes (id 0x%04x)", len, buf[0] | buf[1] << 8);
+ 
+ 	err = parse_request(buf, len, query, sizeof(query));
++    get_inner_ip(ip, query);
++
++    if ((hostname = g_dhcp_server_find_hostname(ip)) != NULL) {
++
++        send_ok_response(sk, buf, len, client_addr,
++                *client_addr_len, hostname);
++        g_free(hostname);
++        return true;
++    }
++
+ 	if (err < 0 || (g_slist_length(server_list) == 0)) {
+ 		send_response(sk, buf, len, client_addr,
+ 				*client_addr_len, IPPROTO_UDP);
+--- connman-1.41/gdhcp/gdhcp.h	2022-01-28 22:48:01.000000000 +0800
++++ connman-1.41/gdhcp/gdhcp_new.h	2022-08-27 14:14:57.787351100 +0800
+@@ -232,6 +232,7 @@
+ 				GDHCPSaveLeaseFunc func, gpointer user_data);
+ void g_dhcp_server_set_lease_added_cb(GDHCPServer *dhcp_server,
+ 							GDHCPLeaseAddedCb cb);
++char * g_dhcp_server_find_hostname(const char *ip);
+ 
+ #ifdef __cplusplus
+ }
+--- connman-1.41/gdhcp/server.c	2022-01-28 22:48:01.000000000 +0800
++++ connman-1.41/gdhcp/server_new.c	2022-08-27 15:33:39.326208800 +0800
+@@ -107,13 +107,47 @@
+ 	return NULL;
+ }
+ 
++static GHashTable *cached_hostname_table = NULL;
++static int add_cached_hostname(const char * ip, const char * hostname)
++{
++    if (ip == NULL) {
++        return -1;
++    }
++    if (cached_hostname_table == NULL) {
++        cached_hostname_table = g_hash_table_new_full(g_str_hash, g_str_equal,
++                                NULL, g_free);
++    }
++    return g_hash_table_insert(cached_hostname_table, g_strdup(ip), g_strdup(hostname));
++}
++
++static int delete_cached_hostname(const char * ip)
++{
++    if (cached_hostname_table != NULL) {
++        return g_hash_table_remove(cached_hostname_table, ip);
++    }
++    return -1;
++}
++char * g_dhcp_server_find_hostname(const char * ip) {
++    if (cached_hostname_table == NULL) {
++        return NULL;
++    }
++    char * hostname = g_hash_table_lookup(cached_hostname_table, ip);
++    if (hostname != NULL) {
++        return g_strdup(hostname);
++    }
++    return NULL;
++}
++
+ static void remove_lease(GDHCPServer *dhcp_server, struct dhcp_lease *lease)
+ {
++    struct in_addr addr;
++    addr.s_addr = htonl(lease->lease_nip);
+ 	dhcp_server->lease_list =
+ 			g_list_remove(dhcp_server->lease_list, lease);
+ 
+ 	g_hash_table_remove(dhcp_server->nip_lease_hash,
+ 				GINT_TO_POINTER((int) lease->lease_nip));
++    delete_cached_hostname(inet_ntoa(addr));
+ 	g_free(lease);
+ }
+ 
+@@ -653,6 +687,10 @@
+ 	uint8_t type, *server_id_option, *request_ip_option;
+ 	uint16_t packet_len;
+ 	int re;
++    const uint8_t *host_name_ptr;
++    char hostname[128] = {0};
++    struct in_addr addr;
++    char *ip = NULL;
+ 
+ 	if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
+ 		dhcp_server->listener_watch = 0;
+@@ -664,7 +702,18 @@
+ 		return TRUE;
+ 	packet_len = (uint16_t)(unsigned int)re;
+ 
++    host_name_ptr = dhcp_get_option(&packet, packet_len, DHCP_HOST_NAME);
++    if (host_name_ptr != NULL) {
++        for(int i=0;i<127;i++) {
++            if( host_name_ptr[i] >= 0x20) {
++                hostname[i] = host_name_ptr[i];
++            }
++        }
++    }
++
++
+ 	type = check_packet_type(&packet, packet_len);
++    debug(dhcp_server, "hostname:%s,  type:%d", hostname, type);
+ 	if (type == 0)
+ 		return TRUE;
+ 
+@@ -682,12 +731,17 @@
+ 		requested_nip = get_be32(request_ip_option);
+ 
+ 	lease = find_lease_by_mac(dhcp_server, packet.chaddr);
++    if (lease && lease->lease_nip != 0) {
++        addr.s_addr = htonl(lease->lease_nip);
++        ip = inet_ntoa(addr);
++    }
+ 
+ 	switch (type) {
+ 	case DHCPDISCOVER:
+ 		debug(dhcp_server, "Received DISCOVER");
+ 
+ 		send_offer(dhcp_server, &packet, lease, requested_nip);
++        add_cached_hostname(ip, hostname);
+ 		break;
+ 	case DHCPREQUEST:
+ 		debug(dhcp_server, "Received REQUEST NIP %d",
+@@ -702,6 +756,7 @@
+ 			debug(dhcp_server, "Sending ACK");
+ 			send_ACK(dhcp_server, &packet,
+ 				lease->lease_nip);
++            add_cached_hostname(ip, hostname);
+ 			break;
+ 		}
+ 
+@@ -743,6 +798,7 @@
+ 	case DHCPINFORM:
+ 		debug(dhcp_server, "Received INFORM");
+ 		send_inform(dhcp_server, &packet);
++        add_cached_hostname(ip, hostname);
+ 		break;
+ 	}
+ 
diff --git a/meta/meta-mediatek-mt2735/recipes-connectivity/connman/connman_%.bbappend b/meta/meta-mediatek-mt2735/recipes-connectivity/connman/connman_%.bbappend
index 48244d8..76415a8 100755
--- a/meta/meta-mediatek-mt2735/recipes-connectivity/connman/connman_%.bbappend
+++ b/meta/meta-mediatek-mt2735/recipes-connectivity/connman/connman_%.bbappend
@@ -4,5 +4,6 @@
             file://lynq_wifi_ap_sta.patch \
             file://lynq_wifi_netmask.patch \
             file://lynq_ifconfig_cmd.patch \
+            file://lynq_ap_cache_hostname.patch \
             "