wlan_nlink_srv.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
  1. /*
  2. * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for
  5. * any purpose with or without fee is hereby granted, provided that the
  6. * above copyright notice and this permission notice appear in all
  7. * copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  10. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  11. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  12. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  13. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  14. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  15. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  16. * PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. /******************************************************************************
  19. * wlan_nlink_srv.c
  20. *
  21. * This file contains the definitions specific to the wlan_nlink_srv
  22. *
  23. ******************************************************************************/
  24. #include <linux/version.h>
  25. #include <linux/kernel.h>
  26. #include <linux/module.h>
  27. #include <linux/init.h>
  28. #include <linux/netdevice.h>
  29. #include <linux/netlink.h>
  30. #include <linux/skbuff.h>
  31. #include <net/sock.h>
  32. #include <wlan_nlink_srv.h>
  33. #include <qdf_trace.h>
  34. #include <qdf_module.h>
  35. #define WLAN_CLD80211_MAX_SIZE (SKB_WITH_OVERHEAD(8192UL) - NLMSG_HDRLEN)
  36. #if defined(CONFIG_CNSS_LOGGER)
  37. #include <net/cnss_logger.h>
  38. static int radio_idx = -EINVAL;
  39. static void *wiphy_ptr;
  40. static bool logger_initialized;
  41. /**
  42. * nl_srv_init() - wrapper function to register to cnss_logger
  43. * @wiphy: the pointer to the wiphy structure
  44. * @proto: the host log netlink protocol
  45. *
  46. * The netlink socket is no longer initialized in the driver itself, instead
  47. * will be initialized in the cnss_logger module, the driver should register
  48. * itself to cnss_logger module to get the radio_index for all the netlink
  49. * operation. (cfg80211 vendor command is using different netlink socket).
  50. *
  51. * The cnss_logger_device_register() use to register the driver with the
  52. * wiphy structure and the module name (debug purpose) and then return the
  53. * radio_index depending on the availibility.
  54. *
  55. * Return: radio index for success and -EINVAL for failure
  56. */
  57. int nl_srv_init(void *wiphy, int proto)
  58. {
  59. if (logger_initialized)
  60. goto initialized;
  61. wiphy_ptr = wiphy;
  62. radio_idx = cnss_logger_device_register(wiphy, THIS_MODULE->name);
  63. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  64. "%s: radio_index: %d, wiphy_ptr: %pK",
  65. __func__, radio_idx, wiphy_ptr);
  66. if (radio_idx >= 0)
  67. logger_initialized = true;
  68. initialized:
  69. return radio_idx;
  70. }
  71. /**
  72. * nl_srv_exit() - wrapper function to unregister from cnss_logger
  73. *
  74. * The cnss_logger_device_unregister() use to unregister the driver with
  75. * the radio_index assigned and wiphy structure from cnss_logger.
  76. *
  77. * Return: None
  78. */
  79. void nl_srv_exit(void)
  80. {
  81. if (logger_initialized) {
  82. cnss_logger_device_unregister(radio_idx, wiphy_ptr);
  83. radio_idx = -EINVAL;
  84. wiphy_ptr = NULL;
  85. logger_initialized = false;
  86. }
  87. }
  88. /**
  89. * nl_srv_ucast() - wrapper function to do unicast tx through cnss_logger
  90. * @skb: the socket buffer to send
  91. * @dst_pid: the port id
  92. * @flag: the blocking or nonblocking flag
  93. *
  94. * The nl_srv_is_initialized() is used to do sanity check if the netlink
  95. * service is ready, e.g if the radio_index is assigned properly, if not
  96. * the driver should take the responsibility to free the skb.
  97. *
  98. * The cnss_logger_nl_ucast() use the same parameters to send the socket
  99. * buffers.
  100. *
  101. * Return: the error of the transmission status
  102. */
  103. int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag)
  104. {
  105. int err = -EINVAL;
  106. /* sender's pid */
  107. #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
  108. NETLINK_CB(skb).pid = 0;
  109. #else
  110. NETLINK_CB(skb).portid = 0;
  111. #endif
  112. /* not multicast */
  113. NETLINK_CB(skb).dst_group = 0;
  114. if (nl_srv_is_initialized() == 0) {
  115. err = cnss_logger_nl_ucast(skb, dst_pid, flag);
  116. if (err < 0)
  117. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
  118. "NLINK: netlink_unicast to pid[%d] failed, ret[%d]",
  119. dst_pid, err);
  120. } else {
  121. dev_kfree_skb(skb);
  122. }
  123. return err;
  124. }
  125. /**
  126. * nl_srv_bcast() - wrapper function to do broadcast tx through cnss_logger
  127. * @skb: the socket buffer to send
  128. *
  129. * The cnss_logger_nl_bcast() is used to transmit the socket buffer.
  130. *
  131. * Return: status of transmission
  132. */
  133. int nl_srv_bcast(struct sk_buff *skb)
  134. {
  135. int err = -EINVAL;
  136. int flags = GFP_KERNEL;
  137. if (in_interrupt() || irqs_disabled() || in_atomic())
  138. flags = GFP_ATOMIC;
  139. /* sender's pid */
  140. #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
  141. NETLINK_CB(skb).pid = 0;
  142. #else
  143. NETLINK_CB(skb).portid = 0;
  144. #endif
  145. /* destination group */
  146. NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID;
  147. if (nl_srv_is_initialized() == 0) {
  148. err = cnss_logger_nl_bcast(skb, WLAN_NLINK_MCAST_GRP_ID, flags);
  149. if ((err < 0) && (err != -ESRCH)) {
  150. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
  151. "NLINK: netlink_broadcast failed err = %d",
  152. err);
  153. dev_kfree_skb(skb);
  154. }
  155. }
  156. else
  157. dev_kfree_skb(skb);
  158. return err;
  159. }
  160. qdf_export_symbol(nl_srv_bcast);
  161. /**
  162. * nl_srv_unregister() - wrapper function to unregister event to cnss_logger
  163. * @msg_type: the message to unregister
  164. * @msg_handler: the message handler
  165. *
  166. * The cnss_logger_event_unregister() is used to unregister the message and
  167. * message handler.
  168. *
  169. * Return: 0 if successfully unregister, otherwise proper error code
  170. */
  171. int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
  172. {
  173. int ret = -EINVAL;
  174. if (nl_srv_is_initialized() != 0)
  175. return ret;
  176. if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
  177. msg_handler) {
  178. ret = cnss_logger_event_unregister(radio_idx, msg_type,
  179. msg_handler);
  180. } else {
  181. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  182. "NLINK: nl_srv_unregister failed for msg_type %d",
  183. msg_type);
  184. ret = -EINVAL;
  185. }
  186. return ret;
  187. }
  188. /**
  189. * nl_srv_register() - wrapper function to register event to cnss_logger
  190. * @msg_type: the message to register
  191. * @msg_handler: the message handler
  192. *
  193. * The cnss_logger_event_register() is used to register the message and
  194. * message handler.
  195. *
  196. * Return: 0 if successfully register, otherwise proper error code
  197. */
  198. int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
  199. {
  200. int ret = -EINVAL;
  201. if (nl_srv_is_initialized() != 0)
  202. return ret;
  203. if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
  204. msg_handler) {
  205. ret = cnss_logger_event_register(radio_idx, msg_type,
  206. msg_handler);
  207. } else {
  208. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  209. "NLINK: nl_srv_register failed for msg_type %d",
  210. msg_type);
  211. ret = -EINVAL;
  212. }
  213. return ret;
  214. }
  215. /**
  216. * nl_srv_is_initialized() - check if netlink service is initialized
  217. *
  218. * Return: 0 if it is initialized, otherwise error code
  219. */
  220. inline int nl_srv_is_initialized(void)
  221. {
  222. if (logger_initialized)
  223. return 0;
  224. else
  225. return -EPERM;
  226. }
  227. qdf_export_symbol(nl_srv_is_initialized);
  228. /*
  229. * If MULTI_IF_NAME is not defined, then this is the primary instance of the
  230. * driver and the diagnostics netlink socket will be available. If
  231. * MULTI_IF_NAME is defined then this is not the primary instance of the driver
  232. * and the diagnotics netlink socket will not be available since this
  233. * diagnostics netlink socket can only be exposed by one instance of the driver.
  234. */
  235. #elif defined(CNSS_GENL)
  236. #include <qdf_mem.h>
  237. #include <wlan_nlink_common.h>
  238. #include <net/genetlink.h>
  239. #ifdef CONFIG_CNSS_OUT_OF_TREE
  240. #include "cnss_nl.h"
  241. #else
  242. #include <net/cnss_nl.h>
  243. #endif
  244. void cld80211_oem_send_reply(struct sk_buff *msg, void *hdr,
  245. struct nlattr *nest, int flags)
  246. {
  247. struct genl_family *cld80211_fam = cld80211_get_genl_family();
  248. nla_nest_end(msg, nest);
  249. genlmsg_end(msg, hdr);
  250. genlmsg_multicast_netns(cld80211_fam, &init_net, msg, 0,
  251. CLD80211_MCGRP_OEM_MSGS, flags);
  252. }
  253. struct sk_buff *
  254. cld80211_oem_rsp_alloc_skb(uint32_t portid, void **hdr, struct nlattr **nest,
  255. int *flags)
  256. {
  257. struct sk_buff *msg;
  258. if (in_interrupt() || irqs_disabled() || in_atomic())
  259. *flags = GFP_ATOMIC;
  260. msg = nlmsg_new(WLAN_CLD80211_MAX_SIZE, *flags);
  261. if (!msg) {
  262. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  263. "nlmsg malloc fails");
  264. return NULL;
  265. }
  266. *hdr = nl80211hdr_put(msg, portid, 0, *flags, WLAN_NL_MSG_OEM);
  267. if (*hdr == NULL) {
  268. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  269. "nl80211 hdr put failed");
  270. goto nla_put_failure;
  271. }
  272. *nest = nla_nest_start(msg, CLD80211_ATTR_VENDOR_DATA);
  273. if (*nest == NULL) {
  274. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  275. "nla_nest_start failed");
  276. goto nla_put_failure;
  277. }
  278. return msg;
  279. nla_put_failure:
  280. genlmsg_cancel(msg, *hdr);
  281. nlmsg_free(msg);
  282. return NULL;
  283. }
  284. /* For CNSS_GENL netlink sockets will be initialized by CNSS Kernel Module */
  285. int nl_srv_init(void *wiphy, int proto)
  286. {
  287. return 0;
  288. }
  289. void nl_srv_exit(void)
  290. {
  291. }
  292. int nl_srv_is_initialized(void)
  293. {
  294. return 0;
  295. }
  296. /* Not implemented by CNSS kernel module */
  297. int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
  298. {
  299. return 0;
  300. }
  301. int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
  302. {
  303. return 0;
  304. }
  305. void *nl80211hdr_put(struct sk_buff *skb, uint32_t portid,
  306. uint32_t seq, int flags, uint8_t cmd)
  307. {
  308. struct genl_family *cld80211_fam = cld80211_get_genl_family();
  309. return genlmsg_put(skb, portid, seq, cld80211_fam, flags, cmd);
  310. }
  311. /**
  312. * cld80211_fill_data() - API to fill payload to nl message
  313. * @msg: Sk buffer
  314. * @portid: Port ID
  315. * @seq: Sequence number
  316. * @flags: Flags
  317. * @cmd: Command ID
  318. * @buf: data buffer/payload to be filled
  319. * @len: length of the payload ie. @buf
  320. *
  321. * API to fill the payload/data of the nl message to be sent
  322. *
  323. * Return: zero on success
  324. */
  325. static int cld80211_fill_data(struct sk_buff *msg, uint32_t portid,
  326. uint32_t seq, int flags, uint8_t cmd,
  327. uint8_t *buf, int len)
  328. {
  329. void *hdr;
  330. struct nlattr *nest;
  331. hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
  332. if (!hdr) {
  333. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  334. "nl80211 hdr put failed");
  335. return -EPERM;
  336. }
  337. nest = nla_nest_start(msg, CLD80211_ATTR_VENDOR_DATA);
  338. if (!nest) {
  339. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  340. "nla_nest_start failed");
  341. goto nla_put_failure;
  342. }
  343. if (nla_put(msg, CLD80211_ATTR_DATA, len, buf)) {
  344. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  345. "nla_put failed");
  346. goto nla_put_failure;
  347. }
  348. nla_nest_end(msg, nest);
  349. genlmsg_end(msg, hdr);
  350. return 0;
  351. nla_put_failure:
  352. genlmsg_cancel(msg, hdr);
  353. return -EPERM;
  354. }
  355. /**
  356. * send_msg_to_cld80211() - API to send message to user space Application
  357. * @mcgroup_id: Multicast group ID
  358. * @pid: Port ID
  359. * @app_id: Application ID
  360. * @buf: Data/payload buffer to be sent
  361. * @len: Length of the data ie. @buf
  362. *
  363. * API to send the nl message to user space application.
  364. *
  365. * Return: zero on success
  366. */
  367. static int send_msg_to_cld80211(int mcgroup_id, int pid, int app_id,
  368. uint8_t *buf, int len)
  369. {
  370. struct sk_buff *msg;
  371. struct genl_family *cld80211_fam = cld80211_get_genl_family();
  372. int status;
  373. int flags = GFP_KERNEL;
  374. if (in_interrupt() || irqs_disabled() || in_atomic())
  375. flags = GFP_ATOMIC;
  376. if (len > NLMSG_DEFAULT_SIZE) {
  377. if (len > WLAN_CLD80211_MAX_SIZE) {
  378. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  379. "buf size:%d if more than max size: %d",
  380. len, (int) WLAN_CLD80211_MAX_SIZE);
  381. return -ENOMEM;
  382. }
  383. msg = nlmsg_new(WLAN_CLD80211_MAX_SIZE, flags);
  384. } else {
  385. msg = nlmsg_new(NLMSG_DEFAULT_SIZE, flags);
  386. }
  387. if (!msg) {
  388. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  389. "nlmsg malloc fails");
  390. return -EPERM;
  391. }
  392. status = cld80211_fill_data(msg, pid, 0, 0, app_id, buf, len);
  393. if (status) {
  394. nlmsg_free(msg);
  395. return -EPERM;
  396. }
  397. genlmsg_multicast_netns(cld80211_fam, &init_net, msg, 0,
  398. mcgroup_id, flags);
  399. return 0;
  400. }
  401. /**
  402. * nl_srv_bcast() - wrapper function to do broadcast events to user space apps
  403. * @skb: the socket buffer to send
  404. * @mcgroup_id: multicast group id
  405. * @app_id: application id
  406. *
  407. * This function is common wrapper to send broadcast events to different
  408. * user space applications.
  409. *
  410. * return: none
  411. */
  412. int nl_srv_bcast(struct sk_buff *skb, int mcgroup_id, int app_id)
  413. {
  414. struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data;
  415. void *msg = NLMSG_DATA(nlh);
  416. uint32_t msg_len = nlmsg_len(nlh);
  417. int status;
  418. status = send_msg_to_cld80211(mcgroup_id, 0, app_id, msg, msg_len);
  419. if (status) {
  420. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  421. "send msg to cld80211 fails for app id %d", app_id);
  422. dev_kfree_skb(skb);
  423. return -EPERM;
  424. }
  425. dev_kfree_skb(skb);
  426. return 0;
  427. }
  428. qdf_export_symbol(nl_srv_bcast);
  429. /**
  430. * nl_srv_ucast() - wrapper function to do unicast events to user space apps
  431. * @skb: the socket buffer to send
  432. * @dst_pid: destination process IF
  433. * @flag: flags
  434. * @app_id: application id
  435. * @mcgroup_id: Multicast group ID
  436. *
  437. * This function is common wrapper to send unicast events to different
  438. * user space applications. This internally used broadcast API with multicast
  439. * group mcgrp_id. This wrapper serves as a common API in both
  440. * new generic netlink infra and legacy implementation.
  441. *
  442. * return: zero on success, error code otherwise
  443. */
  444. int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag,
  445. int app_id, int mcgroup_id)
  446. {
  447. struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data;
  448. void *msg = NLMSG_DATA(nlh);
  449. uint32_t msg_len = nlmsg_len(nlh);
  450. int status;
  451. status = send_msg_to_cld80211(mcgroup_id, dst_pid, app_id,
  452. msg, msg_len);
  453. if (status) {
  454. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  455. "send msg to cld80211 fails for app id %d", app_id);
  456. dev_kfree_skb(skb);
  457. return -EPERM;
  458. }
  459. dev_kfree_skb(skb);
  460. return 0;
  461. }
  462. #elif !defined(MULTI_IF_NAME) || defined(MULTI_IF_LOG)
  463. /* Global variables */
  464. static DEFINE_MUTEX(nl_srv_sem);
  465. static struct sock *nl_srv_sock;
  466. static nl_srv_msg_callback nl_srv_msg_handler[NLINK_MAX_CALLBACKS];
  467. /* Forward declaration */
  468. static void nl_srv_rcv(struct sk_buff *sk);
  469. static void nl_srv_rcv_skb(struct sk_buff *skb);
  470. static void nl_srv_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh);
  471. /*
  472. * Initialize the netlink service.
  473. * Netlink service is usable after this.
  474. */
  475. int nl_srv_init(void *wiphy, int proto)
  476. {
  477. int retcode = 0;
  478. struct netlink_kernel_cfg cfg = {
  479. .groups = WLAN_NLINK_MCAST_GRP_ID,
  480. .input = nl_srv_rcv
  481. };
  482. nl_srv_sock = netlink_kernel_create(&init_net, proto,
  483. &cfg);
  484. if (nl_srv_sock) {
  485. memset(nl_srv_msg_handler, 0, sizeof(nl_srv_msg_handler));
  486. } else {
  487. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  488. "NLINK: netlink_kernel_create failed");
  489. retcode = -ECONNREFUSED;
  490. }
  491. return retcode;
  492. }
  493. /*
  494. * Deinit the netlink service.
  495. * Netlink service is unusable after this.
  496. */
  497. void nl_srv_exit(void)
  498. {
  499. if (nl_srv_is_initialized() == 0)
  500. netlink_kernel_release(nl_srv_sock);
  501. nl_srv_sock = NULL;
  502. }
  503. /*
  504. * Register a message handler for a specified module.
  505. * Each module (e.g. WLAN_NL_MSG_BTC )will register a
  506. * handler to handle messages addressed to it.
  507. */
  508. int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
  509. {
  510. int retcode = 0;
  511. if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
  512. msg_handler) {
  513. nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] = msg_handler;
  514. } else {
  515. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
  516. "NLINK: nl_srv_register failed for msg_type %d",
  517. msg_type);
  518. retcode = -EINVAL;
  519. }
  520. return retcode;
  521. }
  522. qdf_export_symbol(nl_srv_register);
  523. /*
  524. * Unregister the message handler for a specified module.
  525. */
  526. int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
  527. {
  528. int retcode = 0;
  529. if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
  530. (nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] == msg_handler)) {
  531. nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] = NULL;
  532. } else {
  533. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
  534. "NLINK: nl_srv_unregister failed for msg_type %d",
  535. msg_type);
  536. retcode = -EINVAL;
  537. }
  538. return retcode;
  539. }
  540. /*
  541. * Unicast the message to the process in user space identfied
  542. * by the dst-pid
  543. */
  544. int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag)
  545. {
  546. int err = -EINVAL;
  547. NETLINK_CB(skb).portid = 0; /* sender's pid */
  548. NETLINK_CB(skb).dst_group = 0; /* not multicast */
  549. if (nl_srv_sock) {
  550. err = netlink_unicast(nl_srv_sock, skb, dst_pid, flag);
  551. if (err < 0)
  552. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
  553. "NLINK: netlink_unicast to pid[%d] failed, ret[%d]",
  554. dst_pid, err);
  555. } else {
  556. dev_kfree_skb(skb);
  557. }
  558. return err;
  559. }
  560. /*
  561. * Broadcast the message. Broadcast will return an error if
  562. * there are no listeners
  563. */
  564. int nl_srv_bcast(struct sk_buff *skb)
  565. {
  566. int err = -EINVAL;
  567. int flags = GFP_KERNEL;
  568. if (in_interrupt() || irqs_disabled() || in_atomic())
  569. flags = GFP_ATOMIC;
  570. NETLINK_CB(skb).portid = 0; /* sender's pid */
  571. NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID; /* destination group */
  572. if (nl_srv_sock) {
  573. err = netlink_broadcast(nl_srv_sock, skb, 0,
  574. WLAN_NLINK_MCAST_GRP_ID, flags);
  575. if ((err < 0) && (err != -ESRCH)) {
  576. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
  577. "NLINK: netlink_broadcast failed err = %d",
  578. err);
  579. dev_kfree_skb(skb);
  580. }
  581. } else
  582. dev_kfree_skb(skb);
  583. return err;
  584. }
  585. qdf_export_symbol(nl_srv_bcast);
  586. /*
  587. * Processes the Netlink socket input queue.
  588. * Dequeue skb's from the socket input queue and process
  589. * all the netlink messages in that skb, before moving
  590. * to the next skb.
  591. */
  592. static void nl_srv_rcv(struct sk_buff *sk)
  593. {
  594. mutex_lock(&nl_srv_sem);
  595. nl_srv_rcv_skb(sk);
  596. mutex_unlock(&nl_srv_sem);
  597. }
  598. /*
  599. * Each skb could contain multiple Netlink messages. Process all the
  600. * messages in one skb and discard malformed skb's silently.
  601. */
  602. static void nl_srv_rcv_skb(struct sk_buff *skb)
  603. {
  604. struct nlmsghdr *nlh;
  605. while (skb->len >= NLMSG_SPACE(0)) {
  606. u32 rlen;
  607. nlh = (struct nlmsghdr *)skb->data;
  608. if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) {
  609. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
  610. "NLINK: Invalid "
  611. "Netlink message: skb[%pK], len[%d], nlhdr[%pK], nlmsg_len[%d]",
  612. skb, skb->len, nlh, nlh->nlmsg_len);
  613. return;
  614. }
  615. rlen = NLMSG_ALIGN(nlh->nlmsg_len);
  616. if (rlen > skb->len)
  617. rlen = skb->len;
  618. nl_srv_rcv_msg(skb, nlh);
  619. skb_pull(skb, rlen);
  620. }
  621. }
  622. /*
  623. * Process a netlink message.
  624. * Each netlink message will have a message of type tAniMsgHdr inside.
  625. */
  626. static void nl_srv_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
  627. {
  628. int type;
  629. /* Only requests are handled by kernel now */
  630. if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) {
  631. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
  632. "NLINK: Received Invalid NL Req type [%x]",
  633. nlh->nlmsg_flags);
  634. return;
  635. }
  636. type = nlh->nlmsg_type;
  637. /* Unknown message */
  638. if (type < WLAN_NL_MSG_BASE || type >= WLAN_NL_MSG_MAX) {
  639. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
  640. "NLINK: Received Invalid NL Msg type [%x]", type);
  641. return;
  642. }
  643. /*
  644. * All the messages must at least carry the tAniMsgHdr
  645. * Drop any message with invalid length
  646. */
  647. if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(tAniMsgHdr))) {
  648. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
  649. "NLINK: Received NL Msg with invalid len[%x]",
  650. nlh->nlmsg_len);
  651. return;
  652. }
  653. /* turn type into dispatch table offset */
  654. type -= WLAN_NL_MSG_BASE;
  655. /* dispatch to handler */
  656. if (nl_srv_msg_handler[type]) {
  657. (nl_srv_msg_handler[type])(skb);
  658. } else {
  659. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
  660. "NLINK: No handler for Netlink Msg [0x%X]", type);
  661. }
  662. }
  663. /**
  664. * nl_srv_is_initialized() - This function is used check if the netlink
  665. * service is initialized
  666. *
  667. * This function is used check if the netlink service is initialized
  668. *
  669. * Return: Return -EPERM if the service is not initialized
  670. *
  671. */
  672. int nl_srv_is_initialized(void)
  673. {
  674. if (nl_srv_sock)
  675. return 0;
  676. return -EPERM;
  677. }
  678. qdf_export_symbol(nl_srv_is_initialized);
  679. #else
  680. int nl_srv_init(void *wiphy, int proto)
  681. {
  682. return 0;
  683. }
  684. void nl_srv_exit(void)
  685. {
  686. }
  687. int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
  688. {
  689. return 0;
  690. }
  691. int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
  692. {
  693. return 0;
  694. }
  695. int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag)
  696. {
  697. dev_kfree_skb(skb);
  698. return 0;
  699. }
  700. int nl_srv_bcast(struct sk_buff *skb)
  701. {
  702. dev_kfree_skb(skb);
  703. return 0;
  704. }
  705. qdf_export_symbol(nl_srv_bcast);
  706. int nl_srv_is_initialized(void)
  707. {
  708. return -EPERM;
  709. }
  710. qdf_export_symbol(nl_srv_is_initialized);
  711. #endif
  712. /**
  713. * nl_srv_ucast_oem() - Wrapper function to send ucast msgs to OEM
  714. * @skb: sk buffer pointer
  715. * @dst_pid: Destination PID
  716. * @flag: flags
  717. *
  718. * Sends the ucast message to OEM with generic nl socket if CNSS_GENL
  719. * is enabled. Else, use the legacy netlink socket to send.
  720. *
  721. * Return: None
  722. */
  723. #ifdef CNSS_GENL
  724. void nl_srv_ucast_oem(struct sk_buff *skb, int dst_pid, int flag)
  725. {
  726. nl_srv_ucast(skb, dst_pid, flag, WLAN_NL_MSG_OEM,
  727. CLD80211_MCGRP_OEM_MSGS);
  728. }
  729. #else
  730. void nl_srv_ucast_oem(struct sk_buff *skb, int dst_pid, int flag)
  731. {
  732. nl_srv_ucast(skb, dst_pid, flag);
  733. }
  734. qdf_export_symbol(nl_srv_ucast_oem);
  735. #endif