dn_rtmsg.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * DECnet An implementation of the DECnet protocol suite for the LINUX
  3. * operating system. DECnet is implemented using the BSD Socket
  4. * interface as the means of communication with the user level.
  5. *
  6. * DECnet Routing Message Grabulator
  7. *
  8. * (C) 2000 ChyGwyn Limited - http://www.chygwyn.com/
  9. * This code may be copied under the GPL v.2 or at your option
  10. * any later version.
  11. *
  12. * Author: Steven Whitehouse <steve@chygwyn.com>
  13. *
  14. */
  15. #include <linux/module.h>
  16. #include <linux/skbuff.h>
  17. #include <linux/slab.h>
  18. #include <linux/init.h>
  19. #include <linux/netdevice.h>
  20. #include <linux/netfilter.h>
  21. #include <linux/spinlock.h>
  22. #include <net/netlink.h>
  23. #include <linux/netfilter_decnet.h>
  24. #include <net/sock.h>
  25. #include <net/flow.h>
  26. #include <net/dn.h>
  27. #include <net/dn_route.h>
  28. static struct sock *dnrmg = NULL;
  29. static struct sk_buff *dnrmg_build_message(struct sk_buff *rt_skb, int *errp)
  30. {
  31. struct sk_buff *skb = NULL;
  32. size_t size;
  33. sk_buff_data_t old_tail;
  34. struct nlmsghdr *nlh;
  35. unsigned char *ptr;
  36. struct nf_dn_rtmsg *rtm;
  37. size = NLMSG_ALIGN(rt_skb->len) +
  38. NLMSG_ALIGN(sizeof(struct nf_dn_rtmsg));
  39. skb = nlmsg_new(size, GFP_ATOMIC);
  40. if (!skb) {
  41. *errp = -ENOMEM;
  42. return NULL;
  43. }
  44. old_tail = skb->tail;
  45. nlh = nlmsg_put(skb, 0, 0, 0, size, 0);
  46. if (!nlh) {
  47. kfree_skb(skb);
  48. *errp = -ENOMEM;
  49. return NULL;
  50. }
  51. rtm = (struct nf_dn_rtmsg *)nlmsg_data(nlh);
  52. rtm->nfdn_ifindex = rt_skb->dev->ifindex;
  53. ptr = NFDN_RTMSG(rtm);
  54. skb_copy_from_linear_data(rt_skb, ptr, rt_skb->len);
  55. nlh->nlmsg_len = skb->tail - old_tail;
  56. return skb;
  57. }
  58. static void dnrmg_send_peer(struct sk_buff *skb)
  59. {
  60. struct sk_buff *skb2;
  61. int status = 0;
  62. int group = 0;
  63. unsigned char flags = *skb->data;
  64. switch (flags & DN_RT_CNTL_MSK) {
  65. case DN_RT_PKT_L1RT:
  66. group = DNRNG_NLGRP_L1;
  67. break;
  68. case DN_RT_PKT_L2RT:
  69. group = DNRNG_NLGRP_L2;
  70. break;
  71. default:
  72. return;
  73. }
  74. skb2 = dnrmg_build_message(skb, &status);
  75. if (skb2 == NULL)
  76. return;
  77. NETLINK_CB(skb2).dst_group = group;
  78. netlink_broadcast(dnrmg, skb2, 0, group, GFP_ATOMIC);
  79. }
  80. static unsigned int dnrmg_hook(void *priv,
  81. struct sk_buff *skb,
  82. const struct nf_hook_state *state)
  83. {
  84. dnrmg_send_peer(skb);
  85. return NF_ACCEPT;
  86. }
  87. #define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0)
  88. static inline void dnrmg_receive_user_skb(struct sk_buff *skb)
  89. {
  90. struct nlmsghdr *nlh = nlmsg_hdr(skb);
  91. if (skb->len < sizeof(*nlh) ||
  92. nlh->nlmsg_len < sizeof(*nlh) ||
  93. skb->len < nlh->nlmsg_len)
  94. return;
  95. if (!netlink_capable(skb, CAP_NET_ADMIN))
  96. RCV_SKB_FAIL(-EPERM);
  97. /* Eventually we might send routing messages too */
  98. RCV_SKB_FAIL(-EINVAL);
  99. }
  100. static struct nf_hook_ops dnrmg_ops __read_mostly = {
  101. .hook = dnrmg_hook,
  102. .pf = NFPROTO_DECNET,
  103. .hooknum = NF_DN_ROUTE,
  104. .priority = NF_DN_PRI_DNRTMSG,
  105. };
  106. static int __init dn_rtmsg_init(void)
  107. {
  108. int rv = 0;
  109. struct netlink_kernel_cfg cfg = {
  110. .groups = DNRNG_NLGRP_MAX,
  111. .input = dnrmg_receive_user_skb,
  112. };
  113. dnrmg = netlink_kernel_create(&init_net, NETLINK_DNRTMSG, &cfg);
  114. if (dnrmg == NULL) {
  115. printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket");
  116. return -ENOMEM;
  117. }
  118. rv = nf_register_hook(&dnrmg_ops);
  119. if (rv) {
  120. netlink_kernel_release(dnrmg);
  121. }
  122. return rv;
  123. }
  124. static void __exit dn_rtmsg_fini(void)
  125. {
  126. nf_unregister_hook(&dnrmg_ops);
  127. netlink_kernel_release(dnrmg);
  128. }
  129. MODULE_DESCRIPTION("DECnet Routing Message Grabulator");
  130. MODULE_AUTHOR("Steven Whitehouse <steve@chygwyn.com>");
  131. MODULE_LICENSE("GPL");
  132. MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_DNRTMSG);
  133. module_init(dn_rtmsg_init);
  134. module_exit(dn_rtmsg_fini);