af_vsock_tap.c 2.0 KB

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