wlan_nlink_srv.c 19 KB

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