wlan_nlink_srv.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. /*
  2. * Copyright (c) 2012-2020 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. #include <net/cnss_nl.h>
  240. void cld80211_oem_send_reply(struct sk_buff *msg, void *hdr,
  241. struct nlattr *nest, int flags)
  242. {
  243. struct genl_family *cld80211_fam = cld80211_get_genl_family();
  244. nla_nest_end(msg, nest);
  245. genlmsg_end(msg, hdr);
  246. genlmsg_multicast_netns(cld80211_fam, &init_net, msg, 0,
  247. CLD80211_MCGRP_OEM_MSGS, flags);
  248. }
  249. struct sk_buff *
  250. cld80211_oem_rsp_alloc_skb(uint32_t portid, void **hdr, struct nlattr **nest,
  251. int *flags)
  252. {
  253. static struct sk_buff *msg;
  254. if (in_interrupt() || irqs_disabled() || in_atomic())
  255. *flags = GFP_ATOMIC;
  256. msg = nlmsg_new(WLAN_CLD80211_MAX_SIZE, *flags);
  257. if (!msg) {
  258. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  259. "nlmsg malloc fails");
  260. return NULL;
  261. }
  262. *hdr = nl80211hdr_put(msg, portid, 0, *flags, WLAN_NL_MSG_OEM);
  263. if (*hdr == NULL) {
  264. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  265. "nl80211 hdr put failed");
  266. goto nla_put_failure;
  267. }
  268. *nest = nla_nest_start(msg, CLD80211_ATTR_VENDOR_DATA);
  269. if (*nest == NULL) {
  270. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  271. "nla_nest_start failed");
  272. goto nla_put_failure;
  273. }
  274. return msg;
  275. nla_put_failure:
  276. genlmsg_cancel(msg, *hdr);
  277. nlmsg_free(msg);
  278. return NULL;
  279. }
  280. /* For CNSS_GENL netlink sockets will be initialized by CNSS Kernel Module */
  281. int nl_srv_init(void *wiphy, int proto)
  282. {
  283. return 0;
  284. }
  285. void nl_srv_exit(void)
  286. {
  287. }
  288. int nl_srv_is_initialized(void)
  289. {
  290. return 0;
  291. }
  292. /* Not implemented by CNSS kernel module */
  293. int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
  294. {
  295. return 0;
  296. }
  297. int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
  298. {
  299. return 0;
  300. }
  301. void *nl80211hdr_put(struct sk_buff *skb, uint32_t portid,
  302. uint32_t seq, int flags, uint8_t cmd)
  303. {
  304. struct genl_family *cld80211_fam = cld80211_get_genl_family();
  305. return genlmsg_put(skb, portid, seq, cld80211_fam, flags, cmd);
  306. }
  307. /**
  308. * cld80211_fill_data() - API to fill payload to nl message
  309. * @msg: Sk buffer
  310. * @portid: Port ID
  311. * @seq: Sequence number
  312. * @flags: Flags
  313. * @cmd: Command ID
  314. * @buf: data buffer/payload to be filled
  315. * @len: length of the payload ie. @buf
  316. *
  317. * API to fill the payload/data of the nl message to be sent
  318. *
  319. * Return: zero on success
  320. */
  321. static int cld80211_fill_data(struct sk_buff *msg, uint32_t portid,
  322. uint32_t seq, int flags, uint8_t cmd,
  323. uint8_t *buf, int len)
  324. {
  325. void *hdr;
  326. struct nlattr *nest;
  327. hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
  328. if (!hdr) {
  329. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  330. "nl80211 hdr put failed");
  331. return -EPERM;
  332. }
  333. nest = nla_nest_start(msg, CLD80211_ATTR_VENDOR_DATA);
  334. if (!nest) {
  335. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  336. "nla_nest_start failed");
  337. goto nla_put_failure;
  338. }
  339. if (nla_put(msg, CLD80211_ATTR_DATA, len, buf)) {
  340. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  341. "nla_put failed");
  342. goto nla_put_failure;
  343. }
  344. nla_nest_end(msg, nest);
  345. genlmsg_end(msg, hdr);
  346. return 0;
  347. nla_put_failure:
  348. genlmsg_cancel(msg, hdr);
  349. return -EPERM;
  350. }
  351. /**
  352. * send_msg_to_cld80211() - API to send message to user space Application
  353. * @mcgroup_id: Multicast group ID
  354. * @pid: Port ID
  355. * @app_id: Application ID
  356. * @buf: Data/payload buffer to be sent
  357. * @len: Length of the data ie. @buf
  358. *
  359. * API to send the nl message to user space application.
  360. *
  361. * Return: zero on success
  362. */
  363. static int send_msg_to_cld80211(int mcgroup_id, int pid, int app_id,
  364. uint8_t *buf, int len)
  365. {
  366. struct sk_buff *msg;
  367. struct genl_family *cld80211_fam = cld80211_get_genl_family();
  368. int status;
  369. int flags = GFP_KERNEL;
  370. if (in_interrupt() || irqs_disabled() || in_atomic())
  371. flags = GFP_ATOMIC;
  372. if (len > NLMSG_DEFAULT_SIZE) {
  373. if (len > WLAN_CLD80211_MAX_SIZE) {
  374. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  375. "buf size:%d if more than max size: %d",
  376. len, (int) WLAN_CLD80211_MAX_SIZE);
  377. return -ENOMEM;
  378. }
  379. msg = nlmsg_new(WLAN_CLD80211_MAX_SIZE, flags);
  380. } else {
  381. msg = nlmsg_new(NLMSG_DEFAULT_SIZE, flags);
  382. }
  383. if (!msg) {
  384. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  385. "nlmsg malloc fails");
  386. return -EPERM;
  387. }
  388. status = cld80211_fill_data(msg, pid, 0, 0, app_id, buf, len);
  389. if (status) {
  390. nlmsg_free(msg);
  391. return -EPERM;
  392. }
  393. genlmsg_multicast_netns(cld80211_fam, &init_net, msg, 0,
  394. mcgroup_id, flags);
  395. return 0;
  396. }
  397. /**
  398. * nl_srv_bcast() - wrapper function to do broadcast events to user space apps
  399. * @skb: the socket buffer to send
  400. * @mcgroup_id: multicast group id
  401. * @app_id: application id
  402. *
  403. * This function is common wrapper to send broadcast events to different
  404. * user space applications.
  405. *
  406. * return: none
  407. */
  408. int nl_srv_bcast(struct sk_buff *skb, int mcgroup_id, int app_id)
  409. {
  410. struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data;
  411. void *msg = NLMSG_DATA(nlh);
  412. uint32_t msg_len = nlmsg_len(nlh);
  413. int status;
  414. status = send_msg_to_cld80211(mcgroup_id, 0, app_id, msg, msg_len);
  415. if (status) {
  416. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  417. "send msg to cld80211 fails for app id %d", app_id);
  418. dev_kfree_skb(skb);
  419. return -EPERM;
  420. }
  421. dev_kfree_skb(skb);
  422. return 0;
  423. }
  424. qdf_export_symbol(nl_srv_bcast);
  425. /**
  426. * nl_srv_ucast() - wrapper function to do unicast events to user space apps
  427. * @skb: the socket buffer to send
  428. * @dst_pid: destination process IF
  429. * @flag: flags
  430. * @app_id: application id
  431. * @mcgroup_id: Multicast group ID
  432. *
  433. * This function is common wrapper to send unicast events to different
  434. * user space applications. This internally used broadcast API with multicast
  435. * group mcgrp_id. This wrapper serves as a common API in both
  436. * new generic netlink infra and legacy implementation.
  437. *
  438. * return: zero on success, error code otherwise
  439. */
  440. int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag,
  441. int app_id, int mcgroup_id)
  442. {
  443. struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data;
  444. void *msg = NLMSG_DATA(nlh);
  445. uint32_t msg_len = nlmsg_len(nlh);
  446. int status;
  447. status = send_msg_to_cld80211(mcgroup_id, dst_pid, app_id,
  448. msg, msg_len);
  449. if (status) {
  450. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  451. "send msg to cld80211 fails for app id %d", app_id);
  452. dev_kfree_skb(skb);
  453. return -EPERM;
  454. }
  455. dev_kfree_skb(skb);
  456. return 0;
  457. }
  458. #elif !defined(MULTI_IF_NAME) || defined(MULTI_IF_LOG)
  459. /* Global variables */
  460. static DEFINE_MUTEX(nl_srv_sem);
  461. static struct sock *nl_srv_sock;
  462. static nl_srv_msg_callback nl_srv_msg_handler[NLINK_MAX_CALLBACKS];
  463. /* Forward declaration */
  464. static void nl_srv_rcv(struct sk_buff *sk);
  465. static void nl_srv_rcv_skb(struct sk_buff *skb);
  466. static void nl_srv_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh);
  467. /*
  468. * Initialize the netlink service.
  469. * Netlink service is usable after this.
  470. */
  471. int nl_srv_init(void *wiphy, int proto)
  472. {
  473. int retcode = 0;
  474. struct netlink_kernel_cfg cfg = {
  475. .groups = WLAN_NLINK_MCAST_GRP_ID,
  476. .input = nl_srv_rcv
  477. };
  478. nl_srv_sock = netlink_kernel_create(&init_net, proto,
  479. &cfg);
  480. if (nl_srv_sock) {
  481. memset(nl_srv_msg_handler, 0, sizeof(nl_srv_msg_handler));
  482. } else {
  483. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
  484. "NLINK: netlink_kernel_create failed");
  485. retcode = -ECONNREFUSED;
  486. }
  487. return retcode;
  488. }
  489. /*
  490. * Deinit the netlink service.
  491. * Netlink service is unusable after this.
  492. */
  493. void nl_srv_exit(void)
  494. {
  495. if (nl_srv_is_initialized() == 0)
  496. netlink_kernel_release(nl_srv_sock);
  497. nl_srv_sock = NULL;
  498. }
  499. /*
  500. * Register a message handler for a specified module.
  501. * Each module (e.g. WLAN_NL_MSG_BTC )will register a
  502. * handler to handle messages addressed to it.
  503. */
  504. int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
  505. {
  506. int retcode = 0;
  507. if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
  508. msg_handler) {
  509. nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] = msg_handler;
  510. } else {
  511. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
  512. "NLINK: nl_srv_register failed for msg_type %d",
  513. msg_type);
  514. retcode = -EINVAL;
  515. }
  516. return retcode;
  517. }
  518. qdf_export_symbol(nl_srv_register);
  519. /*
  520. * Unregister the message handler for a specified module.
  521. */
  522. int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
  523. {
  524. int retcode = 0;
  525. if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
  526. (nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] == msg_handler)) {
  527. nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] = NULL;
  528. } else {
  529. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
  530. "NLINK: nl_srv_unregister failed for msg_type %d",
  531. msg_type);
  532. retcode = -EINVAL;
  533. }
  534. return retcode;
  535. }
  536. /*
  537. * Unicast the message to the process in user space identfied
  538. * by the dst-pid
  539. */
  540. int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag)
  541. {
  542. int err = -EINVAL;
  543. NETLINK_CB(skb).portid = 0; /* sender's pid */
  544. NETLINK_CB(skb).dst_group = 0; /* not multicast */
  545. if (nl_srv_sock) {
  546. err = netlink_unicast(nl_srv_sock, skb, dst_pid, flag);
  547. if (err < 0)
  548. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
  549. "NLINK: netlink_unicast to pid[%d] failed, ret[%d]",
  550. dst_pid, err);
  551. } else {
  552. dev_kfree_skb(skb);
  553. }
  554. return err;
  555. }
  556. /*
  557. * Broadcast the message. Broadcast will return an error if
  558. * there are no listeners
  559. */
  560. int nl_srv_bcast(struct sk_buff *skb)
  561. {
  562. int err = -EINVAL;
  563. int flags = GFP_KERNEL;
  564. if (in_interrupt() || irqs_disabled() || in_atomic())
  565. flags = GFP_ATOMIC;
  566. NETLINK_CB(skb).portid = 0; /* sender's pid */
  567. NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID; /* destination group */
  568. if (nl_srv_sock) {
  569. err = netlink_broadcast(nl_srv_sock, skb, 0,
  570. WLAN_NLINK_MCAST_GRP_ID, flags);
  571. if ((err < 0) && (err != -ESRCH)) {
  572. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
  573. "NLINK: netlink_broadcast failed err = %d",
  574. err);
  575. dev_kfree_skb(skb);
  576. }
  577. } else
  578. dev_kfree_skb(skb);
  579. return err;
  580. }
  581. qdf_export_symbol(nl_srv_bcast);
  582. /*
  583. * Processes the Netlink socket input queue.
  584. * Dequeue skb's from the socket input queue and process
  585. * all the netlink messages in that skb, before moving
  586. * to the next skb.
  587. */
  588. static void nl_srv_rcv(struct sk_buff *sk)
  589. {
  590. mutex_lock(&nl_srv_sem);
  591. nl_srv_rcv_skb(sk);
  592. mutex_unlock(&nl_srv_sem);
  593. }
  594. /*
  595. * Each skb could contain multiple Netlink messages. Process all the
  596. * messages in one skb and discard malformed skb's silently.
  597. */
  598. static void nl_srv_rcv_skb(struct sk_buff *skb)
  599. {
  600. struct nlmsghdr *nlh;
  601. while (skb->len >= NLMSG_SPACE(0)) {
  602. u32 rlen;
  603. nlh = (struct nlmsghdr *)skb->data;
  604. if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) {
  605. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
  606. "NLINK: Invalid "
  607. "Netlink message: skb[%pK], len[%d], nlhdr[%pK], nlmsg_len[%d]",
  608. skb, skb->len, nlh, nlh->nlmsg_len);
  609. return;
  610. }
  611. rlen = NLMSG_ALIGN(nlh->nlmsg_len);
  612. if (rlen > skb->len)
  613. rlen = skb->len;
  614. nl_srv_rcv_msg(skb, nlh);
  615. skb_pull(skb, rlen);
  616. }
  617. }
  618. /*
  619. * Process a netlink message.
  620. * Each netlink message will have a message of type tAniMsgHdr inside.
  621. */
  622. static void nl_srv_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
  623. {
  624. int type;
  625. /* Only requests are handled by kernel now */
  626. if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) {
  627. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
  628. "NLINK: Received Invalid NL Req type [%x]",
  629. nlh->nlmsg_flags);
  630. return;
  631. }
  632. type = nlh->nlmsg_type;
  633. /* Unknown message */
  634. if (type < WLAN_NL_MSG_BASE || type >= WLAN_NL_MSG_MAX) {
  635. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
  636. "NLINK: Received Invalid NL Msg type [%x]", type);
  637. return;
  638. }
  639. /*
  640. * All the messages must at least carry the tAniMsgHdr
  641. * Drop any message with invalid length
  642. */
  643. if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(tAniMsgHdr))) {
  644. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
  645. "NLINK: Received NL Msg with invalid len[%x]",
  646. nlh->nlmsg_len);
  647. return;
  648. }
  649. /* turn type into dispatch table offset */
  650. type -= WLAN_NL_MSG_BASE;
  651. /* dispatch to handler */
  652. if (nl_srv_msg_handler[type]) {
  653. (nl_srv_msg_handler[type])(skb);
  654. } else {
  655. QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
  656. "NLINK: No handler for Netlink Msg [0x%X]", type);
  657. }
  658. }
  659. /**
  660. * nl_srv_is_initialized() - This function is used check if the netlink
  661. * service is initialized
  662. *
  663. * This function is used check if the netlink service is initialized
  664. *
  665. * Return: Return -EPERM if the service is not initialized
  666. *
  667. */
  668. int nl_srv_is_initialized(void)
  669. {
  670. if (nl_srv_sock)
  671. return 0;
  672. return -EPERM;
  673. }
  674. qdf_export_symbol(nl_srv_is_initialized);
  675. #else
  676. int nl_srv_init(void *wiphy, int proto)
  677. {
  678. return 0;
  679. }
  680. void nl_srv_exit(void)
  681. {
  682. }
  683. int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
  684. {
  685. return 0;
  686. }
  687. int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
  688. {
  689. return 0;
  690. }
  691. int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag)
  692. {
  693. dev_kfree_skb(skb);
  694. return 0;
  695. }
  696. int nl_srv_bcast(struct sk_buff *skb)
  697. {
  698. dev_kfree_skb(skb);
  699. return 0;
  700. }
  701. qdf_export_symbol(nl_srv_bcast);
  702. int nl_srv_is_initialized(void)
  703. {
  704. return -EPERM;
  705. }
  706. qdf_export_symbol(nl_srv_is_initialized);
  707. #endif
  708. /**
  709. * nl_srv_ucast_oem() - Wrapper function to send ucast msgs to OEM
  710. * @skb: sk buffer pointer
  711. * @dst_pid: Destination PID
  712. * @flag: flags
  713. *
  714. * Sends the ucast message to OEM with generic nl socket if CNSS_GENL
  715. * is enabled. Else, use the legacy netlink socket to send.
  716. *
  717. * Return: None
  718. */
  719. #ifdef CNSS_GENL
  720. void nl_srv_ucast_oem(struct sk_buff *skb, int dst_pid, int flag)
  721. {
  722. nl_srv_ucast(skb, dst_pid, flag, WLAN_NL_MSG_OEM,
  723. CLD80211_MCGRP_OEM_MSGS);
  724. }
  725. #else
  726. void nl_srv_ucast_oem(struct sk_buff *skb, int dst_pid, int flag)
  727. {
  728. nl_srv_ucast(skb, dst_pid, flag);
  729. }
  730. qdf_export_symbol(nl_srv_ucast_oem);
  731. #endif