ICMP6Generator.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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/ICMP6Generator_pvt.h"
  16. #include "util/Checksum.h"
  17. #include "util/Bits.h"
  18. #include "util/log/Log.h"
  19. #include "wire/Headers.h"
  20. #include "wire/Error.h"
  21. #include <stddef.h>
  22. #include <stdbool.h>
  23. /** MTU at switch layer, not including switch header overhead. */
  24. #define EXPECTED_MTU \
  25. (1492 /* PPPoE */ \
  26. - Headers_IP4Header_SIZE \
  27. - Headers_UDPHeader_SIZE \
  28. - 20 /* CryptoAuth in ESTABLISHED state. */ )
  29. #define CJDNS_OVERHEAD \
  30. (Headers_SwitchHeader_SIZE \
  31. + 4 /* handle */ \
  32. + Headers_CryptoAuth_SIZE \
  33. /* IPv6 header goes here but operating system subtracts it. */ \
  34. + Headers_CryptoAuth_SIZE)
  35. static inline uint8_t numForType(enum ICMP6Generator_Type type)
  36. {
  37. switch (type) {
  38. case ICMP6Generator_Type_NO_ROUTE_TO_HOST: return 1; /* ICMPV6_DEST_UNREACH */
  39. case ICMP6Generator_Type_PACKET_TOO_BIG: return 2; /* ICMPV6_PKT_TOOBIG */
  40. default: return 0;
  41. }
  42. }
  43. /**
  44. * Generate an ICMPv6 message.
  45. * The message parameter must contain all content which will be beneath the ICMPv6 header
  46. * including the MTU in the case of a "packet too big" message.
  47. *
  48. * @param message a message containing the content. This message must have enough padding
  49. * to contain an additional ICMP header and IPv6 header totaling 44 bytes.
  50. * @param sourceAddr the IPv6 address which this ICMP message will be said to have come from.
  51. * @param destAddr the IPv6 address which this ICMP message will be directed to.
  52. * @param type the ICMP message type/code for this message.
  53. * @param mtu the MTU value for this message.
  54. */
  55. void ICMP6Generator_generate(struct Message* msg,
  56. const uint8_t* restrict sourceAddr,
  57. const uint8_t* restrict destAddr,
  58. enum ICMP6Generator_Type type,
  59. uint32_t mtu)
  60. {
  61. Message_shift(msg, Headers_ICMP6Header_SIZE);
  62. struct Headers_ICMP6Header* icmp6 = (struct Headers_ICMP6Header*) msg->bytes;
  63. Message_shift(msg, Headers_IP6Header_SIZE);
  64. struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) msg->bytes;
  65. if (ICMP6Generator_MIN_IPV6_MTU < msg->length) {
  66. msg->length = ICMP6Generator_MIN_IPV6_MTU;
  67. }
  68. uint16_t contentLen = msg->length - Headers_IP6Header_SIZE;
  69. icmp6->type = numForType(type);
  70. icmp6->code = 0;
  71. icmp6->checksum = 0;
  72. icmp6->additional = Endian_hostToBigEndian32(mtu);
  73. ip6->versionClassAndFlowLabel = 0;
  74. Headers_setIpVersion(ip6);
  75. ip6->flowLabelLow_be = 0;
  76. ip6->payloadLength_be = Endian_hostToBigEndian16(contentLen);
  77. ip6->nextHeader = 58; /* IPPROTO_ICMPV6 */
  78. ip6->hopLimit = 64;
  79. Bits_memcpyConst(ip6->sourceAddr, sourceAddr, 16);
  80. Bits_memcpyConst(ip6->destinationAddr, destAddr, 16);
  81. icmp6->checksum = Checksum_icmp6(ip6->sourceAddr, (uint8_t*)icmp6, contentLen);
  82. }
  83. static uint8_t sendFragmented(struct ICMP6Generator_pvt* ctx,
  84. struct Message* msg,
  85. uint32_t mtu,
  86. int offsetBytes)
  87. {
  88. uint64_t msgHeader[(Headers_IP6Header_SIZE + Headers_IP6Fragment_SIZE) / 8];
  89. Assert_true(msg->length > (int)sizeof(msgHeader));
  90. Bits_memcpyConst(msgHeader, msg->bytes, sizeof(msgHeader));
  91. const int headersSize = (Headers_IP6Header_SIZE + Headers_IP6Fragment_SIZE);
  92. struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) msg->bytes;
  93. struct Headers_IP6Fragment* frag = (struct Headers_IP6Fragment*) (&ip6[1]);
  94. Message_shift(msg, -headersSize);
  95. // prepare next message.
  96. struct Message* nextMessage = &(struct Message) {
  97. .bytes = msg->bytes,
  98. .length = msg->length,
  99. .padding = msg->padding
  100. };
  101. int nextMessageOffsetBytes = offsetBytes + (((mtu - headersSize) / 8) * 8);
  102. Message_shift(nextMessage, -(nextMessageOffsetBytes - offsetBytes));
  103. msg->length -= nextMessage->length;
  104. ip6->payloadLength_be = Endian_hostToBigEndian16(msg->length + Headers_IP6Fragment_SIZE);
  105. Message_shift(msg, headersSize);
  106. // sanity check
  107. Assert_true(!Bits_memcmp(&msg->bytes[msg->length], nextMessage->bytes, 8));
  108. uint64_t msgNextPartFirstLong = ((uint64_t*)nextMessage->bytes)[0];
  109. // Set the required fields.
  110. // RFC-2460 includes the fragment header in the offset so we have to add another 8 bytes.
  111. Headers_IP6Fragment_setOffset(frag, offsetBytes / 8);
  112. Headers_IP6Fragment_setMoreFragments(frag, true);
  113. Interface_receiveMessage(&ctx->pub.internal, msg);
  114. // sanity check
  115. Assert_true(!Bits_memcmp(&msgNextPartFirstLong, nextMessage->bytes, 8));
  116. Message_shift(nextMessage, sizeof(msgHeader));
  117. Bits_memcpyConst(nextMessage->bytes, msgHeader, sizeof(msgHeader));
  118. if (nextMessage->length > (int)mtu) {
  119. return sendFragmented(ctx, nextMessage, mtu, nextMessageOffsetBytes);
  120. }
  121. // Set the required fields for the last fragment.
  122. ip6 = (struct Headers_IP6Header*) nextMessage->bytes;
  123. frag = (struct Headers_IP6Fragment*) (nextMessage->bytes + Headers_IP6Header_SIZE);
  124. Headers_IP6Fragment_setOffset(frag, nextMessageOffsetBytes / 8);
  125. // If the kernel did some fragmentation of it's own, we don't want to set the "last fragment"
  126. // flag so we'll leave it as it is.
  127. //Headers_IP6Fragment_setMoreFragments(frag, false);
  128. ip6->payloadLength_be = Endian_hostToBigEndian16(nextMessage->length - Headers_IP6Header_SIZE);
  129. return Interface_receiveMessage(&ctx->pub.internal, nextMessage);
  130. }
  131. /** Message from the external (TUN facing) interface. */
  132. static uint8_t incoming(struct Message* msg, struct Interface* iface)
  133. {
  134. struct ICMP6Generator_pvt* ctx =
  135. Identity_cast((struct ICMP6Generator_pvt*)
  136. (((uint8_t*)iface) - offsetof(struct ICMP6Generator, external)));
  137. // TODO calculate this on a per-node basis.
  138. int mtu = ctx->mtu;
  139. // source address for packets coming from the router.
  140. const uint8_t magicAddr[] = { 0xfc,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 };
  141. struct Headers_IP6Header* header = (struct Headers_IP6Header*) msg->bytes;
  142. if (msg->length >= Headers_IP6Header_SIZE
  143. && Headers_getIpVersion(header) == 6
  144. && msg->length > mtu)
  145. {
  146. if (header->nextHeader == Headers_IP6Fragment_TYPE) {
  147. return sendFragmented(ctx, msg, mtu, 0);
  148. }
  149. uint8_t destAddr[16];
  150. Bits_memcpyConst(destAddr, header->sourceAddr, 16);
  151. ICMP6Generator_generate(msg,
  152. magicAddr,
  153. destAddr,
  154. ICMP6Generator_Type_PACKET_TOO_BIG,
  155. mtu);
  156. Interface_receiveMessage(&ctx->pub.external, msg);
  157. return Error_NONE;
  158. }
  159. return Interface_receiveMessage(&ctx->pub.internal, msg);
  160. }
  161. /** Message from the internal (Ducttape facing) interface. */
  162. static uint8_t outgoing(struct Message* msg, struct Interface* iface)
  163. {
  164. struct ICMP6Generator_pvt* ctx =
  165. Identity_cast((struct ICMP6Generator_pvt*)
  166. (((uint8_t*)iface) - offsetof(struct ICMP6Generator, internal)));
  167. return Interface_receiveMessage(&ctx->pub.external, msg);
  168. }
  169. struct ICMP6Generator* ICMP6Generator_new(struct Allocator* alloc)
  170. {
  171. struct ICMP6Generator_pvt* out = Allocator_clone(alloc, (&(struct ICMP6Generator_pvt) {
  172. .pub = {
  173. .external = {
  174. .sendMessage = incoming
  175. },
  176. .internal = {
  177. .sendMessage = outgoing
  178. }
  179. },
  180. .mtu = EXPECTED_MTU - CJDNS_OVERHEAD
  181. }));
  182. Identity_set(out);
  183. return &out->pub;
  184. }