qcacld-3.0: Add support to use generic netlink sockets for userspace apps

Currently user space communication functions[cnss diag, PTT socket app]
in host driver uses netlink user sockets which is a security concern from
Linux Android SE policies.

Add support for to use netlink family cld80211 which uses generic
netlink sockets.

Change-Id: I4ea49ac6d7c9381212c93567fdc40f90e04dfba4
CRs-Fixed: 1112784
diff --git a/Kbuild b/Kbuild
index 3ce4903..6529453 100644
--- a/Kbuild
+++ b/Kbuild
@@ -1507,6 +1507,10 @@
 CDEFINES += -DWLAN_FEATURE_ROAM_OFFLOAD
 endif
 
+ifeq ($(CONFIG_CNSS_GENL), y)
+CDEFINES += -DCNSS_GENL
+endif
+
 ifeq ($(CONFIG_QCACLD_WLAN_LFR2),y)
 CDEFINES += -DWLAN_FEATURE_HOST_ROAM
 endif
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index a1351a1..d225add 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -114,6 +114,10 @@
 #include "wlan_pmo_ucfg_api.h"
 #include "sir_api.h"
 
+#ifdef CNSS_GENL
+#include <net/cnss_nl.h>
+#endif
+
 #ifdef MODULE
 #define WLAN_MODULE_NAME  module_name(THIS_MODULE)
 #else
@@ -9270,6 +9274,24 @@
 	}
 }
 
+/**
+ * nl_srv_bcast_svc() - Wrapper function to send bcast msgs to SVC mcast group
+ * @skb: sk buffer pointer
+ *
+ * Sends the bcast message to SVC multicast group with generic nl socket
+ * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send.
+ *
+ * Return: None
+ */
+static void nl_srv_bcast_svc(struct sk_buff *skb)
+{
+#ifdef CNSS_GENL
+	nl_srv_bcast(skb, CLD80211_MCGRP_SVC_MSGS, WLAN_NL_MSG_SVC);
+#else
+	nl_srv_bcast(skb);
+#endif
+}
+
 void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len)
 {
 	struct sk_buff *skb;
@@ -9354,7 +9376,7 @@
 	nlh->nlmsg_len += tlv_len;
 	skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len + tlv_len));
 
-	nl_srv_bcast(skb);
+	nl_srv_bcast_svc(skb);
 
 	return;
 }
diff --git a/core/hdd/src/wlan_hdd_oemdata.c b/core/hdd/src/wlan_hdd_oemdata.c
index 1f9e639..0179988 100644
--- a/core/hdd/src/wlan_hdd_oemdata.c
+++ b/core/hdd/src/wlan_hdd_oemdata.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -46,6 +46,10 @@
 #include "wma.h"
 #include "sme_api.h"
 
+#ifdef CNSS_GENL
+#include <net/cnss_nl.h>
+#endif
+
 static struct hdd_context_s *p_hdd_ctx;
 
 /**
@@ -163,6 +167,27 @@
 }
 
 /**
+ * nl_srv_ucast_oem() - Wrapper function to send ucast msgs to OEM
+ * @skb: sk buffer pointer
+ * @dst_pid: Destination PID
+ * @flag: flags
+ *
+ * Sends the ucast message to OEM with generic nl socket if CNSS_GENL
+ * is enabled. Else, use the legacy netlink socket to send.
+ *
+ * Return: None
+ */
+static void nl_srv_ucast_oem(struct sk_buff *skb, int dst_pid, int flag)
+{
+#ifdef CNSS_GENL
+	nl_srv_ucast(skb, dst_pid, flag, WLAN_NL_MSG_OEM,
+					CLD80211_MCGRP_OEM_MSGS);
+#else
+	nl_srv_ucast(skb, dst_pid, flag);
+#endif
+}
+
+/**
  * send_oem_reg_rsp_nlink_msg() - send oem registration response
  *
  * This function sends oem message to registered application process
@@ -240,7 +265,7 @@
 	hdd_notice("sending App Reg Response length (%d) to process pid (%d)",
 		   aniHdr->length, p_hdd_ctx->oem_pid);
 
-	(void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
+	(void)nl_srv_ucast_oem(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
 
 	return;
 }
@@ -285,7 +310,7 @@
 
 	hdd_notice("sending oem error response to process pid (%d)", app_pid);
 
-	(void)nl_srv_ucast(skb, app_pid, MSG_DONTWAIT);
+	(void)nl_srv_ucast_oem(skb, app_pid, MSG_DONTWAIT);
 
 	return;
 }
@@ -344,7 +369,7 @@
 	hdd_notice("sending Oem Data Response of len (%d) to process pid (%d)",
 		   oem_data_rsp->rsp_len, p_hdd_ctx->oem_pid);
 
-	(void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
+	(void)nl_srv_ucast_oem(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
 
 	return;
 }
@@ -543,7 +568,7 @@
 	hdd_notice("sending channel info resp for num channels (%d) to pid (%d)",
 		   numOfChannels, p_hdd_ctx->oem_pid);
 
-	(void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
+	(void)nl_srv_ucast_oem(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
 
 	return 0;
 }
@@ -604,7 +629,7 @@
 
 	hdd_info("sending oem response to process pid %d", app_pid);
 
-	(void)nl_srv_ucast(skb, app_pid, MSG_DONTWAIT);
+	(void)nl_srv_ucast_oem(skb, app_pid, MSG_DONTWAIT);
 
 	return error_code;
 }
@@ -670,7 +695,7 @@
 	hdd_info("send rsp to oem-pid:%d for get_capability",
 		 p_hdd_ctx->oem_pid);
 
-	(void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
+	(void)nl_srv_ucast_oem(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
 	return 0;
 }
 
@@ -781,11 +806,288 @@
 		  pPeerInfo->peer_chan_info.reg_info_1,
 		  pPeerInfo->peer_chan_info.reg_info_2);
 
-	(void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
+	(void)nl_srv_ucast_oem(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
 
 	return;
 }
 
+/**
+ * oem_app_reg_req_handler() - function to handle APP registration request
+ *                             from userspace
+ * @hdd_ctx: handle to HDD context
+ * @msg_hdr: pointer to ANI message header
+ * @pid: Process ID
+ *
+ * Return: 0 if success, error code otherwise
+ */
+static int oem_app_reg_req_handler(struct hdd_context_s *hdd_ctx,
+					tAniMsgHdr *msg_hdr, int pid)
+{
+	char *sign_str = NULL;
+
+	/* Registration request is only allowed for Qualcomm Application */
+	hdd_info("Received App Reg Req from App process pid(%d), len(%d)",
+			pid, msg_hdr->length);
+
+	sign_str = (char *)((char *)msg_hdr + sizeof(tAniMsgHdr));
+	if ((OEM_APP_SIGNATURE_LEN == msg_hdr->length) &&
+			(0 == strncmp(sign_str, OEM_APP_SIGNATURE_STR,
+				      OEM_APP_SIGNATURE_LEN))) {
+		hdd_info("Valid App Reg Req from oem app process pid(%d)", pid);
+
+		hdd_ctx->oem_app_registered = true;
+		hdd_ctx->oem_pid = pid;
+		send_oem_reg_rsp_nlink_msg();
+	} else {
+		hdd_err("Invalid signature in App Reg Req from pid(%d)", pid);
+		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_INVALID_SIGNATURE);
+		return -EPERM;
+	}
+
+	return 0;
+}
+
+/**
+ * oem_data_req_handler() - function to handle data_req from userspace
+ * @hdd_ctx: handle to HDD context
+ * @msg_hdr: pointer to ANI message header
+ * @pid: Process ID
+ *
+ * Return: 0 if success, error code otherwise
+ */
+static int oem_data_req_handler(struct hdd_context_s *hdd_ctx,
+				tAniMsgHdr *msg_hdr, int pid)
+{
+	hdd_info("Received Oem Data Request length(%d) from pid: %d",
+			msg_hdr->length, pid);
+
+	if ((!hdd_ctx->oem_app_registered) ||
+			(pid != hdd_ctx->oem_pid)) {
+		/* either oem app is not registered yet or pid is different */
+		hdd_err("OEM DataReq: app not registered(%d) or incorrect pid(%d)",
+				hdd_ctx->oem_app_registered, pid);
+		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_APP_NOT_REGISTERED);
+		return -EPERM;
+	}
+
+	if ((!msg_hdr->length) || (OEM_DATA_REQ_SIZE < msg_hdr->length)) {
+		hdd_err("Invalid length (%d) in Oem Data Request",
+				msg_hdr->length);
+		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_INVALID_MESSAGE_LENGTH);
+		return -EPERM;
+	}
+
+	oem_process_data_req_msg(msg_hdr->length,
+			(char *) ((char *)msg_hdr +
+				sizeof(tAniMsgHdr)));
+
+	return 0;
+}
+
+/**
+ * oem_chan_info_req_handler() - function to handle chan_info_req from userspace
+ * @hdd_ctx: handle to HDD context
+ * @msg_hdr: pointer to ANI message header
+ * @pid: Process ID
+ *
+ * Return: 0 if success, error code otherwise
+ */
+static int oem_chan_info_req_handler(struct hdd_context_s *hdd_ctx,
+					tAniMsgHdr *msg_hdr, int pid)
+{
+	hdd_info("Received channel info request, num channel(%d) from pid: %d",
+			msg_hdr->length, pid);
+
+	if ((!hdd_ctx->oem_app_registered) ||
+			(pid != hdd_ctx->oem_pid)) {
+		/* either oem app is not registered yet or pid is different */
+		hdd_err("Chan InfoReq: app not registered(%d) or incorrect pid(%d)",
+				hdd_ctx->oem_app_registered, pid);
+		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_APP_NOT_REGISTERED);
+		return -EPERM;
+	}
+
+	/* message length contains list of channel ids */
+	if ((!msg_hdr->length) ||
+			(WNI_CFG_VALID_CHANNEL_LIST_LEN < msg_hdr->length)) {
+		hdd_err("Invalid length (%d) in channel info request",
+				msg_hdr->length);
+		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_INVALID_MESSAGE_LENGTH);
+		return -EPERM;
+	}
+	oem_process_channel_info_req_msg(msg_hdr->length,
+			(char *)((char *)msg_hdr + sizeof(tAniMsgHdr)));
+
+	return 0;
+}
+
+/**
+ * oem_set_cap_req_handler() - function to handle set_cap_req from userspace
+ * @hdd_ctx: handle to HDD context
+ * @msg_hdr: pointer to ANI message header
+ * @pid: Process ID
+ *
+ * Return: 0 if success, error code otherwise
+ */
+static int oem_set_cap_req_handler(struct hdd_context_s *hdd_ctx,
+					tAniMsgHdr *msg_hdr, int pid)
+{
+	hdd_info("Received set oem cap req of length:%d from pid: %d",
+			msg_hdr->length, pid);
+
+	if ((!hdd_ctx->oem_app_registered) ||
+			(pid != hdd_ctx->oem_pid)) {
+		/* oem app is not registered yet or pid is different */
+		hdd_err("set_oem_capability : app not registered(%d) or incorrect pid(%d)",
+				hdd_ctx->oem_app_registered, pid);
+		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_APP_NOT_REGISTERED);
+		return -EPERM;
+	}
+
+	if ((!msg_hdr->length) ||
+			(sizeof(struct sme_oem_capability) < msg_hdr->length)) {
+		hdd_err("Invalid length (%d) in set_oem_capability",
+				msg_hdr->length);
+		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_INVALID_MESSAGE_LENGTH);
+		return -EPERM;
+	}
+
+	oem_process_set_cap_req_msg(msg_hdr->length, (char *)
+			((char *)msg_hdr + sizeof(tAniMsgHdr)),
+			pid);
+	return 0;
+}
+
+/**
+ * oem_get_cap_req_handler() - function to handle get_cap_req from userspace
+ * @hdd_ctx: handle to HDD context
+ * @msg_hdr: pointer to ANI message header
+ * @pid: Process ID
+ *
+ * Return: 0 if success, error code otherwise
+ */
+static int oem_get_cap_req_handler(struct hdd_context_s *hdd_ctx,
+					tAniMsgHdr *msg_hdr, int pid)
+{
+	hdd_info("Rcvd get oem capability req - length:%d from pid: %d",
+			msg_hdr->length, pid);
+
+	if ((!hdd_ctx->oem_app_registered) ||
+			(pid != hdd_ctx->oem_pid)) {
+		/* oem app is not registered yet or pid is different */
+		hdd_err("get_oem_capability : app not registered(%d) or incorrect pid(%d)",
+				hdd_ctx->oem_app_registered, pid);
+		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_APP_NOT_REGISTERED);
+		return -EPERM;
+	}
+
+	oem_process_get_cap_req_msg();
+	return 0;
+}
+
+/**
+ * oem_request_dispatcher() - OEM command dispatcher API
+ * @msg_hdr: ANI Message Header
+ * @pid: process id
+ *
+ * This API is used to dispatch the command from OEM depending
+ * on the type of the message received.
+ *
+ * Return: None
+ */
+static void oem_request_dispatcher(tAniMsgHdr *msg_hdr, int pid)
+{
+	switch (msg_hdr->type) {
+	case ANI_MSG_APP_REG_REQ:
+		oem_app_reg_req_handler(p_hdd_ctx, msg_hdr, pid);
+		break;
+
+	case ANI_MSG_OEM_DATA_REQ:
+		oem_data_req_handler(p_hdd_ctx, msg_hdr, pid);
+		break;
+
+	case ANI_MSG_CHANNEL_INFO_REQ:
+		oem_chan_info_req_handler(p_hdd_ctx, msg_hdr, pid);
+		break;
+
+	case ANI_MSG_SET_OEM_CAP_REQ:
+		oem_set_cap_req_handler(p_hdd_ctx, msg_hdr, pid);
+		break;
+
+	case ANI_MSG_GET_OEM_CAP_REQ:
+		oem_get_cap_req_handler(p_hdd_ctx, msg_hdr, pid);
+		break;
+
+	default:
+		hdd_err("Received Invalid message type (%d), length (%d)",
+				msg_hdr->type, msg_hdr->length);
+		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_INVALID_MESSAGE_TYPE);
+	}
+}
+
+#ifdef CNSS_GENL
+/**
+ * oem_cmd_handler() - API to handle OEM commands
+ * @data: Pointer to data
+ * @data_len: length of the received data
+ * @ctx: Pointer to the context
+ * @pid: Process id
+ *
+ * This API handles the command from OEM application from user space and
+ * send back event to user space if necessary.
+ *
+ * Return: None
+ */
+static void oem_cmd_handler(const void *data, int data_len, void *ctx, int pid)
+{
+	tAniMsgHdr *msg_hdr;
+	int ret;
+	struct nlattr *tb[CLD80211_ATTR_MAX + 1];
+
+	ret = wlan_hdd_validate_context(p_hdd_ctx);
+	if (ret) {
+		hdd_err("hdd ctx validate fails");
+		return;
+	}
+
+	if (nla_parse(tb, CLD80211_ATTR_MAX, data, data_len, NULL)) {
+		hdd_err("Invalid ATTR");
+		return;
+	}
+
+	if (!tb[CLD80211_ATTR_DATA]) {
+		hdd_err("attr ATTR_DATA failed");
+		return;
+	}
+
+	msg_hdr = (tAniMsgHdr *)nla_data(tb[CLD80211_ATTR_DATA]);
+	if (!msg_hdr) {
+		hdd_err("msg_hdr null");
+		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_NULL_MESSAGE_HEADER);
+		return;
+	}
+	oem_request_dispatcher(msg_hdr, pid);
+
+	return;
+}
+
+/**
+ * oem_activate_service() - API to register the oem command handler
+ * @hdd_ctx: Pointer to HDD Context
+ *
+ * This API is used to register the oem app command handler. Argument
+ * @pAdapter is given for prototype compatibility with legacy code.
+ *
+ * Return: 0
+ */
+int oem_activate_service(struct hdd_context_s *hdd_ctx)
+{
+	p_hdd_ctx = hdd_ctx;
+	register_cld_cmd_cb(WLAN_NL_MSG_OEM, oem_cmd_handler, NULL);
+	return 0;
+}
+#else
+
 /*
  * Callback function invoked by Netlink service for all netlink
  * messages (from user space) addressed to WLAN_NL_MSG_OEM
@@ -806,7 +1108,6 @@
 	struct nlmsghdr *nlh;
 	tAniMsgHdr *msg_hdr;
 	int ret;
-	char *sign_str = NULL;
 	nlh = (struct nlmsghdr *)skb->data;
 
 	if (!nlh) {
@@ -836,142 +1137,7 @@
 		return -EPERM;
 	}
 
-	switch (msg_hdr->type) {
-	case ANI_MSG_APP_REG_REQ:
-		/* Registration request is only allowed for Qualcomm Application */
-		hdd_notice("Received App Req Req from App process pid(%d), len(%d)",
-			   nlh->nlmsg_pid, msg_hdr->length);
-
-		sign_str = (char *)((char *)msg_hdr + sizeof(tAniMsgHdr));
-		if ((OEM_APP_SIGNATURE_LEN == msg_hdr->length) &&
-		    (0 == strncmp(sign_str, OEM_APP_SIGNATURE_STR,
-				  OEM_APP_SIGNATURE_LEN))) {
-			hdd_notice("Valid App Req Req from oem app process pid(%d)",
-				   nlh->nlmsg_pid);
-
-			p_hdd_ctx->oem_app_registered = true;
-			p_hdd_ctx->oem_pid = nlh->nlmsg_pid;
-			send_oem_reg_rsp_nlink_msg();
-		} else {
-			hdd_err("Invalid signature in App Reg Request from pid(%d)",
-				nlh->nlmsg_pid);
-			send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
-						   OEM_ERR_INVALID_SIGNATURE);
-			return -EPERM;
-		}
-		break;
-
-	case ANI_MSG_OEM_DATA_REQ:
-		hdd_notice("Received Oem Data Request length(%d) from pid: %d",
-			   msg_hdr->length, nlh->nlmsg_pid);
-
-		if ((!p_hdd_ctx->oem_app_registered) ||
-		    (nlh->nlmsg_pid != p_hdd_ctx->oem_pid)) {
-			/* either oem app is not registered yet or pid is different */
-			hdd_err("OEM DataReq: app not registered(%d) or incorrect pid(%d)",
-				p_hdd_ctx->oem_app_registered,
-				nlh->nlmsg_pid);
-			send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
-						   OEM_ERR_APP_NOT_REGISTERED);
-			return -EPERM;
-		}
-
-		if ((!msg_hdr->length) || (OEM_DATA_REQ_SIZE < msg_hdr->length)) {
-			hdd_err("Invalid length (%d) in Oem Data Request",
-				msg_hdr->length);
-			send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
-						   OEM_ERR_INVALID_MESSAGE_LENGTH);
-			return -EPERM;
-		}
-		oem_process_data_req_msg(msg_hdr->length,
-					 (char *)((char *)msg_hdr +
-						  sizeof(tAniMsgHdr)));
-		break;
-
-	case ANI_MSG_CHANNEL_INFO_REQ:
-		hdd_notice("Received channel info request, num channel(%d) from pid: %d",
-			   msg_hdr->length, nlh->nlmsg_pid);
-
-		if ((!p_hdd_ctx->oem_app_registered) ||
-		    (nlh->nlmsg_pid != p_hdd_ctx->oem_pid)) {
-			/* either oem app is not registered yet or pid is different */
-			hdd_err("Chan InfoReq: app not registered(%d) or incorrect pid(%d)",
-				p_hdd_ctx->oem_app_registered,
-				nlh->nlmsg_pid);
-			send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
-						   OEM_ERR_APP_NOT_REGISTERED);
-			return -EPERM;
-		}
-
-		/* message length contains list of channel ids */
-		if ((!msg_hdr->length) ||
-		    (WNI_CFG_VALID_CHANNEL_LIST_LEN < msg_hdr->length)) {
-			hdd_err("Invalid length (%d) in channel info request",
-				msg_hdr->length);
-			send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
-						   OEM_ERR_INVALID_MESSAGE_LENGTH);
-			return -EPERM;
-		}
-		oem_process_channel_info_req_msg(msg_hdr->length,
-						 (char *)((char *)msg_hdr +
-							  sizeof(tAniMsgHdr)));
-		break;
-
-	case ANI_MSG_SET_OEM_CAP_REQ:
-		hdd_info("Received set oem capability req of length:%d from pid: %d",
-			 msg_hdr->length, nlh->nlmsg_pid);
-
-		if ((!p_hdd_ctx->oem_app_registered) ||
-		    (nlh->nlmsg_pid != p_hdd_ctx->oem_pid)) {
-			/* oem app is not registered yet or pid is different */
-			hdd_err("set_oem_capability : app not registered(%d) or incorrect pid(%d)",
-				p_hdd_ctx->oem_app_registered,
-				nlh->nlmsg_pid);
-			send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
-						   OEM_ERR_APP_NOT_REGISTERED);
-			return -EPERM;
-		}
-
-		if ((!msg_hdr->length) ||
-			(sizeof(struct sme_oem_capability) < msg_hdr->length)) {
-			hdd_err("Invalid length (%d) in set_oem_capability",
-				msg_hdr->length);
-			send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
-						OEM_ERR_INVALID_MESSAGE_LENGTH);
-			return -EPERM;
-		}
-
-		oem_process_set_cap_req_msg(msg_hdr->length,
-					(char *)((char *)msg_hdr +
-						sizeof(tAniMsgHdr)),
-					nlh->nlmsg_pid);
-		break;
-
-	case ANI_MSG_GET_OEM_CAP_REQ:
-		hdd_info("Rcvd get oem capability req of length:%d from pid: %d",
-			 msg_hdr->length, nlh->nlmsg_pid);
-
-		if ((!p_hdd_ctx->oem_app_registered) ||
-		    (nlh->nlmsg_pid != p_hdd_ctx->oem_pid)) {
-			/* oem app is not registered yet or pid is different */
-			hdd_err("get_oem_capability : app not registered(%d) or incorrect pid(%d)",
-				p_hdd_ctx->oem_app_registered,
-				nlh->nlmsg_pid);
-			send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
-						   OEM_ERR_APP_NOT_REGISTERED);
-			return -EPERM;
-		}
-
-		oem_process_get_cap_req_msg();
-		break;
-
-	default:
-		hdd_err("Received Invalid message type (%d), length (%d)",
-			msg_hdr->type, msg_hdr->length);
-		send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
-					   OEM_ERR_INVALID_MESSAGE_TYPE);
-		return -EPERM;
-	}
+	oem_request_dispatcher(msg_hdr, nlh->nlmsg_pid);
 	return 0;
 }
 
@@ -1003,5 +1169,5 @@
 	/* Register the msg handler for msgs addressed to WLAN_NL_MSG_OEM */
 	return nl_srv_register(WLAN_NL_MSG_OEM, __oem_msg_callback);
 }
-
+#endif
 #endif