1
0

ARPServer.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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/ARPServer.h"
  17. #include "interface/Iface.h"
  18. #include "memory/Allocator.h"
  19. #include "util/Bits.h"
  20. #include "util/log/Log.h"
  21. #include "util/Identity.h"
  22. #include "util/Endian.h"
  23. #include "wire/ARPHeader.h"
  24. #include "wire/Ethernet.h"
  25. #include <stdbool.h>
  26. struct ARPServer_pvt
  27. {
  28. struct ARPServer pub;
  29. struct Iface external;
  30. struct Log* log;
  31. uint8_t localMac[Ethernet_ADDRLEN];
  32. Identity
  33. };
  34. static bool isValidARP(struct Message* msg)
  35. {
  36. struct ARPHeader_6_4 arp;
  37. Message_pop(msg, &arp, ARPHeader_6_4_SIZE, NULL);
  38. Message_shift(msg, ARPHeader_6_4_SIZE, NULL); // Get copy and restore.
  39. if (!ARPHeader_isEthIP4(&arp.prefix)) {
  40. return false; // not ARP.
  41. }
  42. if (arp.prefix.operation != ARPHeader_OP_Q) {
  43. return false; // Not question.
  44. }
  45. if (Bits_memcmp(arp.spa, arp.tpa, 4) == 0) {
  46. return false; // not really ARP question.
  47. }
  48. if (Bits_isZero(arp.spa, 4)) {
  49. return false; // "I am just checking if this IP is not taken."
  50. }
  51. return true;
  52. }
  53. static Iface_DEFUN answerARP(struct Message* msg, struct ARPServer_pvt* as)
  54. {
  55. struct ARPHeader_6_4 arp;
  56. Message_pop(msg, &arp, ARPHeader_6_4_SIZE, NULL);
  57. if (msg->length) {
  58. Log_warn(as->log, "%d extra bytes in ARP, weird", msg->length);
  59. }
  60. // Swap sender with target.
  61. // 10 = Eth_Len + IP4_Len
  62. uint8_t tmp[10];
  63. Bits_memcpy(tmp, arp.sha, 10);
  64. Bits_memcpy(arp.sha, arp.tha, 10);
  65. Bits_memcpy(arp.tha, tmp, 10);
  66. // Set our MAC as source
  67. Bits_memcpy(arp.sha, as->localMac, Ethernet_ADDRLEN);
  68. // Set answer opcode.
  69. arp.prefix.operation = ARPHeader_OP_A;
  70. Message_push(msg, &arp, ARPHeader_6_4_SIZE, NULL);
  71. TUNMessageType_push(msg, Ethernet_TYPE_ARP, NULL);
  72. Log_debug(as->log, "Sending ARP answer.");
  73. return Iface_next(&as->external, msg);
  74. }
  75. static Iface_DEFUN receiveMessage(struct Message* msg, struct Iface* external)
  76. {
  77. struct ARPServer_pvt* as = Identity_containerOf(external, struct ARPServer_pvt, external);
  78. // Length should be ARP + Ethertype
  79. if (msg->length >= ARPHeader_6_4_SIZE + 4) {
  80. uint16_t ethertype = TUNMessageType_pop(msg, NULL);
  81. if (ethertype == Ethernet_TYPE_ARP) {
  82. if (isValidARP(msg)) {
  83. return answerARP(msg, as);
  84. }
  85. }
  86. TUNMessageType_push(msg, ethertype, NULL);
  87. }
  88. return Iface_next(&as->pub.internal, msg);
  89. }
  90. static Iface_DEFUN sendMessage(struct Message* msg, struct Iface* internal)
  91. {
  92. struct ARPServer_pvt* as = Identity_containerOf(internal, struct ARPServer_pvt, pub.internal);
  93. return Iface_next(&as->external, msg);
  94. }
  95. struct ARPServer* ARPServer_new(struct Iface* external,
  96. struct Log* log,
  97. uint8_t localMac[Ethernet_ADDRLEN],
  98. struct Allocator* alloc)
  99. {
  100. struct ARPServer_pvt* out = Allocator_calloc(alloc, sizeof(struct ARPServer_pvt), 1);
  101. Identity_set(out);
  102. out->external.send = receiveMessage;
  103. Iface_plumb(&out->external, external);
  104. out->pub.internal.send = sendMessage;
  105. out->log = log;
  106. Bits_memcpy(out->localMac, localMac, Ethernet_ADDRLEN);
  107. return &out->pub;
  108. }