qcacmn: 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: Ia833249c1f312415e38563d90214979cea3d9f0e
CRs-Fixed: 2015931
This commit is contained in:
Selvaraj, Sridhar
2017-03-07 16:59:51 +05:30
committed by Sandeep Puligilla
parent ca0e169743
commit 7c6b935c64
6 changed files with 555 additions and 40 deletions

View File

@@ -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
@@ -1597,6 +1601,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
@@ -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,93 @@ 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]));
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 +4213,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,27 +4223,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]));
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;
}
/**---------------------------------------------------------------------------
@@ -4162,6 +4252,7 @@ int cnss_diag_activate_service(void)
}
return 0;
}
#endif
static A_BOOL
dbglog_wow_print_handler(A_UINT32 mod_id,

View File

@@ -51,6 +51,10 @@
#include "ol_txrx_api.h"
#include "pktlog_ac.h"
#ifdef CNSS_GENL
#include <net/cnss_nl.h>
#endif
#define MAX_NUM_PKT_LOG 32
/**
@@ -85,7 +89,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
@@ -179,6 +184,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
*/
@@ -230,6 +236,7 @@ static int wlan_send_sock_msg_to_app(tAniHdr *wmsg, int radio,
__func__, wmsg->type, pid);
return err;
}
#endif
/* Need to call this with spin_lock acquired */
static int wlan_queue_logmsg_for_app(void)
@@ -523,6 +530,42 @@ static int pkt_stats_fill_headers(struct sk_buff *skb)
return 0;
}
/**
* 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
@@ -542,11 +585,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;
@@ -567,7 +610,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,
@@ -662,7 +705,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",
@@ -825,6 +868,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
*/
@@ -875,6 +942,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;
@@ -962,8 +1057,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:
@@ -994,7 +1088,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();
gapp_pid = INVALID_PID;
#ifdef CONFIG_MCL

View File

@@ -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

View File

@@ -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>
@@ -358,6 +365,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
@@ -410,6 +606,7 @@ int nl_srv_bcast(struct sk_buff *skb)
dev_kfree_skb(skb);
return err;
}
#endif
/*
* Processes the Netlink socket input queue.

View File

@@ -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 */

View File

@@ -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)
@@ -66,6 +71,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
@@ -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 */