summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSelvaraj, Sridhar <sselvara@codeaurora.org>2017-02-21 12:47:11 +0530
committerqcabuildsw <qcabuildsw@localhost>2017-03-07 02:18:54 -0800
commitfcb39cb0b884428589faa7db56f81843e391b479 (patch)
tree6edde0e21b14791d59d4002a082f717570e620d5
parentd1b1a1ebbb0406295e2fc4d12140def0b632af0e (diff)
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
-rw-r--r--Kbuild4
-rw-r--r--core/hdd/src/wlan_hdd_main.c24
-rw-r--r--core/hdd/src/wlan_hdd_oemdata.c456
-rw-r--r--core/utils/fwlog/dbglog_host.c154
-rw-r--r--core/utils/logging/src/wlan_logging_sock_svc.c110
-rw-r--r--core/utils/nlink/inc/wlan_nlink_srv.h10
-rw-r--r--core/utils/nlink/src/wlan_nlink_srv.c197
-rw-r--r--core/utils/ptt/inc/wlan_ptt_sock_svc.h15
-rw-r--r--core/utils/ptt/src/wlan_ptt_sock_svc.c126
9 files changed, 901 insertions, 195 deletions
diff --git a/Kbuild b/Kbuild
index 1b85149bc22d..6140bbf0d9a8 100644
--- a/Kbuild
+++ b/Kbuild
@@ -1243,6 +1243,10 @@ ifeq ($(CONFIG_QCACLD_WLAN_LFR3),y)
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 414f857f05ef..8a93f786a72a 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -109,6 +109,10 @@
#include "cds_utils.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
@@ -9072,6 +9076,24 @@ void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
}
}
+/**
+ * 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;
@@ -9156,7 +9178,7 @@ void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len)
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 6196b904ff57..01799882c9a8 100644
--- a/core/hdd/src/wlan_hdd_oemdata.c
+++ b/core/hdd/src/wlan_hdd_oemdata.c
@@ -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 @@ int iw_get_oem_data_cap(struct net_device *dev,
}
/**
+ * 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 @@ static void send_oem_reg_rsp_nlink_msg(void)
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 @@ static void send_oem_err_rsp_nlink_msg(int32_t app_pid, uint8_t error_code)
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 @@ void hdd_send_oem_data_rsp_msg(struct oem_data_rsp *oem_data_rsp)
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 @@ static int oem_process_channel_info_req_msg(int numOfChannels, char *chanList)
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 @@ static int oem_process_set_cap_req_msg(int oem_cap_len,
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 @@ static int oem_process_get_cap_req_msg(void)
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 @@ void hdd_send_peer_status_ind_to_oem_app(struct qdf_mac_addr *peerMac,
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 @@ static int oem_msg_callback(struct sk_buff *skb)
struct nlmsghdr *nlh;
tAniMsgHdr *msg_hdr;
int ret;
- char *sign_str = NULL;
nlh = (struct nlmsghdr *)skb->data;
if (!nlh) {
@@ -836,142 +1137,7 @@ static int oem_msg_callback(struct sk_buff *skb)
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 @@ int oem_activate_service(struct hdd_context_s *hdd_ctx)
/* 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
diff --git a/core/utils/fwlog/dbglog_host.c b/core/utils/fwlog/dbglog_host.c
index 11be14cb7faa..1654407fef26 100644
--- a/core/utils/fwlog/dbglog_host.c
+++ b/core/utils/fwlog/dbglog_host.c
@@ -46,6 +46,10 @@
#endif /* WLAN_OPEN_SOURCE */
#include "wmi_unified_priv.h"
+#ifdef CNSS_GENL
+#include <net/cnss_nl.h>
+#endif
+
#ifdef MULTI_IF_NAME
#define CLD_DEBUGFS_DIR "cld" MULTI_IF_NAME
#else
@@ -1598,6 +1602,24 @@ dbglog_debugfs_raw_data(wmi_unified_t wmi_handle, const uint8_t *buf,
#endif /* WLAN_OPEN_SOURCE */
/**
+ * nl_srv_bcast_fw_logs() - Wrapper func to send bcast msgs to FW logs mcast grp
+ * @skb: sk buffer pointer
+ *
+ * Sends the bcast message to FW logs multicast group with generic nl socket
+ * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send.
+ *
+ * Return: zero on success, error code otherwise
+ */
+static int nl_srv_bcast_fw_logs(struct sk_buff *skb)
+{
+#ifdef CNSS_GENL
+ return nl_srv_bcast(skb, CLD80211_MCGRP_FW_LOGS, WLAN_NL_MSG_CNSS_DIAG);
+#else
+ return nl_srv_bcast(skb);
+#endif
+}
+
+/**
* send_fw_diag_nl_data - pack the data from fw diag event handler
* @buffer: buffer of diag event
* @len: length of the diag event
@@ -1645,10 +1667,10 @@ static int send_fw_diag_nl_data(const uint8_t *buffer, A_UINT32 len,
/* data buffer offset from nlmsg_hdr + sizeof(int) radio */
memcpy(nlmsg_data(nlh) + sizeof(radio), buffer, len);
- res = nl_srv_bcast(skb_out);
+ res = nl_srv_bcast_fw_logs(skb_out);
if ((res < 0) && (res != -ESRCH)) {
AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1,
- ("%s: nl_srv_bcast failed 0x%x\n",
+ ("%s: nl_srv_bcast_fw_logs failed 0x%x\n",
__func__, res));
return res;
}
@@ -1745,10 +1767,10 @@ send_diag_netlink_data(const uint8_t *buffer, A_UINT32 len, A_UINT32 cmd)
slot->dropped = get_version;
memcpy(slot->payload, buffer, len);
- res = nl_srv_bcast(skb_out);
+ res = nl_srv_bcast_fw_logs(skb_out);
if ((res < 0) && (res != -ESRCH)) {
AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1,
- ("%s: nl_srv_bcast failed 0x%x\n",
+ ("%s: nl_srv_bcast_fw_logs failed 0x%x\n",
__func__, res));
return res;
}
@@ -1805,10 +1827,10 @@ dbglog_process_netlink_data(wmi_unified_t wmi_handle, const uint8_t *buffer,
slot->dropped = cpu_to_le32(dropped);
memcpy(slot->payload, buffer, len);
- res = nl_srv_bcast(skb_out);
+ res = nl_srv_bcast_fw_logs(skb_out);
if ((res < 0) && (res != -ESRCH)) {
AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1,
- ("%s: nl_srv_ucast failed 0x%x\n",
+ ("%s: nl_srv_bcast_fw_logs failed 0x%x\n",
__func__, res));
return res;
}
@@ -4090,6 +4112,98 @@ static int dbglog_debugfs_remove(wmi_unified_t wmi_handle)
}
#endif /* WLAN_OPEN_SOURCE */
+/**
+ * cnss_diag_handle_crash_inject() - API to handle crash inject command
+ * @slot: pointer to struct dbglog_slot
+ *
+ * API to handle CNSS diag crash inject command
+ *
+ * Return: None
+ */
+static void cnss_diag_handle_crash_inject(struct dbglog_slot *slot)
+{
+ switch (slot->diag_type) {
+ case DIAG_TYPE_CRASH_INJECT:
+ if (slot->length != 2) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("crash_inject cmd error\n"));
+ return;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
+ ("%s : DIAG_TYPE_CRASH_INJECT: %d %d\n", __func__,
+ slot->payload[0], slot->payload[1]));
+ if (!tgt_assert_enable) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
+ ("%s: tgt Assert Disabled\n", __func__));
+ return;
+ }
+ wma_cli_set2_command(0, (int)GEN_PARAM_CRASH_INJECT,
+ slot->payload[0],
+ slot->payload[1], GEN_CMD);
+ break;
+ default:
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown cmd[%d] error\n",
+ slot->diag_type));
+ break;
+ }
+}
+
+#ifdef CNSS_GENL
+/**
+ * cnss_diag_cmd_handler() - API to handle CNSS diag command
+ * @data: Data received
+ * @data_len: length of the data received
+ * @ctx: Pointer to stored context
+ * @pid: Process ID
+ *
+ * API to handle CNSS diag commands from user space
+ *
+ * Return: None
+ */
+static void cnss_diag_cmd_handler(const void *data, int data_len,
+ void *ctx, int pid)
+{
+ struct dbglog_slot *slot = NULL;
+ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
+
+ if (nla_parse(tb, CLD80211_ATTR_MAX, data, data_len, NULL)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: nla parse fails \n",
+ __func__));
+ return;
+ }
+
+ if (!tb[CLD80211_ATTR_DATA]) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: attr VENDOR_DATA fails \n",
+ __func__));
+ return;
+ }
+ slot = (struct dbglog_slot *)nla_data(tb[CLD80211_ATTR_DATA]);
+
+ if (!slot) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: data NULL \n", __func__));
+ return;
+ }
+
+ cnss_diag_handle_crash_inject(slot);
+ return;
+}
+
+/**
+ * cnss_diag_activate_service() - API to register CNSS diag cmd handler
+ *
+ * API to register the CNSS diag command handler using new genl infra.
+ * Return type is zero to match with legacy prototype
+ *
+ * Return: 0
+ */
+int cnss_diag_activate_service(void)
+{
+ register_cld_cmd_cb(WLAN_NL_MSG_CNSS_DIAG, cnss_diag_cmd_handler, NULL);
+ return 0;
+}
+
+#else
+
/**---------------------------------------------------------------------------
\brief cnss_diag_msg_callback() - Call back invoked by netlink service
@@ -4104,7 +4218,6 @@ static int dbglog_debugfs_remove(wmi_unified_t wmi_handle)
static int cnss_diag_msg_callback(struct sk_buff *skb)
{
struct nlmsghdr *nlh;
- struct dbglog_slot *slot;
A_UINT8 *msg;
nlh = (struct nlmsghdr *)skb->data;
@@ -4115,33 +4228,9 @@ static int cnss_diag_msg_callback(struct sk_buff *skb)
}
msg = NLMSG_DATA(nlh);
+ cnss_diag_handle_crash_inject((struct dbglog_slot *)msg);
- slot = (struct dbglog_slot *)msg;
- switch (slot->diag_type) {
- case DIAG_TYPE_CRASH_INJECT:
- if (slot->length == 2) {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
- ("%s : DIAG_TYPE_CRASH_INJECT: %d %d\n",
- __func__, slot->payload[0], slot->payload[1]));
- if (!tgt_assert_enable) {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
- ("%s: tgt Assert Disabled\n",
- __func__));
- return 0;
- }
- wma_cli_set2_command(0, GEN_PARAM_CRASH_INJECT,
- slot->payload[0], slot->payload[1],
- GEN_CMD);
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("crash_inject cmd error\n"));
- }
- break;
- default:
- break;
- }
return 0;
-
}
/**---------------------------------------------------------------------------
@@ -4168,6 +4257,7 @@ int cnss_diag_activate_service(void)
}
return 0;
}
+#endif
static A_BOOL
dbglog_wow_print_handler(A_UINT32 mod_id,
diff --git a/core/utils/logging/src/wlan_logging_sock_svc.c b/core/utils/logging/src/wlan_logging_sock_svc.c
index 79db19389782..dd43d7621e2e 100644
--- a/core/utils/logging/src/wlan_logging_sock_svc.c
+++ b/core/utils/logging/src/wlan_logging_sock_svc.c
@@ -46,6 +46,10 @@
#include "wlan_hdd_main.h"
#include "pktlog_ac.h"
+#ifdef CNSS_GENL
+#include <net/cnss_nl.h>
+#endif
+
#define MAX_NUM_PKT_LOG 32
/**
@@ -78,7 +82,8 @@ static uint8_t grx_count;
#define ANI_NL_MSG_LOG_TYPE 89
#define ANI_NL_MSG_READY_IND_TYPE 90
-#define MAX_LOGMSG_LENGTH 4096
+#define MAX_LOGMSG_LENGTH 2048
+#define MAX_SKBMSG_LENGTH 4096
#define MAX_PKTSTATS_LENGTH 2048
#define MAX_PKTSTATS_BUFF 16
@@ -172,6 +177,7 @@ static struct pkt_stats_msg *gpkt_stats_buffers;
/* PID of the APP to log the message */
static int gapp_pid = INVALID_PID;
+#ifndef CNSS_GENL
/* Utility function to send a netlink message to an application
* in user space
*/
@@ -223,6 +229,7 @@ static int wlan_send_sock_msg_to_app(tAniHdr *wmsg, int radio,
__func__, wmsg->type, pid);
return err;
}
+#endif
/**
* is_data_path_module() - To check for a Datapath module
@@ -559,6 +566,42 @@ static int pkt_stats_fill_headers(struct sk_buff *skb)
}
/**
+ * nl_srv_bcast_diag() - Wrapper to send bcast msgs to diag events mcast grp
+ * @skb: sk buffer pointer
+ *
+ * Sends the bcast message to diag events multicast group with generic nl socket
+ * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send.
+ *
+ * Return: zero on success, error code otherwise
+ */
+static int nl_srv_bcast_diag(struct sk_buff *skb)
+{
+#ifdef CNSS_GENL
+ return nl_srv_bcast(skb, CLD80211_MCGRP_DIAG_EVENTS, ANI_NL_MSG_PUMAC);
+#else
+ return nl_srv_bcast(skb);
+#endif
+}
+
+/**
+ * nl_srv_bcast_host_logs() - Wrapper to send bcast msgs to host logs mcast grp
+ * @skb: sk buffer pointer
+ *
+ * Sends the bcast message to host logs multicast group with generic nl socket
+ * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send.
+ *
+ * Return: zero on success, error code otherwise
+ */
+static int nl_srv_bcast_host_logs(struct sk_buff *skb)
+{
+#ifdef CNSS_GENL
+ return nl_srv_bcast(skb, CLD80211_MCGRP_HOST_LOGS, ANI_NL_MSG_LOG);
+#else
+ return nl_srv_bcast(skb);
+#endif
+}
+
+/**
* pktlog_send_per_pkt_stats_to_user() - This function is used to send the per
* packet statistics to the user
*
@@ -577,11 +620,11 @@ int pktlog_send_per_pkt_stats_to_user(void)
while (!list_empty(&gwlan_logging.pkt_stat_filled_list)
&& !gwlan_logging.exit) {
- skb_new = dev_alloc_skb(MAX_PKTSTATS_LENGTH);
+ skb_new = dev_alloc_skb(MAX_SKBMSG_LENGTH);
if (skb_new == NULL) {
if (!rate_limit) {
pr_err("%s: dev_alloc_skb() failed for msg size[%d] drop count = %u\n",
- __func__, MAX_LOGMSG_LENGTH,
+ __func__, MAX_SKBMSG_LENGTH,
gwlan_logging.drop_count);
}
rate_limit = 1;
@@ -602,7 +645,7 @@ int pktlog_send_per_pkt_stats_to_user(void)
free_old_skb = true;
goto err;
}
- ret = nl_srv_bcast(pstats_msg->skb);
+ ret = nl_srv_bcast_diag(pstats_msg->skb);
if (ret < 0) {
pr_info("%s: Send Failed %d drop_count = %u\n",
__func__, ret,
@@ -697,7 +740,7 @@ static int send_filled_buffers_to_user(void)
list_add_tail(&plog_msg->node, &gwlan_logging.free_list);
spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);
- ret = nl_srv_bcast(skb);
+ ret = nl_srv_bcast_host_logs(skb);
/* print every 64th drop count */
if (ret < 0 && (!(gwlan_logging.drop_count % 0x40))) {
pr_err("%s: Send Failed %d drop_count = %u\n",
@@ -858,6 +901,30 @@ static int wlan_logging_thread(void *Arg)
return 0;
}
+#ifdef CNSS_GENL
+/**
+ * register_logging_sock_handler() - Logging sock handler registration
+ *
+ * Dummy API to register the command handler for logger socket app.
+ *
+ * Return: None
+ */
+static void register_logging_sock_handler(void)
+{
+}
+
+/**
+ * unregister_logging_sock_handler() - Logging sock handler unregistration
+ *
+ * Dummy API to unregister the command handler for logger socket app.
+ *
+ * Return: None
+ */
+static void unregister_logging_sock_handler(void)
+{
+}
+#else
+
/*
* Process all the Netlink messages from Logger Socket app in user space
*/
@@ -924,6 +991,34 @@ static int wlan_logging_proc_sock_rx_msg(struct sk_buff *skb)
return ret;
}
+/**
+ * register_logging_sock_handler() - Logging sock handler registration
+ *
+ * API to register the command handler for logger socket app. Registers
+ * legacy handler
+ *
+ * Return: None
+ */
+static void register_logging_sock_handler(void)
+{
+ nl_srv_register(ANI_NL_MSG_LOG, wlan_logging_proc_sock_rx_msg);
+}
+
+/**
+ * unregister_logging_sock_handler() - Logging sock handler unregistration
+ *
+ * API to unregister the command handler for logger socket app. Unregisters
+ * legacy handler
+ *
+ * Return: None
+ */
+static void unregister_logging_sock_handler(void)
+{
+ nl_srv_unregister(ANI_NL_MSG_LOG, wlan_logging_proc_sock_rx_msg);
+}
+#endif
+
+
int wlan_logging_sock_activate_svc(int log_fe_to_console, int num_buf)
{
int i = 0, j, pkt_stats_size;
@@ -1011,8 +1106,7 @@ int wlan_logging_sock_activate_svc(int log_fe_to_console, int num_buf)
gwlan_logging.is_active = true;
gwlan_logging.is_flush_complete = false;
- nl_srv_register(ANI_NL_MSG_LOG, wlan_logging_proc_sock_rx_msg);
-
+ register_logging_sock_handler();
return 0;
err3:
@@ -1043,7 +1137,7 @@ int wlan_logging_sock_deactivate_svc(void)
if (!gplog_msg)
return 0;
- nl_srv_unregister(ANI_NL_MSG_LOG, wlan_logging_proc_sock_rx_msg);
+ unregister_logging_sock_handler();
clear_default_logtoapp_log_level();
gapp_pid = INVALID_PID;
diff --git a/core/utils/nlink/inc/wlan_nlink_srv.h b/core/utils/nlink/inc/wlan_nlink_srv.h
index b455b64d583f..4f76a4171d01 100644
--- a/core/utils/nlink/inc/wlan_nlink_srv.h
+++ b/core/utils/nlink/inc/wlan_nlink_srv.h
@@ -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.
*
@@ -54,7 +54,15 @@ void nl_srv_exit(void);
int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler);
int nl_srv_unregister(tWlanNlModTypes msg_type,
nl_srv_msg_callback msg_handler);
+
+#ifdef CNSS_GENL
+int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag,
+ int app_id, int mcgroup_id);
+int nl_srv_bcast(struct sk_buff *skb, int mcgroup_id, int app_id);
+#else
int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag);
int nl_srv_bcast(struct sk_buff *skb);
+#endif
+
int nl_srv_is_initialized(void);
#endif
diff --git a/core/utils/nlink/src/wlan_nlink_srv.c b/core/utils/nlink/src/wlan_nlink_srv.c
index cef164515339..b8b8e2aab114 100644
--- a/core/utils/nlink/src/wlan_nlink_srv.c
+++ b/core/utils/nlink/src/wlan_nlink_srv.c
@@ -51,6 +51,13 @@
#include <wlan_nlink_srv.h>
#include <qdf_trace.h>
+#ifdef CNSS_GENL
+#include <qdf_mem.h>
+#include <wlan_nlink_common.h>
+#include <net/genetlink.h>
+#include <net/cnss_nl.h>
+#endif
+
#if defined(CONFIG_CNSS_LOGGER)
#include <net/cnss_logger.h>
@@ -344,6 +351,195 @@ int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
return retcode;
}
+#ifdef CNSS_GENL
+/**
+ * nl80211hdr_put() - API to fill genlmsg header
+ * @skb: Sk buffer
+ * @portid: Port ID
+ * @seq: Sequence number
+ * @flags: Flags
+ * @cmd: Command id
+ *
+ * API to fill genl message header for brodcast events to user space
+ *
+ * Return: Pointer to user specific header/payload
+ */
+static inline void *nl80211hdr_put(struct sk_buff *skb, uint32_t portid,
+ uint32_t seq, int flags, uint8_t cmd)
+{
+ struct genl_family *cld80211_fam = cld80211_get_genl_family();
+
+ return genlmsg_put(skb, portid, seq, cld80211_fam, flags, cmd);
+}
+
+/**
+ * cld80211_fill_data() - API to fill payload to nl message
+ * @msg: Sk buffer
+ * @portid: Port ID
+ * @seq: Sequence number
+ * @flags: Flags
+ * @cmd: Command ID
+ * @buf: data buffer/payload to be filled
+ * @len: length of the payload ie. @buf
+ *
+ * API to fill the payload/data of the nl message to be sent
+ *
+ * Return: zero on success
+ */
+static int cld80211_fill_data(struct sk_buff *msg, uint32_t portid,
+ uint32_t seq, int flags, uint8_t cmd,
+ uint8_t *buf, int len)
+{
+ void *hdr;
+ struct nlattr *nest;
+
+ hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
+ if (!hdr) {
+ QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
+ "nl80211 hdr put failed");
+ return -EPERM;
+ }
+
+ nest = nla_nest_start(msg, CLD80211_ATTR_VENDOR_DATA);
+ if (!nest) {
+ QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
+ "nla_nest_start failed");
+ goto nla_put_failure;
+ }
+
+ if (nla_put(msg, CLD80211_ATTR_DATA, len, buf)) {
+ QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
+ "nla_put failed");
+ goto nla_put_failure;
+ }
+
+ nla_nest_end(msg, nest);
+ genlmsg_end(msg, hdr);
+
+ return 0;
+nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ return -EPERM;
+}
+
+/**
+ * send_msg_to_cld80211() - API to send message to user space Application
+ * @mcgroup_id: Multicast group ID
+ * @pid: Port ID
+ * @app_id: Application ID
+ * @buf: Data/payload buffer to be sent
+ * @len: Length of the data ie. @buf
+ *
+ * API to send the nl message to user space application.
+ *
+ * Return: zero on success
+ */
+static int send_msg_to_cld80211(int mcgroup_id, int pid, int app_id,
+ uint8_t *buf, int len)
+{
+ struct sk_buff *msg;
+ struct genl_family *cld80211_fam = cld80211_get_genl_family();
+ int status;
+ int flags = GFP_KERNEL;
+
+ if (in_interrupt() || irqs_disabled() || in_atomic())
+ flags = GFP_ATOMIC;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, flags);
+ if (!msg) {
+ QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
+ "nlmsg malloc fails");
+ return -EPERM;
+ }
+
+ status = cld80211_fill_data(msg, pid, 0, 0, app_id, buf, len);
+ if (status) {
+ nlmsg_free(msg);
+ return -EPERM;
+ }
+
+ genlmsg_multicast_netns(cld80211_fam, &init_net, msg, 0,
+ mcgroup_id, flags);
+ return 0;
+}
+
+/**
+ * nl_srv_bcast() - wrapper function to do broadcast events to user space apps
+ * @skb: the socket buffer to send
+ * @mcgroup_id: multicast group id
+ * @app_id: application id
+ *
+ * This function is common wrapper to send broadcast events to different
+ * user space applications.
+ *
+ * return: none
+ */
+int nl_srv_bcast(struct sk_buff *skb, int mcgroup_id, int app_id)
+{
+ struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data;
+ void *msg = NLMSG_DATA(nlh);
+ uint32_t msg_len = nlmsg_len(nlh);
+ uint8_t *tempbuf;
+ int status;
+
+ tempbuf = (uint8_t *)qdf_mem_malloc(msg_len);
+ qdf_mem_copy(tempbuf, msg, msg_len);
+ status = send_msg_to_cld80211(mcgroup_id, 0, app_id, tempbuf, msg_len);
+ if (status) {
+ QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
+ "send msg to cld80211 fails for app id %d", app_id);
+ dev_kfree_skb(skb);
+ qdf_mem_free(tempbuf);
+ return -EPERM;
+ }
+
+ dev_kfree_skb(skb);
+ qdf_mem_free(tempbuf);
+ return 0;
+}
+
+/**
+ * nl_srv_ucast() - wrapper function to do unicast events to user space apps
+ * @skb: the socket buffer to send
+ * @dst_pid: destination process IF
+ * @flag: flags
+ * @app_id: application id
+ * @mcgroup_id: Multicast group ID
+ *
+ * This function is common wrapper to send unicast events to different
+ * user space applications. This internally used broadcast API with multicast
+ * group mcgrp_id. This wrapper serves as a common API in both
+ * new generic netlink infra and legacy implementation.
+ *
+ * return: zero on success, error code otherwise
+ */
+int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag,
+ int app_id, int mcgroup_id)
+{
+ struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data;
+ void *msg = NLMSG_DATA(nlh);
+ uint32_t msg_len = nlmsg_len(nlh);
+ uint8_t *tempbuf;
+ int status;
+
+ tempbuf = (uint8_t *)qdf_mem_malloc(msg_len);
+ qdf_mem_copy(tempbuf, msg, msg_len);
+ status = send_msg_to_cld80211(mcgroup_id, dst_pid, app_id,
+ tempbuf, msg_len);
+ if (status) {
+ QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
+ "send msg to cld80211 fails for app id %d", app_id);
+ dev_kfree_skb(skb);
+ qdf_mem_free(tempbuf);
+ return -EPERM;
+ }
+
+ dev_kfree_skb(skb);
+ qdf_mem_free(tempbuf);
+ return 0;
+}
+#else
+
/*
* Unicast the message to the process in user space identfied
* by the dst-pid
@@ -391,6 +587,7 @@ int nl_srv_bcast(struct sk_buff *skb)
}
return err;
}
+#endif
/*
* Processes the Netlink socket input queue.
diff --git a/core/utils/ptt/inc/wlan_ptt_sock_svc.h b/core/utils/ptt/inc/wlan_ptt_sock_svc.h
index 44587480e7ac..c75f7e0cb9d4 100644
--- a/core/utils/ptt/inc/wlan_ptt_sock_svc.h
+++ b/core/utils/ptt/inc/wlan_ptt_sock_svc.h
@@ -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.
*
@@ -119,6 +119,19 @@ typedef struct sAniAppRegReq {
tAniNlModTypes type; /* module id */
int pid; /* process id */
} tAniNlAppRegReq;
+
+/**
+ * struct sptt_app_reg_req - PTT register request structure
+ * @radio: Radio ID
+ * @wmsg: ANI header
+ *
+ * payload structure received as nl data from PTT app/user space
+ */
+typedef struct sptt_app_reg_req {
+ int radio;
+ tAniHdr wmsg;
+} ptt_app_reg_req;
+
typedef struct sAniNlAppRegRsp {
tAniHdr wniHdr; /* Generic WNI msg header */
tAniNlAppRegReq regReq; /* The original request msg */
diff --git a/core/utils/ptt/src/wlan_ptt_sock_svc.c b/core/utils/ptt/src/wlan_ptt_sock_svc.c
index 4efb50ffbc47..39a7afaf4342 100644
--- a/core/utils/ptt/src/wlan_ptt_sock_svc.c
+++ b/core/utils/ptt/src/wlan_ptt_sock_svc.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.
*
@@ -39,6 +39,14 @@
#include <qdf_types.h>
#include <qdf_trace.h>
+#ifdef CNSS_GENL
+#include <net/cnss_nl.h>
+#else
+
+/** ptt Process ID */
+static int32_t ptt_pid = INVALID_PID;
+#endif
+
#define PTT_SOCK_DEBUG
#ifdef PTT_SOCK_DEBUG
#define PTT_TRACE(level, args ...) QDF_TRACE(QDF_MODULE_ID_QDF, level, ## args)
@@ -46,9 +54,6 @@
#define PTT_TRACE(level, args ...)
#endif
-/** ptt Process ID */
-static int32_t ptt_pid = INVALID_PID;
-
#ifdef PTT_SOCK_DEBUG_VERBOSE
/* Utility function to perform a hex dump */
static void ptt_sock_dump_buf(const unsigned char *pbuf, int cnt)
@@ -67,6 +72,45 @@ static void ptt_sock_dump_buf(const unsigned char *pbuf, int cnt)
#endif
/**
+ * nl_srv_ucast_ptt() - Wrapper function to send ucast msgs to PTT
+ * @skb: sk buffer pointer
+ * @dst_pid: Destination PID
+ * @flag: flags
+ *
+ * Sends the ucast message to PTT with generic nl socket if CNSS_GENL
+ * is enabled. Else, use the legacy netlink socket to send.
+ *
+ * Return: zero on success, error code otherwise
+ */
+static int nl_srv_ucast_ptt(struct sk_buff *skb, int dst_pid, int flag)
+{
+#ifdef CNSS_GENL
+ return nl_srv_ucast(skb, dst_pid, flag, ANI_NL_MSG_PUMAC,
+ CLD80211_MCGRP_DIAG_EVENTS);
+#else
+ return nl_srv_ucast(skb, dst_pid, flag);
+#endif
+}
+
+/**
+ * nl_srv_bcast_ptt() - Wrapper function to send bcast msgs to DIAG mcast group
+ * @skb: sk buffer pointer
+ *
+ * Sends the bcast message to DIAG multicast group with generic nl socket
+ * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send.
+ *
+ * Return: zero on success, error code otherwise
+ */
+static int nl_srv_bcast_ptt(struct sk_buff *skb)
+{
+#ifdef CNSS_GENL
+ return nl_srv_bcast(skb, CLD80211_MCGRP_DIAG_EVENTS, ANI_NL_MSG_PUMAC);
+#else
+ return nl_srv_bcast(skb);
+#endif
+}
+
+/**
* ptt_sock_send_msg_to_app() - Send nl message to user space
* wmsg: Message header
* radio: Unit number of the radio
@@ -121,9 +165,9 @@ int ptt_sock_send_msg_to_app(tAniHdr *wmsg, int radio, int src_mod, int pid)
#endif
if (pid != INVALID_PID)
- err = nl_srv_ucast(skb, pid, MSG_DONTWAIT);
+ err = nl_srv_ucast_ptt(skb, pid, MSG_DONTWAIT);
else
- err = nl_srv_bcast(skb);
+ err = nl_srv_bcast_ptt(skb);
if (err)
PTT_TRACE(QDF_TRACE_LEVEL_INFO,
@@ -132,6 +176,7 @@ int ptt_sock_send_msg_to_app(tAniHdr *wmsg, int radio, int src_mod, int pid)
return err;
}
+#ifndef CNSS_GENL
/*
* Process tregisteration request and send registration response messages
* to the PTT Socket App in user space
@@ -204,6 +249,73 @@ static int ptt_sock_rx_nlink_msg(struct sk_buff *skb)
}
return 0;
}
+#endif
+
+#ifdef CNSS_GENL
+/**
+ * ptt_cmd_handler() - Handler function for PTT commands
+ * @data: Data to be parsed
+ * @data_len: Length of the data received
+ * @ctx: Registered context reference
+ * @pid: Process id of the user space application
+ *
+ * This function handles the command from PTT user space application
+ *
+ * Return: None
+ */
+static void ptt_cmd_handler(const void *data, int data_len, void *ctx, int pid)
+{
+ ptt_app_reg_req *payload;
+ struct nlattr *tb[CLD80211_ATTR_MAX + 1];
+
+ if (nla_parse(tb, CLD80211_ATTR_MAX, data, data_len, NULL)) {
+ PTT_TRACE(QDF_TRACE_LEVEL_ERROR, "Invalid ATTR");
+ return;
+ }
+
+ if (!tb[CLD80211_ATTR_DATA]) {
+ PTT_TRACE(QDF_TRACE_LEVEL_ERROR, "attr ATTR_DATA failed");
+ return;
+ }
+
+ payload = (ptt_app_reg_req *)(nla_data(tb[CLD80211_ATTR_DATA]));
+ switch (payload->wmsg.type) {
+ case ANI_MSG_APP_REG_REQ:
+ ptt_sock_send_msg_to_app(&payload->wmsg, payload->radio,
+ ANI_NL_MSG_PUMAC, pid);
+ break;
+ default:
+ PTT_TRACE(QDF_TRACE_LEVEL_ERROR, "Unknown msg type %d",
+ payload->wmsg.type);
+ break;
+ }
+}
+
+/**
+ * ptt_sock_activate_svc() - API to register PTT/PUMAC command handler
+ *
+ * API to register the PTT/PUMAC command handlers. Argument @pAdapter
+ * is sent for prototype compatibility between new genl and legacy
+ * implementation
+ *
+ * Return: 0
+ */
+int ptt_sock_activate_svc(void)
+{
+ register_cld_cmd_cb(ANI_NL_MSG_PUMAC, ptt_cmd_handler, NULL);
+ register_cld_cmd_cb(ANI_NL_MSG_PTT, ptt_cmd_handler, NULL);
+ return 0;
+}
+
+/**
+ * ptt_sock_deactivate_svc() - Dummy API to deactivate PTT service
+ *
+ * Return: Void
+ */
+void ptt_sock_deactivate_svc(void)
+{
+}
+#else
/**
* ptt_sock_activate_svc() - activate PTT service
@@ -227,5 +339,5 @@ void ptt_sock_deactivate_svc(void)
{
ptt_pid = INVALID_PID;
}
-
+#endif
#endif /* PTT_SOCK_SVC_ENABLE */