TUNTools.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "interface/tuntap/TUNMessageType.h"
  16. #include "interface/tuntap/test/TUNTools.h"
  17. #include "util/events/UDPAddrIface.h"
  18. #include "exception/Jmp.h"
  19. #include "util/events/Timeout.h"
  20. #include "wire/Ethernet.h"
  21. #include "wire/Headers.h"
  22. #ifdef win32
  23. #include <windows.h>
  24. #define sleep(x) Sleep(1000*x)
  25. #else
  26. #include <unistd.h>
  27. #endif
  28. static struct AddrIface* setupUDP2(struct EventBase* base,
  29. struct Sockaddr* bindAddr,
  30. struct Allocator* allocator,
  31. struct Log* logger)
  32. {
  33. struct Jmp jmp;
  34. Jmp_try(jmp) {
  35. struct UDPAddrIface* ua = UDPAddrIface_new(base, bindAddr, allocator, &jmp.handler, logger);
  36. return &ua->generic;
  37. } Jmp_catch {
  38. sleep(1);
  39. return NULL;
  40. }
  41. }
  42. static struct AddrIface* setupUDP(struct EventBase* base,
  43. struct Sockaddr* bindAddr,
  44. struct Allocator* allocator,
  45. struct Log* logger)
  46. {
  47. // Mac OSX and BSD do not set up their TUN devices synchronously.
  48. // We'll just keep on trying until this works.
  49. struct AddrIface* udp = NULL;
  50. for (int i = 0; i < 20; i++) {
  51. if ((udp = setupUDP2(base, bindAddr, allocator, logger))) {
  52. break;
  53. }
  54. }
  55. Assert_true(udp);
  56. return udp;
  57. }
  58. struct TUNTools_pvt
  59. {
  60. struct TUNTools pub;
  61. Identity
  62. };
  63. static void sendHello(void* vctx)
  64. {
  65. struct TUNTools_pvt* ctx = Identity_check((struct TUNTools_pvt*) vctx);
  66. struct Allocator* tempAlloc = Allocator_child(ctx->pub.alloc);
  67. struct Message* msg = Message_new(0, 64, tempAlloc);
  68. Message_push(msg, "Hello World", 12, NULL);
  69. Message_push(msg, ctx->pub.tunDestAddr, ctx->pub.tunDestAddr->addrLen, NULL);
  70. Iface_send(&ctx->pub.udpIface, msg);
  71. Allocator_free(tempAlloc);
  72. }
  73. const uint8_t* TUNTools_testIP6AddrA = (uint8_t[])
  74. {
  75. 0xfd,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
  76. };
  77. const uint8_t* TUNTools_testIP6AddrB = (uint8_t[])
  78. {
  79. 0xfd,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
  80. };
  81. Iface_DEFUN TUNTools_genericIP6Echo(struct Message* msg, struct TUNTools* tt)
  82. {
  83. uint16_t ethertype = TUNMessageType_pop(msg, NULL);
  84. if (ethertype != Ethernet_TYPE_IP6) {
  85. Log_debug(tt->log, "Spurious packet with ethertype [%04x]\n",
  86. Endian_bigEndianToHost16(ethertype));
  87. return 0;
  88. }
  89. struct Headers_IP6Header* header = (struct Headers_IP6Header*) msg->bytes;
  90. if (msg->length != Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE + 12) {
  91. int type = (msg->length >= Headers_IP6Header_SIZE) ? header->nextHeader : -1;
  92. Log_debug(tt->log, "Message of unexpected length [%u] ip6->nextHeader: [%d]\n",
  93. msg->length, type);
  94. return 0;
  95. }
  96. Assert_true(!Bits_memcmp(header->destinationAddr, TUNTools_testIP6AddrB, 16));
  97. Assert_true(!Bits_memcmp(header->sourceAddr, TUNTools_testIP6AddrA, 16));
  98. Bits_memcpyConst(header->destinationAddr, TUNTools_testIP6AddrA, 16);
  99. Bits_memcpyConst(header->sourceAddr, TUNTools_testIP6AddrB, 16);
  100. TUNMessageType_push(msg, ethertype, NULL);
  101. return Iface_next(&tt->tunIface, msg);
  102. }
  103. static Iface_DEFUN receiveMessageTUN(struct Message* msg, struct Iface* tunIface)
  104. {
  105. struct TUNTools_pvt* ctx = Identity_containerOf(tunIface, struct TUNTools_pvt, pub.tunIface);
  106. ctx->pub.receivedMessageTUNCount++;
  107. return ctx->pub.cb(msg, &ctx->pub);
  108. }
  109. static Iface_DEFUN receiveMessageUDP(struct Message* msg, struct Iface* udpIface)
  110. {
  111. struct TUNTools_pvt* ctx = Identity_containerOf(udpIface, struct TUNTools_pvt, pub.udpIface);
  112. if (ctx->pub.receivedMessageTUNCount) {
  113. Log_debug(ctx->pub.log, "test complete");
  114. // Got the message, test successful, tear everything down by freeing the root alloc.
  115. EventBase_endLoop(ctx->pub.base);
  116. }
  117. return NULL;
  118. }
  119. static void fail(void* ignored)
  120. {
  121. Assert_true(!"timeout");
  122. }
  123. void TUNTools_echoTest(struct Sockaddr* udpBindTo,
  124. struct Sockaddr* tunDestAddr,
  125. TUNTools_Callback tunMessageHandler,
  126. struct Iface* tun,
  127. struct EventBase* base,
  128. struct Log* logger,
  129. struct Allocator* allocator)
  130. {
  131. struct Allocator* alloc = Allocator_child(allocator);
  132. struct AddrIface* udp = setupUDP(base, udpBindTo, alloc, logger);
  133. struct Sockaddr* dest = Sockaddr_clone(udp->addr, alloc);
  134. uint8_t* tunDestAddrBytes = NULL;
  135. uint8_t* udpDestPointer = NULL;
  136. int len = Sockaddr_getAddress(dest, &udpDestPointer);
  137. Assert_true(len && len == Sockaddr_getAddress(tunDestAddr, &tunDestAddrBytes));
  138. Bits_memcpy(udpDestPointer, tunDestAddrBytes, len);
  139. struct TUNTools_pvt* ctx = Allocator_calloc(alloc, sizeof(struct TUNTools_pvt), 1);
  140. Identity_set(ctx);
  141. ctx->pub.udpIface.send = receiveMessageUDP;
  142. ctx->pub.tunIface.send = receiveMessageTUN;
  143. Iface_plumb(&ctx->pub.udpIface, &udp->iface);
  144. Iface_plumb(&ctx->pub.tunIface, tun);
  145. ctx->pub.cb = tunMessageHandler;
  146. ctx->pub.tunDestAddr = Sockaddr_clone(dest, alloc);
  147. ctx->pub.udpBindTo = Sockaddr_clone(udpBindTo, alloc);
  148. ctx->pub.alloc = alloc;
  149. ctx->pub.log = logger;
  150. ctx->pub.base = base;
  151. Timeout_setInterval(sendHello, ctx, 1000, base, alloc);
  152. Timeout_setTimeout(fail, NULL, 10000, base, alloc);
  153. EventBase_beginLoop(base);
  154. }