af_vsock_tap.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * Tap functions for AF_VSOCK sockets.
  3. *
  4. * Code based on net/netlink/af_netlink.c tap functions.
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. */
  11. #include <linux/module.h>
  12. #include <net/sock.h>
  13. #include <net/af_vsock.h>
  14. #include <linux/if_arp.h>
  15. static DEFINE_SPINLOCK(vsock_tap_lock);
  16. static struct list_head vsock_tap_all __read_mostly =
  17. LIST_HEAD_INIT(vsock_tap_all);
  18. int vsock_add_tap(struct vsock_tap *vt)
  19. {
  20. if (unlikely(vt->dev->type != ARPHRD_VSOCKMON))
  21. return -EINVAL;
  22. __module_get(vt->module);
  23. spin_lock(&vsock_tap_lock);
  24. list_add_rcu(&vt->list, &vsock_tap_all);
  25. spin_unlock(&vsock_tap_lock);
  26. return 0;
  27. }
  28. EXPORT_SYMBOL_GPL(vsock_add_tap);
  29. int vsock_remove_tap(struct vsock_tap *vt)
  30. {
  31. struct vsock_tap *tmp;
  32. bool found = false;
  33. spin_lock(&vsock_tap_lock);
  34. list_for_each_entry(tmp, &vsock_tap_all, list) {
  35. if (vt == tmp) {
  36. list_del_rcu(&vt->list);
  37. found = true;
  38. goto out;
  39. }
  40. }
  41. pr_warn("vsock_remove_tap: %p not found\n", vt);
  42. out:
  43. spin_unlock(&vsock_tap_lock);
  44. synchronize_net();
  45. if (found)
  46. module_put(vt->module);
  47. return found ? 0 : -ENODEV;
  48. }
  49. EXPORT_SYMBOL_GPL(vsock_remove_tap);
  50. static int __vsock_deliver_tap_skb(struct sk_buff *skb,
  51. struct net_device *dev)
  52. {
  53. int ret = 0;
  54. struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
  55. if (nskb) {
  56. dev_hold(dev);
  57. nskb->dev = dev;
  58. ret = dev_queue_xmit(nskb);
  59. if (unlikely(ret > 0))
  60. ret = net_xmit_errno(ret);
  61. dev_put(dev);
  62. }
  63. return ret;
  64. }
  65. static void __vsock_deliver_tap(struct sk_buff *skb)
  66. {
  67. int ret;
  68. struct vsock_tap *tmp;
  69. list_for_each_entry_rcu(tmp, &vsock_tap_all, list) {
  70. ret = __vsock_deliver_tap_skb(skb, tmp->dev);
  71. if (unlikely(ret))
  72. break;
  73. }
  74. }
  75. void vsock_deliver_tap(struct sk_buff *build_skb(void *opaque), void *opaque)
  76. {
  77. struct sk_buff *skb;
  78. rcu_read_lock();
  79. if (likely(list_empty(&vsock_tap_all)))
  80. goto out;
  81. skb = build_skb(opaque);
  82. if (skb) {
  83. __vsock_deliver_tap(skb);
  84. consume_skb(skb);
  85. }
  86. out:
  87. rcu_read_unlock();
  88. }
  89. EXPORT_SYMBOL_GPL(vsock_deliver_tap);