1
0

TUNTools.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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 <https://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/Er.h"
  19. #include "util/events/Timeout.h"
  20. #include "wire/Ethernet.h"
  21. #include "wire/Headers.h"
  22. #include "wire/Error.h"
  23. #ifdef win32
  24. #include <windows.h>
  25. #define sleep(x) Sleep(1000*x)
  26. #else
  27. #include <unistd.h>
  28. #endif
  29. static AddrIface_t* setupUDP(EventBase_t* base,
  30. struct Sockaddr* bindAddr,
  31. struct Allocator* allocator,
  32. struct Log* logger)
  33. {
  34. // Mac OSX and BSD do not set up their TUN devices synchronously.
  35. // We'll just keep on trying until this works.
  36. struct UDPAddrIface* udp = NULL;
  37. struct Er_Ret* er = NULL;
  38. for (int i = 0; i < 20; i++) {
  39. udp = Er_check(&er, UDPAddrIface_new(base, bindAddr, allocator, logger));
  40. if (udp) {
  41. break;
  42. }
  43. sleep(1);
  44. }
  45. Assert_true(udp);
  46. return &udp->generic;
  47. }
  48. struct TUNTools_pvt
  49. {
  50. struct TUNTools pub;
  51. Identity
  52. };
  53. static void sendHello(void* vctx)
  54. {
  55. struct TUNTools_pvt* ctx = Identity_check((struct TUNTools_pvt*) vctx);
  56. struct Allocator* tempAlloc = Allocator_child(ctx->pub.alloc);
  57. Message_t* msg = Message_new(0, 64, tempAlloc);
  58. Er_assert(Message_epush(msg, "Hello World", 12));
  59. Er_assert(Message_epush(msg, ctx->pub.tunDestAddr, ctx->pub.tunDestAddr->addrLen));
  60. Iface_send(&ctx->pub.udpIface, msg);
  61. Allocator_free(tempAlloc);
  62. }
  63. const uint8_t* TUNTools_testIP6AddrA = (uint8_t[])
  64. {
  65. 0xfd,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
  66. };
  67. const uint8_t* TUNTools_testIP6AddrB = (uint8_t[])
  68. {
  69. 0xfd,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
  70. };
  71. const uint8_t* TUNTools_testIP6AddrC = (uint8_t[])
  72. {
  73. 0xfd,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5
  74. };
  75. Iface_DEFUN TUNTools_genericIP6Echo(Message_t* msg, struct TUNTools* tt)
  76. {
  77. uint16_t ethertype = Er_assert(TUNMessageType_pop(msg));
  78. if (ethertype != Ethernet_TYPE_IP6) {
  79. Log_debug(tt->log, "Spurious packet with ethertype [%04x]\n",
  80. Endian_bigEndianToHost16(ethertype));
  81. return Error(msg, "INVALID");
  82. }
  83. struct Headers_IP6Header* header = (struct Headers_IP6Header*) Message_bytes(msg);
  84. if (Message_getLength(msg) != Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE + 12) {
  85. int type = (Message_getLength(msg) >= Headers_IP6Header_SIZE) ? header->nextHeader : -1;
  86. Log_debug(tt->log, "Message of unexpected length [%u] ip6->nextHeader: [%d]\n",
  87. Message_getLength(msg), type);
  88. return Error(msg, "INVALID");
  89. }
  90. uint8_t* address;
  91. Sockaddr_getAddress(tt->tunDestAddr, &address);
  92. Assert_true(!Bits_memcmp(header->destinationAddr, address, 16));
  93. Sockaddr_getAddress(tt->udpBindTo, &address);
  94. Assert_true(!Bits_memcmp(header->sourceAddr, address, 16));
  95. Sockaddr_getAddress(tt->udpBindTo, &address);
  96. Bits_memcpy(header->destinationAddr, address, 16);
  97. Sockaddr_getAddress(tt->tunDestAddr, &address);
  98. Bits_memcpy(header->sourceAddr, address, 16);
  99. Er_assert(TUNMessageType_push(msg, ethertype));
  100. return Iface_next(&tt->tunIface, msg);
  101. }
  102. static Iface_DEFUN receiveMessageTUN(Message_t* msg, struct Iface* tunIface)
  103. {
  104. struct TUNTools_pvt* ctx = Identity_containerOf(tunIface, struct TUNTools_pvt, pub.tunIface);
  105. ctx->pub.receivedMessageTUNCount++;
  106. return ctx->pub.cb(msg, &ctx->pub);
  107. }
  108. static Iface_DEFUN receiveMessageUDP(Message_t* msg, struct Iface* udpIface)
  109. {
  110. struct TUNTools_pvt* ctx = Identity_containerOf(udpIface, struct TUNTools_pvt, pub.udpIface);
  111. if (ctx->pub.receivedMessageTUNCount) {
  112. Log_debug(ctx->pub.log, "test complete");
  113. // Got the message, test successful, tear everything down by freeing the root alloc.
  114. EventBase_endLoop(ctx->pub.base);
  115. }
  116. return NULL;
  117. }
  118. static void fail(void* ignored)
  119. {
  120. Assert_true(!"timeout");
  121. }
  122. void TUNTools_echoTest(struct Sockaddr* udpBindTo,
  123. struct Sockaddr* tunDestAddr,
  124. TUNTools_Callback tunMessageHandler,
  125. struct Iface* tun,
  126. EventBase_t* base,
  127. struct Log* logger,
  128. struct Allocator* allocator)
  129. {
  130. struct Allocator* alloc = Allocator_child(allocator);
  131. AddrIface_t* udp = setupUDP(base, udpBindTo, alloc, logger);
  132. struct Sockaddr* dest = Sockaddr_clone(udp->addr, alloc);
  133. uint8_t* tunDestAddrBytes = NULL;
  134. uint8_t* udpDestPointer = NULL;
  135. int len = Sockaddr_getAddress(dest, &udpDestPointer);
  136. Assert_true(len && len == Sockaddr_getAddress(tunDestAddr, &tunDestAddrBytes));
  137. Bits_memcpy(udpDestPointer, tunDestAddrBytes, len);
  138. struct TUNTools_pvt* ctx = Allocator_calloc(alloc, sizeof(struct TUNTools_pvt), 1);
  139. Identity_set(ctx);
  140. ctx->pub.udpIface.send = receiveMessageUDP;
  141. ctx->pub.tunIface.send = receiveMessageTUN;
  142. Iface_plumb(&ctx->pub.udpIface, udp->iface);
  143. Iface_plumb(&ctx->pub.tunIface, tun);
  144. ctx->pub.cb = tunMessageHandler;
  145. ctx->pub.tunDestAddr = Sockaddr_clone(dest, alloc);
  146. ctx->pub.udpBindTo = Sockaddr_clone(udpBindTo, alloc);
  147. ctx->pub.alloc = alloc;
  148. ctx->pub.log = logger;
  149. ctx->pub.base = base;
  150. Timeout_setInterval(sendHello, ctx, 1000, base, alloc);
  151. Timeout_setTimeout(fail, NULL, 10000, base, alloc);
  152. EventBase_beginLoop(base);
  153. }