Merge "Feature capability to fetch concurrent sessions on Wi-Fi Bands" into wlan-aosp.lnx.6.0
diff --git a/qcwcn/wifi_hal/Android.mk b/qcwcn/wifi_hal/Android.mk
index 1f9a572..c543531 100644
--- a/qcwcn/wifi_hal/Android.mk
+++ b/qcwcn/wifi_hal/Android.mk
@@ -51,6 +51,13 @@
 
 LOCAL_CFLAGS += -Wall -Werror
 
+ifdef WIFI_DRIVER_STATE_CTRL_PARAM
+LOCAL_CFLAGS += -DWIFI_DRIVER_STATE_CTRL_PARAM=\"$(WIFI_DRIVER_STATE_CTRL_PARAM)\"
+ifdef WIFI_DRIVER_STATE_ON
+LOCAL_CFLAGS += -DWIFI_DRIVER_STATE_ON=\"$(WIFI_DRIVER_STATE_ON)\"
+endif
+endif
+
 LOCAL_C_INCLUDES += \
 	$(LOCAL_PATH) \
 	external/libnl/include \
@@ -123,6 +130,13 @@
 # gscan.cpp: address of array 'cached_results[i].results' will always evaluate to 'true'
 LOCAL_CLANG_CFLAGS := -Wno-pointer-bool-conversion
 
+ifdef WIFI_DRIVER_STATE_CTRL_PARAM
+LOCAL_CFLAGS += -DWIFI_DRIVER_STATE_CTRL_PARAM=\"$(WIFI_DRIVER_STATE_CTRL_PARAM)\"
+ifdef WIFI_DRIVER_STATE_ON
+LOCAL_CFLAGS += -DWIFI_DRIVER_STATE_ON=\"$(WIFI_DRIVER_STATE_ON)\"
+endif
+endif
+
 LOCAL_C_INCLUDES += \
 	$(LOCAL_PATH) \
 	external/libnl/include \
diff --git a/qcwcn/wifi_hal/common.cpp b/qcwcn/wifi_hal/common.cpp
index 3d72e76..35ef627 100644
--- a/qcwcn/wifi_hal/common.cpp
+++ b/qcwcn/wifi_hal/common.cpp
@@ -16,12 +16,12 @@
 
 #include <stdlib.h>
 #include <linux/pkt_sched.h>
+#include <linux-private/linux/fib_rules.h>
 #include <netlink/object-api.h>
 #include <netlink-private/object-api.h>
 #include <netlink-private/types.h>
 #include <dlfcn.h>
 #include <pthread.h>
-
 #include "wifi_hal.h"
 #include "common.h"
 #include <errno.h>
diff --git a/qcwcn/wifi_hal/llstats.cpp b/qcwcn/wifi_hal/llstats.cpp
index b02da62..fc36df9 100644
--- a/qcwcn/wifi_hal/llstats.cpp
+++ b/qcwcn/wifi_hal/llstats.cpp
@@ -1152,10 +1152,19 @@
 
                         memset(pIfaceStat, 0, resultsBufSize);
                         if(mResultsParams.iface_stat) {
-                            memcpy ( pIfaceStat, mResultsParams.iface_stat,
-                                sizeof(wifi_iface_stat));
-                            free (mResultsParams.iface_stat);
-                            mResultsParams.iface_stat = pIfaceStat;
+                            if(resultsBufSize > sizeof(wifi_iface_stat)) {
+                                memcpy ( pIfaceStat, mResultsParams.iface_stat,
+                                    sizeof(wifi_iface_stat));
+                                free (mResultsParams.iface_stat);
+                                mResultsParams.iface_stat = pIfaceStat;
+                            } else {
+                                ALOGE("%s: numPeers = %u, num_rates= %u, "
+                                      "either numPeers or num_rates is invalid",
+                                      __FUNCTION__,numPeers,num_rates);
+                                status = WIFI_ERROR_UNKNOWN;
+                                free(pIfaceStat);
+                                goto cleanup;
+                            }
                         }
                         wifi_peer_info *pPeerStats;
                         pIfaceStat->num_peers = numPeers;
diff --git a/qcwcn/wifi_hal/nan_ind.cpp b/qcwcn/wifi_hal/nan_ind.cpp
index 12d2d97..6496314 100644
--- a/qcwcn/wifi_hal/nan_ind.cpp
+++ b/qcwcn/wifi_hal/nan_ind.cpp
@@ -346,6 +346,11 @@
             /* Populate receive discovery attribute from
                received TLV */
             idx = event->num_rx_discovery_attr;
+            if (idx < 0 || idx >= NAN_MAX_POSTDISCOVERY_LEN) {
+                ALOGE("NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_RECEIVE"
+                      " Incorrect index:%d >= %d", idx, NAN_MAX_POSTDISCOVERY_LEN);
+                break;
+            }
             ret = getNanReceivePostDiscoveryVal(outputTlv.value,
                                                 outputTlv.length,
                                                 &event->discovery_attr[idx]);
diff --git a/qcwcn/wifi_hal/ring_buffer.cpp b/qcwcn/wifi_hal/ring_buffer.cpp
index cd9865a..5918923 100644
--- a/qcwcn/wifi_hal/ring_buffer.cpp
+++ b/qcwcn/wifi_hal/ring_buffer.cpp
@@ -160,7 +160,7 @@
                                      // write in current buffer
     unsigned int total_push_in_rd_ptr = 0; // Total amount of push in read pointer in this write
 
-    if (record_length > rbc->each_buf_size) {
+    if (record_length > rbc->each_buf_size || length > rbc->each_buf_size) {
         return RB_FAILURE;
     }
 
@@ -279,6 +279,17 @@
             }
         }
         rb_unlock(&rbc->rb_rw_lock);
+        if(rbc->bufs[rbc->wr_buf_no].data == NULL || (rbc->bufs[rbc->wr_buf_no].data + rbc->cur_wr_buf_idx) == NULL ||
+                buf == NULL || buf + bytes_written == NULL) {
+            ALOGE("The read or Write buffer is null");
+            return RB_FAILURE;
+        }
+        if (((bytes_written + cur_copy_len) > length
+                || (rbc->cur_wr_buf_idx + cur_copy_len) > rbc->each_buf_size)) {
+            ALOGE("LOG_RB rb_write overflow - cur_copy_len=%d wr_buf[max=%zu no=%d idx=%d] buf[max=%zu accessed=%d]",
+              cur_copy_len, rbc->each_buf_size, rbc->wr_buf_no, rbc->cur_wr_buf_idx, length, bytes_written + cur_copy_len);
+            return RB_FAILURE;
+        }
 
         /* don't use lock while doing memcpy, so that we don't block the read
          * context for too long. There is no harm while writing the memory if
@@ -476,7 +487,13 @@
             cur_read_len = rbc->cur_wr_buf_idx - rbc->cur_rd_buf_idx;
         } else {
             /* write is rolled over and just behind the read */
-            cur_read_len = rbc->bufs[rbc->rd_buf_no].last_wr_index - rbc->cur_rd_buf_idx;
+            if (rbc->bufs[rbc->rd_buf_no].last_wr_index >= rbc->cur_rd_buf_idx) {
+                cur_read_len = rbc->bufs[rbc->rd_buf_no].last_wr_index - rbc->cur_rd_buf_idx;
+            } else {
+                ALOGE("Alert: cur_read_len=%u invalid, rd_buf[no=%d rd_idx=%d wr_index=%d]",cur_read_len, rbc->rd_buf_no, rbc->cur_rd_buf_idx, rbc->bufs[rbc->rd_buf_no].last_wr_index);
+                rb_unlock(&rbc->rb_rw_lock);
+                return NULL;
+            }
         }
     } else {
         if (rbc->cur_rd_buf_idx == 0) {
diff --git a/qcwcn/wifi_hal/wifi_hal.cpp b/qcwcn/wifi_hal/wifi_hal.cpp
index 8d35058..ed58f45 100644
--- a/qcwcn/wifi_hal/wifi_hal.cpp
+++ b/qcwcn/wifi_hal/wifi_hal.cpp
@@ -25,7 +25,7 @@
 #include <netpacket/packet.h>
 #include <linux/filter.h>
 #include <linux/errqueue.h>
-
+#include <linux-private/linux/fib_rules.h>
 #include <linux/pkt_sched.h>
 #include <netlink/object-api.h>
 #include <netlink/netlink.h>
@@ -948,6 +948,39 @@
     return ret;
 }
 
+#ifdef WIFI_DRIVER_STATE_CTRL_PARAM
+static int wifi_update_driver_state(const char *state) {
+    struct timespec ts;
+    int len, fd, ret = 0, count = 5;
+    ts.tv_sec = 0;
+    ts.tv_nsec = 200 * 1000000L;
+    do {
+        if (access(WIFI_DRIVER_STATE_CTRL_PARAM, W_OK) == 0)
+            break;
+        nanosleep(&ts, (struct timespec *)NULL);
+    } while (--count > 0); /* wait at most 1 second for completion. */
+    if (count == 0) {
+        ALOGE("Failed to access driver state control param %s, %d at %s",
+              strerror(errno), errno, WIFI_DRIVER_STATE_CTRL_PARAM);
+        return -1;
+    }
+    fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_STATE_CTRL_PARAM, O_WRONLY));
+    if (fd < 0) {
+        ALOGE("Failed to open driver state control param at %s",
+              WIFI_DRIVER_STATE_CTRL_PARAM);
+        return -1;
+    }
+    len = strlen(state) + 1;
+    if (TEMP_FAILURE_RETRY(write(fd, state, len)) != len) {
+        ALOGE("Failed to write driver state control param at %s",
+              WIFI_DRIVER_STATE_CTRL_PARAM);
+        ret = -1;
+    }
+    close(fd);
+    return ret;
+}
+#endif
+
 wifi_error wifi_wait_for_driver_ready(void)
 {
     // This function will wait to make sure basic client netdev is created
@@ -955,6 +988,12 @@
     int count = (POLL_DRIVER_MAX_TIME_MS * 1000) / POLL_DRIVER_DURATION_US;
     FILE *fd;
 
+#if defined(WIFI_DRIVER_STATE_CTRL_PARAM) && defined(WIFI_DRIVER_STATE_ON)
+    if (wifi_update_driver_state(WIFI_DRIVER_STATE_ON) < 0) {
+        return WIFI_ERROR_UNKNOWN;
+    }
+#endif
+
     do {
         if ((fd = fopen("/sys/class/net/wlan0", "r")) != NULL) {
             fclose(fd);
@@ -1792,6 +1831,11 @@
 
 static bool is_wifi_interface(const char *name)
 {
+    // filter out bridge interface
+    if (strstr(name, "br") != NULL) {
+        return false;
+    }
+
     if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0
         && strncmp(name, "wifi", 4) != 0
         && strncmp(name, "swlan", 5) != 0) {
diff --git a/qcwcn/wifi_hal/wifilogger_diag.cpp b/qcwcn/wifi_hal/wifilogger_diag.cpp
index 827e235..e2bb153 100644
--- a/qcwcn/wifi_hal/wifilogger_diag.cpp
+++ b/qcwcn/wifi_hal/wifilogger_diag.cpp
@@ -1009,6 +1009,11 @@
                 payloadlen = diag_msg_hdr->u.msg_hdr.payload_len;
                 hdr_size = sizeof(fw_diag_msg_hdr_t);
                 payload = diag_msg_hdr->payload;
+                if ((count + hdr_size + payloadlen) > length) {
+                    ALOGE("WLAN_DIAG_TYPE_MSG - possible buffer over access, length=%d count=%d hdr_size=%d payload len=%d",
+                           length, count, hdr_size, payloadlen);
+                    return WIFI_ERROR_UNKNOWN;
+                }
                 process_firmware_prints(info, (u8 *)diag_msg_fixed_hdr,
                                        payloadlen + hdr_size);
                 break;
@@ -1019,6 +1024,11 @@
                 payloadlen = diag_msg_hdr_v2->u.msg_hdr.payload_len;
                 hdr_size = sizeof(fw_diag_msg_hdr_v2_t);
                 payload = diag_msg_hdr_v2->payload;
+                if ((count + hdr_size + payloadlen) > length) {
+                    ALOGE("WLAN_DIAG_TYPE_MSG_V2 - possible buffer over access, length=%d count=%d hdr_size=%d payload len=%d",
+                           length, count, hdr_size, payloadlen);
+                    return WIFI_ERROR_UNKNOWN;
+                }
                 process_firmware_prints(info, (u8 *)diag_msg_fixed_hdr,
                                        payloadlen + hdr_size);
                 break;
@@ -1030,6 +1040,11 @@
                 payload = diag_msg_hdr->payload;
                 payloadlen = diag_msg_hdr->u.payload_len;
                 hdr_size = sizeof(fw_diag_msg_hdr_t);
+                if ((count + hdr_size + payloadlen) > length) {
+                    ALOGE("WLAN_DIAG_TYPE_CONFIG - possible buffer over access, length=%d count=%d hdr_size=%d payload len=%d",
+                           length, count, hdr_size, payloadlen);
+                    return WIFI_ERROR_UNKNOWN;
+                }
                 process_firmware_prints(info, (u8 *)diag_msg_hdr,
                                         payloadlen + hdr_size);
             }
diff --git a/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c b/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
index 5ee1119..8163fb5 100644
--- a/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
+++ b/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
@@ -209,7 +209,7 @@
 	struct nlattr *attr, *attr1, *attr2;
 	u8 *beacon_ies = NULL;
 	size_t beacon_ies_len = 0;
-	u8 seg0, seg1;
+	u8 seg1;
 
 	os_memset(&data, 0, sizeof(struct bss_info));
 
@@ -330,12 +330,9 @@
 			}
 			break;
 		case CHANWIDTH_80MHZ:
-			seg0 = info->vht_op_info_chan_center_freq_seg0_idx;
 			seg1 = info->vht_op_info_chan_center_freq_seg1_idx;
-			if (seg1 && abs(seg1 - seg0) == 8)
-				data.bw = 160;
-			else if (seg1)
-				/* Notifying 80P80 as bandwidth = 160 */
+			if (seg1)
+				/* Notifying 80P80 also as bandwidth = 160 */
 				data.bw = 160;
 			else
 				data.bw = 80;
@@ -377,6 +374,27 @@
 		if (he_info->he_oper_params &
 		    IEEE80211_HE_OPERATION_VHT_OPER_MASK) {
 			ch_bw = opr[HE_OPER_VHT_CH_WIDTH_OFFSET];
+			switch (ch_bw) {
+			case CHANWIDTH_USE_HT:
+				/* TO DO */
+				break;
+			case CHANWIDTH_80MHZ:
+				seg1 = opr[HE_OPER_VHT_CENTER_FRQ_SEG1_OFFSET];
+				if (seg1)
+					/* Notifying 80P80 also as bandwidth = 160 */
+					data.bw = 160;
+				else
+					data.bw = 80;
+				break;
+			case CHANWIDTH_160MHZ:
+				data.bw = 160;
+				break;
+			case CHANWIDTH_80P80MHZ:
+				data.bw = 160;
+				break;
+			default:
+				break;
+			}
 			opr += (HE_OPER_VHT_MAX_OFFSET + 1);
 		}
 
@@ -389,24 +407,25 @@
 		    IEEE80211_HE_OPERATION_6G_OPER_MASK) {
 			ch_bw = (opr[HE_OPER_6G_PARAMS_OFFSET] &
 				 HE_OPER_6G_PARAMS_SUB_CH_BW_MASK);
+			switch (ch_bw) {
+			case HE_CHANWIDTH_20MHZ:
+				data.bw = 20;
+				break;
+			case HE_CHANWIDTH_40MHZ:
+				data.bw = 40;
+				break;
+			case HE_CHANWIDTH_80MHZ:
+				data.bw = 80;
+				break;
+			case HE_CHANWIDTH_160MHZ:
+				/* Notifying 80P80 also as bandwidth = 160 */
+				data.bw = 160;
+				break;
+			default:
+				wpa_printf(MSG_ERROR,"Invalid channel width received : %u", ch_bw);
+			}
 		}
 
-		switch (ch_bw) {
-		case CHANWIDTH_USE_HT:
-			/* TO DO */
-			break;
-		case CHANWIDTH_80MHZ:
-			data.bw = 80;
-			break;
-		case CHANWIDTH_160MHZ:
-			data.bw = 160;
-			break;
-		case CHANWIDTH_80P80MHZ:
-			data.bw = 160;
-			break;
-		default:
-			wpa_printf(MSG_ERROR,"Invalid channel width received : %u", ch_bw);
-		}
 	}
 
 parse_beacon_ies:
@@ -1500,11 +1519,13 @@
 int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration)
 {
 	char buf[MAX_DRV_CMD_SIZE];
+	char reply_buf[MAX_DRV_CMD_SIZE];
 
 	memset(buf, 0, sizeof(buf));
+	memset(reply_buf, 0, sizeof(reply_buf));
 	wpa_printf(MSG_DEBUG, "%s: Entry", __func__);
 	snprintf(buf, sizeof(buf), "P2P_SET_NOA %d %d %d", count, start, duration);
-	return wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(buf)+1);
+	return wpa_driver_nl80211_driver_cmd(priv, buf, reply_buf, sizeof(reply_buf));
 }
 
 int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len)
@@ -1517,11 +1538,13 @@
 int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow)
 {
 	char buf[MAX_DRV_CMD_SIZE];
+	char reply_buf[MAX_DRV_CMD_SIZE];
 
 	memset(buf, 0, sizeof(buf));
+	memset(reply_buf, 0, sizeof(reply_buf));
 	wpa_printf(MSG_DEBUG, "%s: Entry", __func__);
 	snprintf(buf, sizeof(buf), "P2P_SET_PS %d %d %d", legacy_ps, opp_ps, ctwindow);
-	return wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(buf) + 1);
+	return wpa_driver_nl80211_driver_cmd(priv, buf, reply_buf, sizeof(reply_buf));
 }
 
 int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon,
diff --git a/qcwcn/wpa_supplicant_8_lib/wpa_driver_common_lib.h b/qcwcn/wpa_supplicant_8_lib/wpa_driver_common_lib.h
index d5deec3..6249d14 100644
--- a/qcwcn/wpa_supplicant_8_lib/wpa_driver_common_lib.h
+++ b/qcwcn/wpa_supplicant_8_lib/wpa_driver_common_lib.h
@@ -30,7 +30,7 @@
 #ifndef WPA_DRIVER_COMMON_LIB
 #define WPA_DRIVER_COMMON_LIB
 
-#include "android_drv.h"	//needed?
+#include "android_drv.h"
 #define OUI_LEN		3
 #define MAX_CMD_LEN	32
 #define MAC_ADDR_LEN	6
@@ -40,6 +40,8 @@
 #define IEEE80211_HE_OPERATION_6G_OPER_MASK 0x00020000
 
 #define HE_OPER_VHT_CH_WIDTH_OFFSET 0
+#define HE_OPER_VHT_CENTER_FRQ_SEG0_OFFSET 1
+#define HE_OPER_VHT_CENTER_FRQ_SEG1_OFFSET 2
 #define HE_OPER_VHT_MAX_OFFSET 2
 
 #define HE_OPER_CO_LOCATED_MAX_OFFSET 0
@@ -102,6 +104,13 @@
 #define CHANWIDTH_80P80MHZ VHT_CHANWIDTH_80P80MHZ
 #endif /* CHANWIDTH_80P80MHZ */
 
+/* HE channel widths */
+
+#define HE_CHANWIDTH_20MHZ     0
+#define HE_CHANWIDTH_40MHZ     1
+#define HE_CHANWIDTH_80MHZ     2
+#define HE_CHANWIDTH_160MHZ    3
+
 /**
  * enum qca_wlan_vendor_attr_get_station - Sub commands used by
  * QCA_NL80211_VENDOR_SUBCMD_GET_STATION to get the corresponding