123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755 |
- /*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
- *
- * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
- *
- *
- * Permission to use, copy, modify, and/or distribute this software for
- * any purpose with or without fee is hereby granted, provided that the
- * above copyright notice and this permission notice appear in all
- * copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
- * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
- /*
- * This file was originally distributed by Qualcomm Atheros, Inc.
- * under proprietary terms before Copyright ownership was assigned
- * to the Linux Foundation.
- */
- /******************************************************************************
- * wlan_nlink_srv.c
- *
- * This file contains the definitions specific to the wlan_nlink_srv
- *
- ******************************************************************************/
- /*
- * If MULTI_IF_NAME is not defined, then this is the primary instance of the
- * driver and the diagnostics netlink socket will be available. If
- * MULTI_IF_NAME is defined then this is not the primary instance of the driver
- * and the diagnotics netlink socket will not be available since this
- * diagnostics netlink socket can only be exposed by one instance of the driver.
- */
- #ifndef MULTI_IF_NAME
- #include <linux/version.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/netdevice.h>
- #include <linux/netlink.h>
- #include <linux/skbuff.h>
- #include <net/sock.h>
- #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>
- static int radio_idx = -EINVAL;
- static void *wiphy_ptr;
- static bool logger_initialized;
- /**
- * nl_srv_init() - wrapper function to register to cnss_logger
- * @wiphy: the pointer to the wiphy structure
- *
- * The netlink socket is no longer initialized in the driver itself, instead
- * will be initialized in the cnss_logger module, the driver should register
- * itself to cnss_logger module to get the radio_index for all the netlink
- * operation. (cfg80211 vendor command is using different netlink socket).
- *
- * The cnss_logger_device_register() use to register the driver with the
- * wiphy structure and the module name (debug purpose) and then return the
- * radio_index depending on the availibility.
- *
- * Return: radio index for success and -EINVAL for failure
- */
- int nl_srv_init(void *wiphy)
- {
- if (logger_initialized)
- goto initialized;
- wiphy_ptr = wiphy;
- radio_idx = cnss_logger_device_register(wiphy, THIS_MODULE->name);
- QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
- "%s: radio_index: %d, wiphy_ptr: %p",
- __func__, radio_idx, wiphy_ptr);
- if (radio_idx >= 0)
- logger_initialized = true;
- initialized:
- return radio_idx;
- }
- /**
- * nl_srv_exit() - wrapper function to unregister from cnss_logger
- *
- * The cnss_logger_device_unregister() use to unregister the driver with
- * the radio_index assigned and wiphy structure from cnss_logger.
- *
- * Return: None
- */
- void nl_srv_exit(void)
- {
- if (logger_initialized) {
- cnss_logger_device_unregister(radio_idx, wiphy_ptr);
- radio_idx = -EINVAL;
- wiphy_ptr = NULL;
- logger_initialized = false;
- }
- }
- /**
- * nl_srv_ucast() - wrapper function to do unicast tx through cnss_logger
- * @skb: the socket buffer to send
- * @dst_pid: the port id
- * @flag: the blocking or nonblocking flag
- *
- * The nl_srv_is_initialized() is used to do sanity check if the netlink
- * service is ready, e.g if the radio_index is assigned properly, if not
- * the driver should take the responsibility to free the skb.
- *
- * The cnss_logger_nl_ucast() use the same parameters to send the socket
- * buffers.
- *
- * Return: the error of the transmission status
- */
- int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag)
- {
- int err = -EINVAL;
- /* sender's pid */
- #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
- NETLINK_CB(skb).pid = 0;
- #else
- NETLINK_CB(skb).portid = 0;
- #endif
- /* not multicast */
- NETLINK_CB(skb).dst_group = 0;
- if (nl_srv_is_initialized() == 0) {
- err = cnss_logger_nl_ucast(skb, dst_pid, flag);
- if (err < 0) {
- QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
- "NLINK: netlink_unicast to pid[%d] failed, ret[%d]",
- dst_pid, err);
- dev_kfree_skb(skb);
- }
- }
- else
- dev_kfree_skb(skb);
- return err;
- }
- /**
- * nl_srv_bcast() - wrapper function to do broadcast tx through cnss_logger
- * @skb: the socket buffer to send
- *
- * The cnss_logger_nl_bcast() is used to transmit the socket buffer.
- *
- * Return: status of transmission
- */
- int nl_srv_bcast(struct sk_buff *skb)
- {
- int err = -EINVAL;
- int flags = GFP_KERNEL;
- if (in_interrupt() || irqs_disabled() || in_atomic())
- flags = GFP_ATOMIC;
- /* sender's pid */
- #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
- NETLINK_CB(skb).pid = 0;
- #else
- NETLINK_CB(skb).portid = 0;
- #endif
- /* destination group */
- NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID;
- if (nl_srv_is_initialized() == 0) {
- err = cnss_logger_nl_bcast(skb, WLAN_NLINK_MCAST_GRP_ID, flags);
- if ((err < 0) && (err != -ESRCH)) {
- QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
- "NLINK: netlink_broadcast failed err = %d",
- err);
- dev_kfree_skb(skb);
- }
- }
- else
- dev_kfree_skb(skb);
- return err;
- }
- /**
- * nl_srv_unregister() - wrapper function to unregister event to cnss_logger
- * @msg_type: the message to unregister
- * @msg_handler: the message handler
- *
- * The cnss_logger_event_unregister() is used to unregister the message and
- * message handler.
- *
- * Return: 0 if successfully unregister, otherwise proper error code
- */
- int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
- {
- int ret = -EINVAL;
- if (nl_srv_is_initialized() != 0)
- return ret;
- if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
- msg_handler != NULL) {
- ret = cnss_logger_event_unregister(radio_idx, msg_type,
- msg_handler);
- } else {
- QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
- "NLINK: nl_srv_unregister failed for msg_type %d",
- msg_type);
- ret = -EINVAL;
- }
- return ret;
- }
- /**
- * nl_srv_register() - wrapper function to register event to cnss_logger
- * @msg_type: the message to register
- * @msg_handler: the message handler
- *
- * The cnss_logger_event_register() is used to register the message and
- * message handler.
- *
- * Return: 0 if successfully register, otherwise proper error code
- */
- int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
- {
- int ret = -EINVAL;
- if (nl_srv_is_initialized() != 0)
- return ret;
- if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
- msg_handler != NULL) {
- ret = cnss_logger_event_register(radio_idx, msg_type,
- msg_handler);
- } else {
- QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
- "NLINK: nl_srv_register failed for msg_type %d",
- msg_type);
- ret = -EINVAL;
- }
- return ret;
- }
- /**
- * nl_srv_is_initialized() - check if netlink service is initialized
- *
- * Return: 0 if it is initialized, otherwise error code
- */
- inline int nl_srv_is_initialized(void)
- {
- if (logger_initialized)
- return 0;
- else
- return -EPERM;
- }
- #else
- /* Global variables */
- static DEFINE_MUTEX(nl_srv_sem);
- static struct sock *nl_srv_sock;
- static nl_srv_msg_callback nl_srv_msg_handler[NLINK_MAX_CALLBACKS];
- /* Forward declaration */
- static void nl_srv_rcv(struct sk_buff *sk);
- static void nl_srv_rcv_skb(struct sk_buff *skb);
- static void nl_srv_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh);
- /*
- * Initialize the netlink service.
- * Netlink service is usable after this.
- */
- int nl_srv_init(void *wiphy)
- {
- int retcode = 0;
- struct netlink_kernel_cfg cfg = {
- .groups = WLAN_NLINK_MCAST_GRP_ID,
- .input = nl_srv_rcv
- };
- nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_PROTO_FAMILY,
- &cfg);
- if (nl_srv_sock != NULL) {
- memset(nl_srv_msg_handler, 0, sizeof(nl_srv_msg_handler));
- } else {
- QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
- "NLINK: netlink_kernel_create failed");
- retcode = -ECONNREFUSED;
- }
- return retcode;
- }
- /*
- * Deinit the netlink service.
- * Netlink service is unusable after this.
- */
- void nl_srv_exit(void)
- {
- if (nl_srv_is_initialized() == 0)
- netlink_kernel_release(nl_srv_sock);
- nl_srv_sock = NULL;
- }
- /*
- * Register a message handler for a specified module.
- * Each module (e.g. WLAN_NL_MSG_BTC )will register a
- * handler to handle messages addressed to it.
- */
- int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
- {
- int retcode = 0;
- if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
- msg_handler != NULL) {
- nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] = msg_handler;
- } else {
- QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
- "NLINK: nl_srv_register failed for msg_type %d",
- msg_type);
- retcode = -EINVAL;
- }
- return retcode;
- }
- /*
- * Unregister the message handler for a specified module.
- */
- int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
- {
- int retcode = 0;
- if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
- (nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] == msg_handler)) {
- nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] = NULL;
- } else {
- QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
- "NLINK: nl_srv_unregister failed for msg_type %d",
- msg_type);
- retcode = -EINVAL;
- }
- 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
- */
- int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag)
- {
- int err = -EINVAL;
- NETLINK_CB(skb).portid = 0; /* sender's pid */
- NETLINK_CB(skb).dst_group = 0; /* not multicast */
- if (nl_srv_sock) {
- err = netlink_unicast(nl_srv_sock, skb, dst_pid, flag);
- if (err < 0) {
- QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
- "NLINK: netlink_unicast to pid[%d] failed, ret[%d]",
- dst_pid, err);
- dev_kfree_skb(skb);
- }
- } else
- dev_kfree_skb(skb);
- return err;
- }
- /*
- * Broadcast the message. Broadcast will return an error if
- * there are no listeners
- */
- int nl_srv_bcast(struct sk_buff *skb)
- {
- int err = -EINVAL;
- int flags = GFP_KERNEL;
- if (in_interrupt() || irqs_disabled() || in_atomic())
- flags = GFP_ATOMIC;
- NETLINK_CB(skb).portid = 0; /* sender's pid */
- NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID; /* destination group */
- if (nl_srv_sock) {
- err = netlink_broadcast(nl_srv_sock, skb, 0,
- WLAN_NLINK_MCAST_GRP_ID, flags);
- if ((err < 0) && (err != -ESRCH)) {
- QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
- "NLINK: netlink_broadcast failed err = %d",
- err);
- dev_kfree_skb(skb);
- }
- } else
- dev_kfree_skb(skb);
- return err;
- }
- #endif
- /*
- * Processes the Netlink socket input queue.
- * Dequeue skb's from the socket input queue and process
- * all the netlink messages in that skb, before moving
- * to the next skb.
- */
- static void nl_srv_rcv(struct sk_buff *sk)
- {
- mutex_lock(&nl_srv_sem);
- nl_srv_rcv_skb(sk);
- mutex_unlock(&nl_srv_sem);
- }
- /*
- * Each skb could contain multiple Netlink messages. Process all the
- * messages in one skb and discard malformed skb's silently.
- */
- static void nl_srv_rcv_skb(struct sk_buff *skb)
- {
- struct nlmsghdr *nlh;
- while (skb->len >= NLMSG_SPACE(0)) {
- u32 rlen;
- nlh = (struct nlmsghdr *)skb->data;
- if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) {
- QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
- "NLINK: Invalid "
- "Netlink message: skb[%p], len[%d], nlhdr[%p], nlmsg_len[%d]",
- skb, skb->len, nlh, nlh->nlmsg_len);
- return;
- }
- rlen = NLMSG_ALIGN(nlh->nlmsg_len);
- if (rlen > skb->len)
- rlen = skb->len;
- nl_srv_rcv_msg(skb, nlh);
- skb_pull(skb, rlen);
- }
- }
- /*
- * Process a netlink message.
- * Each netlink message will have a message of type tAniMsgHdr inside.
- */
- static void nl_srv_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
- {
- int type;
- /* Only requests are handled by kernel now */
- if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) {
- QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
- "NLINK: Received Invalid NL Req type [%x]",
- nlh->nlmsg_flags);
- return;
- }
- type = nlh->nlmsg_type;
- /* Unknown message */
- if (type < WLAN_NL_MSG_BASE || type >= WLAN_NL_MSG_MAX) {
- QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
- "NLINK: Received Invalid NL Msg type [%x]", type);
- return;
- }
- /*
- * All the messages must at least carry the tAniMsgHdr
- * Drop any message with invalid length
- */
- if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(tAniMsgHdr))) {
- QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
- "NLINK: Received NL Msg with invalid len[%x]",
- nlh->nlmsg_len);
- return;
- }
- /* turn type into dispatch table offset */
- type -= WLAN_NL_MSG_BASE;
- /* dispatch to handler */
- if (nl_srv_msg_handler[type] != NULL) {
- (nl_srv_msg_handler[type])(skb);
- } else {
- QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
- "NLINK: No handler for Netlink Msg [0x%X]", type);
- }
- }
- /**
- * nl_srv_is_initialized() - This function is used check if the netlink
- * service is initialized
- *
- * This function is used check if the netlink service is initialized
- *
- * Return: Return -EPERM if the service is not initialized
- *
- */
- int nl_srv_is_initialized(void)
- {
- if (nl_srv_sock)
- return 0;
- return -EPERM;
- }
- #endif
- #else /* ifndef MULTI_IF_NAME */
- #include <wlan_nlink_srv.h>
- int nl_srv_init(void *wiphy)
- {
- return 0;
- }
- void nl_srv_exit(void)
- {
- }
- int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
- {
- return 0;
- }
- int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
- {
- return 0;
- }
- int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag)
- {
- return 0;
- }
- int nl_srv_bcast(struct sk_buff *skb)
- {
- return 0;
- }
- int nl_srv_is_initialized(void)
- {
- return 0;
- }
- #endif
|