netlink_k.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
  3. *
  4. * This software is licensed under the terms of the GNU General Public
  5. * License version 2, as published by the Free Software Foundation, and
  6. * may be copied, distributed, and modified under those terms.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  14. #include <linux/module.h>
  15. #include <linux/etherdevice.h>
  16. #include <net/netlink.h>
  17. #include <asm/byteorder.h>
  18. #include <net/sock.h>
  19. #include "netlink_k.h"
  20. #if !defined(NLMSG_HDRLEN)
  21. #define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
  22. #endif
  23. #define ND_MAX_GROUP 30
  24. #define ND_IFINDEX_LEN sizeof(int)
  25. #define ND_NLMSG_SPACE(len) (nlmsg_total_size(len) + ND_IFINDEX_LEN)
  26. #define ND_NLMSG_DATA(nlh) \
  27. ((void *)((char *)nlmsg_data(nlh) + ND_IFINDEX_LEN))
  28. #define ND_NLMSG_S_LEN(len) (len+ND_IFINDEX_LEN)
  29. #define ND_NLMSG_R_LEN(nlh) (nlh->nlmsg_len-ND_IFINDEX_LEN)
  30. #define ND_NLMSG_IFIDX(nlh) nlmsg_data(nlh)
  31. #define ND_MAX_MSG_LEN 8096
  32. #if defined(DEFINE_MUTEX)
  33. static DEFINE_MUTEX(netlink_mutex);
  34. #else
  35. static struct semaphore netlink_mutex;
  36. #define mutex_lock(x) down(x)
  37. #define mutex_unlock(x) up(x)
  38. #endif
  39. static void (*rcv_cb)(struct net_device *dev, u16 type, void *msg, int len);
  40. static void netlink_rcv_cb(struct sk_buff *skb)
  41. {
  42. struct nlmsghdr *nlh;
  43. struct net_device *dev;
  44. u32 mlen;
  45. void *msg;
  46. int ifindex;
  47. if (skb->len >= NLMSG_HDRLEN) {
  48. nlh = (struct nlmsghdr *)skb->data;
  49. if (skb->len < nlh->nlmsg_len ||
  50. nlh->nlmsg_len > ND_MAX_MSG_LEN) {
  51. netdev_err(skb->dev, "Invalid length (%d,%d)\n",
  52. skb->len, nlh->nlmsg_len);
  53. return;
  54. }
  55. memcpy(&ifindex, ND_NLMSG_IFIDX(nlh), ND_IFINDEX_LEN);
  56. msg = ND_NLMSG_DATA(nlh);
  57. mlen = ND_NLMSG_R_LEN(nlh);
  58. if (rcv_cb) {
  59. dev = dev_get_by_index(&init_net, ifindex);
  60. if (dev) {
  61. rcv_cb(dev, nlh->nlmsg_type, msg, mlen);
  62. dev_put(dev);
  63. } else
  64. netdev_err(skb->dev,
  65. "dev_get_by_index(%d) is not found.\n",
  66. ifindex);
  67. } else {
  68. netdev_err(skb->dev, "Unregistered Callback\n");
  69. }
  70. }
  71. }
  72. static void netlink_rcv(struct sk_buff *skb)
  73. {
  74. mutex_lock(&netlink_mutex);
  75. netlink_rcv_cb(skb);
  76. mutex_unlock(&netlink_mutex);
  77. }
  78. struct sock *netlink_init(int unit, void (*cb)(struct net_device *dev, u16 type,
  79. void *msg, int len))
  80. {
  81. struct sock *sock;
  82. struct netlink_kernel_cfg cfg = {
  83. .input = netlink_rcv,
  84. };
  85. #if !defined(DEFINE_MUTEX)
  86. init_MUTEX(&netlink_mutex);
  87. #endif
  88. sock = netlink_kernel_create(&init_net, unit, &cfg);
  89. if (sock)
  90. rcv_cb = cb;
  91. return sock;
  92. }
  93. void netlink_exit(struct sock *sock)
  94. {
  95. netlink_kernel_release(sock);
  96. }
  97. int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len)
  98. {
  99. static u32 seq;
  100. struct sk_buff *skb = NULL;
  101. struct nlmsghdr *nlh;
  102. int ret = 0;
  103. if (group > ND_MAX_GROUP) {
  104. pr_err("Group %d is invalid.\n", group);
  105. pr_err("Valid group is 0 ~ %d.\n", ND_MAX_GROUP);
  106. return -EINVAL;
  107. }
  108. skb = nlmsg_new(len, GFP_ATOMIC);
  109. if (!skb) {
  110. pr_err("netlink_broadcast ret=%d\n", ret);
  111. return -ENOMEM;
  112. }
  113. seq++;
  114. nlh = nlmsg_put(skb, 0, seq, type, len, 0);
  115. if (!nlh) {
  116. kfree_skb(skb);
  117. return -EMSGSIZE;
  118. }
  119. memcpy(nlmsg_data(nlh), msg, len);
  120. NETLINK_CB(skb).portid = 0;
  121. NETLINK_CB(skb).dst_group = 0;
  122. ret = netlink_broadcast(sock, skb, 0, group+1, GFP_ATOMIC);
  123. if (!ret)
  124. return len;
  125. if (ret != -ESRCH) {
  126. pr_err("netlink_broadcast g=%d, t=%d, l=%d, r=%d\n",
  127. group, type, len, ret);
  128. }
  129. ret = 0;
  130. return ret;
  131. }