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