diff --git a/include/arp.h b/include/arp.h new file mode 100644 index 0000000..941b8ad --- /dev/null +++ b/include/arp.h @@ -0,0 +1,43 @@ +#ifndef __ARP_H +#define __ARP_H + + +#include +#include "pdu.h" + +namespace Tins { + + class ARP : public PDU { + public: + enum Flags { + REQUEST = 0x0100, + REPLY = 0x0200 + }; + + ARP(); + + void set_arp_request(const std::string &ip_dst, const std::string &ip_src, const std::string &hw_src = ""); + + uint32_t header_size() const; + + bool send(PacketSender* sender); + private: + struct arphdr { + uint16_t ar_hrd; /* format of hardware address */ + uint16_t ar_pro; /* format of protocol address */ + uint8_t ar_hln; /* length of hardware address */ + uint8_t ar_pln; /* length of protocol address */ + uint16_t ar_op; /* ARP opcode (command) */ + + uint8_t ar_sha[6]; /* sender hardware address */ + uint32_t ar_sip; /* sender IP address */ + uint8_t ar_tha[6]; /* target hardware address */ + uint32_t ar_tip; /* target IP address */ + } __attribute__((packed)); + + void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent); + + arphdr _arp; + }; +}; +#endif diff --git a/src/arp.cpp b/src/arp.cpp new file mode 100644 index 0000000..ab33c38 --- /dev/null +++ b/src/arp.cpp @@ -0,0 +1,40 @@ +#include +#include +#include +#include "arp.h" +#include "utils.h" + + +using namespace std; + +Tins::ARP::ARP() : PDU(0x0608) { + std::memset(&_arp, 0, sizeof(arphdr)); + _arp.ar_hrd = 0x0100; + _arp.ar_pro = 0x0008; + _arp.ar_hln = 6; + _arp.ar_pln = 4; +} + +void Tins::ARP::set_arp_request(const string &ip_dst, const string &ip_src, const string &hw_src) { + _arp.ar_tip = Utils::resolve_ip(ip_dst); + _arp.ar_sip = Utils::resolve_ip(ip_src); +} + +uint32_t Tins::ARP::header_size() const { + return sizeof(arphdr); +} + +void Tins::ARP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) { + assert(total_sz >= sizeof(arphdr)); + memcpy(buffer, &_arp, sizeof(arphdr)); +} + +bool Tins::ARP::send(PacketSender* sender) { + struct sockaddr_in link_addr; + link_addr.sin_family = AF_INET; + link_addr.sin_port = 0; + link_addr.sin_addr.s_addr = _arp.ar_sip; + + return sender->send_l3(this, (struct sockaddr*)&link_addr, sizeof(link_addr), PacketSender::IP_SOCKET); +} +