wlan_nlink_srv.c 20 KB

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