PacketHeaderToUDPAddrIface.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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 "memory/Allocator.h"
  16. #include "interface/addressable/PacketHeaderToUDPAddrIface.h"
  17. #include "util/platform/Sockaddr.h"
  18. #include "util/Assert.h"
  19. #include "util/Identity.h"
  20. #include "util/Checksum.h"
  21. #include "wire/Headers.h"
  22. #include "wire/Message.h"
  23. #include "wire/Error.h"
  24. struct PacketHeaderToUDPAddrIface_pvt
  25. {
  26. struct PacketHeaderToUDPAddrIface pub;
  27. Identity
  28. };
  29. static Iface_DEFUN incomingFromUdpIf(struct Message* message, struct Iface* udpIf)
  30. {
  31. struct PacketHeaderToUDPAddrIface_pvt* context =
  32. Identity_containerOf(udpIf, struct PacketHeaderToUDPAddrIface_pvt, pub.udpIf.iface);
  33. struct Sockaddr_storage ss;
  34. Er_assert(Message_epop(message, &ss, context->pub.udpIf.addr->addrLen));
  35. struct Sockaddr* addr = &ss.addr;
  36. struct Headers_UDPHeader udp;
  37. udp.srcPort_be = Endian_hostToBigEndian16(Sockaddr_getPort(context->pub.udpIf.addr));
  38. udp.destPort_be = Endian_hostToBigEndian16(Sockaddr_getPort(addr));
  39. udp.length_be = Endian_hostToBigEndian16(message->length + Headers_UDPHeader_SIZE);
  40. udp.checksum_be = 0;
  41. Er_assert(Message_epush(message, &udp, sizeof(struct Headers_UDPHeader)));
  42. struct Headers_IP6Header ip = {
  43. .nextHeader = 17,
  44. .hopLimit = 255,
  45. };
  46. ip.payloadLength_be = Endian_hostToBigEndian16(message->length);
  47. Headers_setIpVersion(&ip);
  48. uint8_t* addrPtr = NULL;
  49. Assert_true(Sockaddr_getAddress(addr, &addrPtr) == 16);
  50. Bits_memcpy(ip.destinationAddr, addrPtr, 16);
  51. Assert_true(Sockaddr_getAddress(context->pub.udpIf.addr, &addrPtr) == 16);
  52. Bits_memcpy(ip.sourceAddr, addrPtr, 16);
  53. uint16_t checksum_be = Checksum_udpIp6_be(ip.sourceAddr, message->bytes, message->length);
  54. ((struct Headers_UDPHeader*)message->bytes)->checksum_be = checksum_be;
  55. Er_assert(Message_epush(message, &ip, sizeof(struct Headers_IP6Header)));
  56. return Iface_next(&context->pub.headerIf, message);
  57. }
  58. static Iface_DEFUN incomingFromHeaderIf(struct Message* message, struct Iface* iface)
  59. {
  60. struct PacketHeaderToUDPAddrIface_pvt* context =
  61. Identity_check((struct PacketHeaderToUDPAddrIface_pvt*)
  62. ((uint8_t*)(iface) - offsetof(struct PacketHeaderToUDPAddrIface, headerIf)));
  63. if (message->length < Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE) {
  64. // runt
  65. return NULL;
  66. }
  67. struct Headers_IP6Header* ip = (struct Headers_IP6Header*) message->bytes;
  68. // udp
  69. if (ip->nextHeader != 17) {
  70. return NULL;
  71. }
  72. struct Allocator* alloc = Allocator_child(message->alloc);
  73. struct Sockaddr* addr = Sockaddr_clone(context->pub.udpIf.addr, alloc);
  74. uint8_t* addrPtr = NULL;
  75. Assert_true(Sockaddr_getAddress(addr, &addrPtr) == 16);
  76. Bits_memcpy(addrPtr, ip->sourceAddr, 16);
  77. struct Headers_UDPHeader* udp = (struct Headers_UDPHeader*) (&ip[1]);
  78. Sockaddr_setPort(addr, Endian_bigEndianToHost16(udp->srcPort_be));
  79. if (Sockaddr_getPort(context->pub.udpIf.addr) != Endian_bigEndianToHost16(udp->destPort_be)) {
  80. // not the right port
  81. return NULL;
  82. }
  83. Er_assert(Message_eshift(message, -(Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE)));
  84. Er_assert(Message_epush(message, addr, addr->addrLen));
  85. return Iface_next(&context->pub.udpIf.iface, message);
  86. }
  87. struct PacketHeaderToUDPAddrIface* PacketHeaderToUDPAddrIface_new(struct Allocator* alloc,
  88. struct Sockaddr* addr)
  89. {
  90. struct PacketHeaderToUDPAddrIface_pvt* context =
  91. Allocator_calloc(alloc, sizeof(struct PacketHeaderToUDPAddrIface_pvt), 1);
  92. Identity_set(context);
  93. context->pub.udpIf.addr = Sockaddr_clone(addr, alloc);
  94. context->pub.udpIf.iface.send = incomingFromUdpIf;
  95. context->pub.headerIf.send = incomingFromHeaderIf;
  96. context->pub.udpIf.alloc = alloc;
  97. return &context->pub;
  98. }