NDPServer.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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/NDPServer.h"
  17. #include "util/Bits.h"
  18. #include "util/Checksum.h"
  19. #include "util/Identity.h"
  20. #include "wire/Message.h"
  21. #include "wire/Ethernet.h"
  22. #include "wire/Headers.h"
  23. #include "wire/NDPHeader.h"
  24. #include <stdbool.h>
  25. struct NDPServer_pvt
  26. {
  27. struct NDPServer pub;
  28. struct Iface external;
  29. struct Log* log;
  30. uint8_t localMac[Ethernet_ADDRLEN];
  31. Identity
  32. };
  33. #define MULTICAST_ADDR "\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff\x00\x00\x08"
  34. // ff 02 00 00 00 00 00 00 00 00 00 01 ff 00 00 02 870099
  35. #define UNICAST_ADDR "\xfe\x80\0\0\0\0\0\0\0\0\0\0\0\0\0\x08"
  36. //#define UNICAST_ADDR "\xfd\x80\0\0\0\0\0\0\0\0\0\0\0\0\0\x08"
  37. #define ALL_ROUTERS "\xff\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\x02"
  38. static bool isNeighborSolicitation(struct Message* msg, struct NDPServer_pvt* ns)
  39. {
  40. if (msg->length < Headers_IP6Header_SIZE + NDPHeader_NeighborSolicitation_SIZE) {
  41. return false;
  42. }
  43. struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) msg->bytes;
  44. struct NDPHeader_NeighborSolicitation* sol = (struct NDPHeader_NeighborSolicitation*) &ip6[1];
  45. if (sol->oneThirtyFive != 135 || sol->zero != 0) {
  46. Log_debug(ns->log, "wrong type/code for neighbor solicitation");
  47. return false;
  48. }
  49. if (//Bits_memcmp(ip6->destinationAddr, UNICAST_ADDR, 16) ||
  50. Bits_memcmp(ip6->destinationAddr, MULTICAST_ADDR, 13))
  51. {
  52. Log_debug(ns->log, "wrong address for neighbor solicitation");
  53. return false;
  54. }
  55. /*if (Bits_memcmp(sol->targetAddr, UNICAST_ADDR, 16)) {
  56. Log_debug(ns->log, "Soliciting the wrong neighbor");
  57. return false;
  58. }*/
  59. return true;
  60. }
  61. static Iface_DEFUN answerNeighborSolicitation(struct Message* msg, struct NDPServer_pvt* ns)
  62. {
  63. struct Headers_IP6Header ip6;
  64. Message_pop(msg, &ip6, Headers_IP6Header_SIZE, NULL);
  65. struct NDPHeader_NeighborSolicitation sol;
  66. Message_pop(msg, &sol, NDPHeader_NeighborSolicitation_SIZE, NULL);
  67. Assert_true(!msg->length);
  68. struct NDPHeader_MacOpt macOpt = {
  69. .type = NDPHeader_MacOpt_type_TARGET,
  70. .one = 1
  71. };
  72. Bits_memcpyConst(macOpt.mac, ns->localMac, Ethernet_ADDRLEN);
  73. Message_push(msg, &macOpt, sizeof(struct NDPHeader_MacOpt), NULL);
  74. struct NDPHeader_NeighborAdvert na = {
  75. .oneThirtySix = 136,
  76. .zero = 0,
  77. .checksum = 0,
  78. .bits = NDPHeader_NeighborAdvert_bits_ROUTER
  79. | NDPHeader_NeighborAdvert_bits_SOLICITED
  80. | NDPHeader_NeighborAdvert_bits_OVERRIDE
  81. };
  82. Bits_memcpyConst(na.targetAddr, sol.targetAddr, 16);
  83. Message_push(msg, &na, sizeof(struct NDPHeader_NeighborAdvert), NULL);
  84. Bits_memcpyConst(ip6.destinationAddr, ip6.sourceAddr, 16);
  85. Bits_memcpyConst(ip6.sourceAddr, sol.targetAddr, 16);
  86. ip6.hopLimit = 255;
  87. ip6.payloadLength_be = Endian_hostToBigEndian16(msg->length);
  88. struct NDPHeader_RouterAdvert* adv = (struct NDPHeader_RouterAdvert*) msg->bytes;
  89. adv->checksum = Checksum_icmp6(ip6.sourceAddr, msg->bytes, msg->length);
  90. Message_push(msg, &ip6, sizeof(struct Headers_IP6Header), NULL);
  91. TUNMessageType_push(msg, Ethernet_TYPE_IP6, NULL);
  92. Log_debug(ns->log, "Sending neighbor advert");
  93. return Iface_next(&ns->external, msg);
  94. }
  95. static Iface_DEFUN receiveMessage(struct Message* msg, struct Iface* external)
  96. {
  97. struct NDPServer_pvt* ns = Identity_containerOf(external, struct NDPServer_pvt, external);
  98. if (msg->length > Headers_IP6Header_SIZE + 4) {
  99. uint16_t ethertype = TUNMessageType_pop(msg, NULL);
  100. if (ethertype != Ethernet_TYPE_IP6) {
  101. } else if (isNeighborSolicitation(msg, ns)) {
  102. return answerNeighborSolicitation(msg, ns);
  103. }
  104. TUNMessageType_push(msg, ethertype, NULL);
  105. }
  106. return Iface_next(&ns->pub.internal, msg);
  107. }
  108. static Iface_DEFUN sendMessage(struct Message* msg, struct Iface* internal)
  109. {
  110. struct NDPServer_pvt* ns = Identity_containerOf(internal, struct NDPServer_pvt, pub.internal);
  111. return Iface_next(&ns->external, msg);
  112. }
  113. struct NDPServer* NDPServer_new(struct Iface* external,
  114. struct Log* log,
  115. uint8_t localMac[Ethernet_ADDRLEN],
  116. struct Allocator* alloc)
  117. {
  118. struct NDPServer_pvt* out = Allocator_calloc(alloc, sizeof(struct NDPServer_pvt), 1);
  119. Identity_set(out);
  120. out->external.send = receiveMessage;
  121. Iface_plumb(&out->external, external);
  122. out->pub.internal.send = sendMessage;
  123. out->log = log;
  124. Bits_memcpyConst(out->localMac, localMac, Ethernet_ADDRLEN);
  125. return &out->pub;
  126. }