rose_loopback.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * Copyright (C) Jonathan Naylor G4KLX ([email protected])
  5. */
  6. #include <linux/types.h>
  7. #include <linux/slab.h>
  8. #include <linux/socket.h>
  9. #include <linux/timer.h>
  10. #include <net/ax25.h>
  11. #include <linux/skbuff.h>
  12. #include <net/rose.h>
  13. #include <linux/init.h>
  14. static struct sk_buff_head loopback_queue;
  15. #define ROSE_LOOPBACK_LIMIT 1000
  16. static struct timer_list loopback_timer;
  17. static void rose_set_loopback_timer(void);
  18. static void rose_loopback_timer(struct timer_list *unused);
  19. void rose_loopback_init(void)
  20. {
  21. skb_queue_head_init(&loopback_queue);
  22. timer_setup(&loopback_timer, rose_loopback_timer, 0);
  23. }
  24. static int rose_loopback_running(void)
  25. {
  26. return timer_pending(&loopback_timer);
  27. }
  28. int rose_loopback_queue(struct sk_buff *skb, struct rose_neigh *neigh)
  29. {
  30. struct sk_buff *skbn = NULL;
  31. if (skb_queue_len(&loopback_queue) < ROSE_LOOPBACK_LIMIT)
  32. skbn = skb_clone(skb, GFP_ATOMIC);
  33. if (skbn) {
  34. consume_skb(skb);
  35. skb_queue_tail(&loopback_queue, skbn);
  36. if (!rose_loopback_running())
  37. rose_set_loopback_timer();
  38. } else {
  39. kfree_skb(skb);
  40. }
  41. return 1;
  42. }
  43. static void rose_set_loopback_timer(void)
  44. {
  45. mod_timer(&loopback_timer, jiffies + 10);
  46. }
  47. static void rose_loopback_timer(struct timer_list *unused)
  48. {
  49. struct sk_buff *skb;
  50. struct net_device *dev;
  51. rose_address *dest;
  52. struct sock *sk;
  53. unsigned short frametype;
  54. unsigned int lci_i, lci_o;
  55. int count;
  56. for (count = 0; count < ROSE_LOOPBACK_LIMIT; count++) {
  57. skb = skb_dequeue(&loopback_queue);
  58. if (!skb)
  59. return;
  60. if (skb->len < ROSE_MIN_LEN) {
  61. kfree_skb(skb);
  62. continue;
  63. }
  64. lci_i = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF);
  65. frametype = skb->data[2];
  66. if (frametype == ROSE_CALL_REQUEST &&
  67. (skb->len <= ROSE_CALL_REQ_FACILITIES_OFF ||
  68. skb->data[ROSE_CALL_REQ_ADDR_LEN_OFF] !=
  69. ROSE_CALL_REQ_ADDR_LEN_VAL)) {
  70. kfree_skb(skb);
  71. continue;
  72. }
  73. dest = (rose_address *)(skb->data + ROSE_CALL_REQ_DEST_ADDR_OFF);
  74. lci_o = ROSE_DEFAULT_MAXVC + 1 - lci_i;
  75. skb_reset_transport_header(skb);
  76. sk = rose_find_socket(lci_o, rose_loopback_neigh);
  77. if (sk) {
  78. if (rose_process_rx_frame(sk, skb) == 0)
  79. kfree_skb(skb);
  80. continue;
  81. }
  82. if (frametype == ROSE_CALL_REQUEST) {
  83. if (!rose_loopback_neigh->dev &&
  84. !rose_loopback_neigh->loopback) {
  85. kfree_skb(skb);
  86. continue;
  87. }
  88. dev = rose_dev_get(dest);
  89. if (!dev) {
  90. kfree_skb(skb);
  91. continue;
  92. }
  93. if (rose_rx_call_request(skb, dev, rose_loopback_neigh, lci_o) == 0) {
  94. dev_put(dev);
  95. kfree_skb(skb);
  96. }
  97. } else {
  98. kfree_skb(skb);
  99. }
  100. }
  101. if (!skb_queue_empty(&loopback_queue))
  102. mod_timer(&loopback_timer, jiffies + 1);
  103. }
  104. void __exit rose_loopback_clear(void)
  105. {
  106. struct sk_buff *skb;
  107. del_timer(&loopback_timer);
  108. while ((skb = skb_dequeue(&loopback_queue)) != NULL) {
  109. skb->sk = NULL;
  110. kfree_skb(skb);
  111. }
  112. }