[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 \
"