diff --git a/include/arp.h b/include/arp.h index 5cab63d..6bddb83 100644 --- a/include/arp.h +++ b/include/arp.h @@ -28,6 +28,7 @@ #include "pdu.h" #include "ipaddress.h" #include "utils.h" +#include "hwaddress.h" namespace Tins { @@ -37,6 +38,8 @@ namespace Tins { */ class ARP : public PDU { public: + typedef HWAddress<6> hwaddress_type; + /** * \brief This PDU's flag. */ @@ -57,7 +60,8 @@ namespace Tins { * ARP::make_arp_request/reply static functions. */ ARP(IPv4Address target_ip = 0, IPv4Address sender_ip = 0, - const uint8_t *target_hw = 0, const uint8_t *sender_hw = 0); + const hwaddress_type &target_hw = hwaddress_type(), + const hwaddress_type &sender_hw = hwaddress_type()); /** * \brief Constructor which creates an ARP object from a buffer and adds all identifiable @@ -73,63 +77,63 @@ namespace Tins { * * \return Returns the sender's hardware address in an uint8_t*. */ - const uint8_t* sender_hw_addr() const { return this->_arp.ar_sha; } + hwaddress_type sender_hw_addr() const { return _arp.ar_sha; } /** * \brief Getter for the sender's IP address. * * \return Returns the sender's IP address in an uint32_t. */ - IPv4Address sender_ip_addr() const { return Utils::net_to_host_l(this->_arp.ar_sip); } + IPv4Address sender_ip_addr() const { return Utils::net_to_host_l(_arp.ar_sip); } /** * \brief Getter for the target's hardware address. * * \return Returns the target's hardware address in an uint8_t*. */ - const uint8_t* target_hw_addr() const { return this->_arp.ar_tha; } + hwaddress_type target_hw_addr() const { return _arp.ar_tha; } /** * \brief Getter for the target's IP address. * * \return Returns the target's IP address in an uint32_t. */ - IPv4Address target_ip_addr() const { return Utils::net_to_host_l(this->_arp.ar_tip); } + IPv4Address target_ip_addr() const { return Utils::net_to_host_l(_arp.ar_tip); } /** * \brief Getter for the hardware address format. * * \return Returns the hardware address' format in an uint16_t. */ - uint16_t hw_addr_format() const { return Utils::net_to_host_s(this->_arp.ar_hrd); } + uint16_t hw_addr_format() const { return Utils::net_to_host_s(_arp.ar_hrd); } /** * \brief Getter for the protocol address format. * * \return Returns the protocol address' format in an uint16_t. */ - uint16_t prot_addr_format() const { return Utils::net_to_host_s(this->_arp.ar_pro); } + uint16_t prot_addr_format() const { return Utils::net_to_host_s(_arp.ar_pro); } /** * \brief Getter for the hardware address length. * * \return Returns the hardware address' length in an uint8_t. */ - uint8_t hw_addr_length() const { return this->_arp.ar_hln; } + uint8_t hw_addr_length() const { return _arp.ar_hln; } /** * \brief Getter for the protocol address length. * * \return Returns the protocol address' length in an uint8_t. */ - uint8_t prot_addr_length() const { return this->_arp.ar_pln; } + uint8_t prot_addr_length() const { return _arp.ar_pln; } /** * \brief Getter for the ARP opcode. * * \return Returns the ARP opcode in an uint16_t. */ - uint16_t opcode() const { return Utils::net_to_host_s(this->_arp.ar_op); } + uint16_t opcode() const { return Utils::net_to_host_s(_arp.ar_op); } /** \brief Getter for the header size. * \return Returns the ARP header size. @@ -143,7 +147,7 @@ namespace Tins { * * \param new_snd_hw_addr uint8_t array containing the new sender's hardware address. */ - void sender_hw_addr(const uint8_t* new_snd_hw_addr); + void sender_hw_addr(const hwaddress_type &new_snd_hw_addr); /** * \brief Setter for the sender's IP address. @@ -157,7 +161,7 @@ namespace Tins { * * \param new_tgt_hw_addr uint8_t array containing the new target's hardware address. */ - void target_hw_addr(const uint8_t* new_tgt_hw_addr); + void target_hw_addr(const hwaddress_type &new_tgt_hw_addr); /** * \brief Setter for the target's IP address. @@ -220,7 +224,7 @@ namespace Tins { * \return Returns a PDU* to the new Layer 2 PDU containing the ARP Request. */ static PDU* make_arp_request(const std::string& iface, IPv4Address target, - IPv4Address sender, const uint8_t* hw_snd = 0); + IPv4Address sender, const hwaddress_type &hw_snd = hwaddress_type()); /** * \brief Creates an ARP Reply within a Layer 2 PDU using uint32_t for target and sender. @@ -236,32 +240,8 @@ namespace Tins { * \return Returns a PDU* to the new Layer 2 PDU containing the ARP Replay. */ static PDU* make_arp_reply(const std::string& iface, IPv4Address target, - IPv4Address sender, const uint8_t* hw_tgt, const uint8_t* hw_snd); - - /** - * \brief Converts the current ARP PDU to an ARP Request. - * - * Calling this method sets the values of the target ARP PDU to become - * an ARP Request PDU. - * - * \param ip_tgt string with the target's IP or hostname. - * \param ip_snd string with the sender's IP or hostname. - * \param hw_snd uint8_t array of 6 bytes containing the sender's hardware address(optional). - */ - void set_arp_request(const std::string& ip_tgt, const std::string& ip_snd, const uint8_t* hw_snd = 0); - - /** - * \brief Converts the current ARP PDU to an ARP Reply. - * - * Calling this method sets the values of the target ARP PDU to become - * an ARP Reply PDU. - * - * \param ip_tgt string with the target's IP or hostname. - * \param ip_snd string with the sender's IP or hostname. - * \param hw_tgt uint8_t array of 6 bytes containing the target's hardware address. - * \param hw_snd uint8_t array of 6 bytes containing the sender's hardware address. - */ - void set_arp_reply(const std::string& ip_tgt, const std::string& ip_snd, const uint8_t* hw_tgt, const uint8_t* hw_snd); + IPv4Address sender, const hwaddress_type &hw_tgt = hwaddress_type(), + const hwaddress_type &hw_snd = hwaddress_type()); /** \brief Check wether ptr points to a valid response for this PDU. * @@ -295,10 +275,14 @@ namespace Tins { 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 */ + /* sender hardware address */ + uint8_t ar_sha[hwaddress_type::address_size]; + /* sender IP address */ + uint32_t ar_sip; + /* target hardware address */ + uint8_t ar_tha[hwaddress_type::address_size]; + /* target IP address */ + uint32_t ar_tip; } __attribute__((__packed__)); void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent); diff --git a/include/utils.h b/include/utils.h index b51cb76..b687f63 100644 --- a/include/utils.h +++ b/include/utils.h @@ -33,6 +33,7 @@ #include #include "packetsender.h" #include "ipaddress.h" +#include "hwaddress.h" namespace Tins { /** \brief Network utils namespace. @@ -124,7 +125,7 @@ namespace Tins { * false otherwise. */ bool resolve_hwaddr(const std::string &iface, IPv4Address ip, - uint8_t *buffer, PacketSender *sender); + HWAddress<6> *address, PacketSender *sender); /** \brief List all network interfaces. * @@ -168,7 +169,7 @@ namespace Tins { * * \return bool indicating wether the operation was successfull. */ - bool interface_hwaddr(const std::string &iface, uint8_t *buffer); + bool interface_hwaddr(const std::string &iface, HWAddress<6> *address); /** * \brief Lookup the interface identifier. diff --git a/src/arp.cpp b/src/arp.cpp index 73dedb4..f4449b6 100644 --- a/src/arp.cpp +++ b/src/arp.cpp @@ -37,7 +37,7 @@ using std::runtime_error; namespace Tins { ARP::ARP(IPv4Address target_ip, IPv4Address sender_ip, - const uint8_t *target_hw, const uint8_t *sender_hw) + const hwaddress_type &target_hw, const hwaddress_type &sender_hw) : PDU(0x0608) { memset(&_arp, 0, sizeof(arphdr)); @@ -47,10 +47,8 @@ ARP::ARP(IPv4Address target_ip, IPv4Address sender_ip, prot_addr_length(IP::ADDR_SIZE); sender_ip_addr(sender_ip); target_ip_addr(target_ip); - if(sender_hw) - sender_hw_addr(sender_hw); - if(target_hw) - target_hw_addr(target_hw); + sender_hw_addr(sender_hw); + target_hw_addr(target_hw); } ARP::ARP(const uint8_t *buffer, uint32_t total_sz) @@ -64,18 +62,16 @@ ARP::ARP(const uint8_t *buffer, uint32_t total_sz) inner_pdu(new RawPDU(buffer + sizeof(arphdr), total_sz)); } -void ARP::sender_hw_addr(const uint8_t* new_snd_hw_addr) { - //Should this use hardware address' length? - memcpy(this->_arp.ar_sha, new_snd_hw_addr, 6); +void ARP::sender_hw_addr(const hwaddress_type &new_snd_hw_addr) { + std::copy(new_snd_hw_addr.begin(), new_snd_hw_addr.end(), _arp.ar_sha); } void ARP::sender_ip_addr(IPv4Address new_snd_ip_addr) { this->_arp.ar_sip = new_snd_ip_addr; } -void ARP::target_hw_addr(const uint8_t* new_tgt_hw_addr) { - //Should this use hardware address' length? - memcpy(this->_arp.ar_tha, new_tgt_hw_addr, 6); +void ARP::target_hw_addr(const hwaddress_type &new_tgt_hw_addr) { + std::copy(new_tgt_hw_addr.begin(), new_tgt_hw_addr.end(), _arp.ar_tha); } void ARP::target_ip_addr(IPv4Address new_tgt_ip_addr) { @@ -102,27 +98,6 @@ void ARP::opcode(Flags new_opcode) { this->_arp.ar_op = Utils::net_to_host_s(new_opcode); } -void ARP::set_arp_request(const string& ip_tgt, const string& ip_snd, - const uint8_t* hw_snd) -{ - this->target_ip_addr(ip_tgt); - this->sender_ip_addr(ip_snd); - if (hw_snd) - this->sender_hw_addr(hw_snd); - this->opcode(REQUEST); -} - -void ARP::set_arp_reply(const std::string& ip_tgt, const std::string& ip_snd, - const uint8_t* hw_tgt, const uint8_t* hw_snd) -{ - this->target_ip_addr(ip_tgt); - this->sender_ip_addr(ip_snd); - this->sender_hw_addr(hw_snd); - this->target_hw_addr(hw_tgt); - this->opcode(REPLY); - -} - uint32_t ARP::header_size() const { return sizeof(arphdr); } @@ -154,24 +129,22 @@ PDU *ARP::clone_packet(const uint8_t *ptr, uint32_t total_sz) { } PDU* ARP::make_arp_request(const std::string& iface, IPv4Address target, - IPv4Address sender, const uint8_t* hw_snd) + IPv4Address sender, const hwaddress_type &hw_snd) { /* Create ARP packet and set its attributes */ ARP* arp = new ARP(); arp->target_ip_addr(target); arp->sender_ip_addr(sender); - if (hw_snd) { - arp->sender_hw_addr(hw_snd); - } + arp->sender_hw_addr(hw_snd); arp->opcode(REQUEST); /* Create the EthernetII PDU with the ARP PDU as its inner PDU */ - EthernetII* eth = new EthernetII(iface, EthernetII::BROADCAST, hw_snd, arp); - return eth; + return new EthernetII(iface, EthernetII::BROADCAST, hw_snd, arp); } PDU* ARP::make_arp_reply(const string& iface, IPv4Address target, - IPv4Address sender, const uint8_t* hw_tgt, const uint8_t* hw_snd) + IPv4Address sender, const hwaddress_type &hw_tgt, + const hwaddress_type &hw_snd) { /* Create ARP packet and set its attributes */ ARP* arp = new ARP(target, sender, hw_tgt, hw_snd); diff --git a/src/utils.cpp b/src/utils.cpp index f7e3ccf..99a21c7 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -66,15 +66,16 @@ struct IPv4Collector { /** \cond */ struct HWAddressCollector { - uint8_t *result; + Tins::HWAddress<6> *result; bool found; const char *iface; - HWAddressCollector(uint8_t *res, const char *interface) : result(res), found(false), iface(interface) { } + HWAddressCollector(Tins::HWAddress<6> *res, const char *interface) + : result(res), found(false), iface(interface) { } void operator() (struct ifaddrs *addr) { if(!found && addr->ifa_addr->sa_family == AF_PACKET && !strcmp(addr->ifa_name, iface)) { - memcpy(result, ((struct sockaddr_ll*)addr->ifa_addr)->sll_addr, 6); + *result = ((struct sockaddr_ll*)addr->ifa_addr)->sll_addr; found = true; } } @@ -225,10 +226,10 @@ Tins::PDU *Tins::Utils::ping_address(uint32_t ip, PacketSender *sender, IPv4Addr } bool Tins::Utils::resolve_hwaddr(const string &iface, IPv4Address ip, - uint8_t *buffer, PacketSender *sender) { + HWAddress<6> *address, PacketSender *sender) { IPv4Address my_ip; - uint8_t my_hw[6]; - if(!interface_ip(iface, my_ip) || !interface_hwaddr(iface, my_hw)) + HWAddress<6> my_hw; + if(!interface_ip(iface, my_ip) || !interface_hwaddr(iface, &my_hw)) return false; PDU *packet = ARP::make_arp_request(iface, ip, my_ip, my_hw); PDU *response = sender->send_recv(packet); @@ -236,7 +237,7 @@ bool Tins::Utils::resolve_hwaddr(const string &iface, IPv4Address ip, if(response) { ARP *arp_resp = dynamic_cast(response->inner_pdu()); if(arp_resp) - memcpy(buffer, arp_resp->sender_hw_addr(), 6); + *address = arp_resp->sender_hw_addr(); delete response; return arp_resp; } @@ -258,11 +259,11 @@ string Tins::Utils::interface_from_ip(IPv4Address ip) { } bool Tins::Utils::gateway_from_ip(IPv4Address ip, IPv4Address &gw_addr) { - std::vector entries; + typedef std::vector entries_type; + entries_type entries; uint32_t ip_int = ip; route_entries(std::back_inserter(entries)); - for(std::vector::const_iterator it(entries.begin()); it != entries.end(); ++it) { - std::cout << std::hex << ip_int << " " << (uint32_t)it->mask << " " << (uint32_t)it->destination << "\n"; + for(entries_type::const_iterator it(entries.begin()); it != entries.end(); ++it) { if((ip_int & it->mask) == it->destination) { gw_addr = it->gateway; return true; @@ -284,8 +285,8 @@ bool Tins::Utils::interface_ip(const string &iface, IPv4Address &ip) { return collector.found; } -bool Tins::Utils::interface_hwaddr(const string &iface, uint8_t *buffer) { - HWAddressCollector collector(buffer, iface.c_str()); +bool Tins::Utils::interface_hwaddr(const string &iface, HWAddress<6> *address) { + HWAddressCollector collector(address, iface.c_str()); generic_iface_loop(collector); return collector.found; } diff --git a/tests/src/arp.cpp b/tests/src/arp.cpp index aa33a91..add9d1a 100644 --- a/tests/src/arp.cpp +++ b/tests/src/arp.cpp @@ -11,11 +11,13 @@ using namespace std; using namespace Tins; +typedef ARP::hwaddress_type address_type; + class ARPTest : public testing::Test { public: - static const uint8_t empty_addr[]; - static const uint8_t hw_addr1[]; - static const uint8_t hw_addr2[]; + static const address_type empty_addr; + static const address_type hw_addr1; + static const address_type hw_addr2; static const string ip_addr1; static const uint8_t expected_packet[]; static const IPv4Address addr1, addr2; @@ -23,10 +25,15 @@ public: void test_equals(const ARP &arp1, const ARP &arp2); }; -const uint8_t ARPTest::empty_addr[] = {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00'}; -const uint8_t ARPTest::hw_addr1[] = {'\x13', '\xda', '\xde', '\xf1', '\x01', '\x85'}; -const uint8_t ARPTest::hw_addr2[] = {'\x7a', '\x1f', '\xf4', '\x39', '\xab', '\x0d'}; -const uint8_t ARPTest::expected_packet[] = {'\x00', '\x01', '\x08', '\x00', '\x06', '\x04', '\x00', '\x02', '\x03', '\xde', '\xf5', '\x12', '\t', '\xfa', '\xc0', '\xa8', '-', '\xe7', '\xf5', '\x12', '\xda', 'g', '\xbd', '\r', ' ', '\x9b', 'Q', '\xfe'}; +const address_type ARPTest::empty_addr; +const address_type ARPTest::hw_addr1("13:da:de:f1:01:85"); +const address_type ARPTest::hw_addr2("7a:1f:f4:39:ab:0d"); +const uint8_t ARPTest::expected_packet[] = { + '\x00', '\x01', '\x08', '\x00', '\x06', '\x04', '\x00', '\x02', + '\x03', '\xde', '\xf5', '\x12', '\t', '\xfa', '\xc0', '\xa8', '-', + '\xe7', '\xf5', '\x12', '\xda', 'g', '\xbd', '\r', ' ', '\x9b', 'Q', + '\xfe' +}; const IPv4Address ARPTest::addr1(0x1234), ARPTest::addr2(0xa3f1); void ARPTest::test_equals(const ARP &arp1, const ARP &arp2) { @@ -37,8 +44,8 @@ void ARPTest::test_equals(const ARP &arp1, const ARP &arp2) { EXPECT_EQ(arp1.prot_addr_format(), arp2.prot_addr_format()); EXPECT_EQ(arp1.sender_ip_addr(), arp2.sender_ip_addr()); EXPECT_EQ(arp1.target_ip_addr(), arp2.target_ip_addr()); - EXPECT_TRUE(memcmp(arp1.sender_hw_addr(), arp2.sender_hw_addr(), arp2.hw_addr_length()) == 0); - EXPECT_TRUE(memcmp(arp1.target_hw_addr(), arp2.target_hw_addr(), arp2.hw_addr_length()) == 0); + EXPECT_EQ(arp1.sender_hw_addr(), arp2.sender_hw_addr()); + EXPECT_EQ(arp1.target_hw_addr(), arp2.target_hw_addr()); EXPECT_EQ((bool)arp1.inner_pdu(), (bool)arp2.inner_pdu()); } @@ -46,8 +53,8 @@ TEST_F(ARPTest, DefaultContructor) { ARP arp; EXPECT_EQ(arp.target_ip_addr(), 0); EXPECT_EQ(arp.sender_ip_addr(), 0); - EXPECT_TRUE(memcmp(arp.target_hw_addr(), empty_addr, sizeof(empty_addr)) == 0); - EXPECT_TRUE(memcmp(arp.target_hw_addr(), empty_addr, sizeof(empty_addr)) == 0); + EXPECT_EQ(arp.target_hw_addr(), empty_addr); + EXPECT_EQ(arp.target_hw_addr(), empty_addr); EXPECT_EQ(arp.pdu_type(), PDU::ARP); } @@ -73,8 +80,8 @@ TEST_F(ARPTest, NestedCopy) { TEST_F(ARPTest, CompleteContructor) { ARP arp(addr1, addr2, hw_addr1, hw_addr2); - EXPECT_TRUE(memcmp(arp.target_hw_addr(), hw_addr1, sizeof(hw_addr1)) == 0); - EXPECT_TRUE(memcmp(arp.sender_hw_addr(), hw_addr2, sizeof(hw_addr2)) == 0); + EXPECT_EQ(arp.target_hw_addr(), hw_addr1); + EXPECT_EQ(arp.sender_hw_addr(), hw_addr2); EXPECT_EQ(arp.target_ip_addr(), addr1); EXPECT_EQ(arp.sender_ip_addr(), addr2); } @@ -94,13 +101,13 @@ TEST_F(ARPTest, TargetIPAddrInt) { TEST_F(ARPTest, TargetHWAddr) { ARP arp; arp.target_hw_addr(hw_addr1); - EXPECT_TRUE(memcmp(arp.target_hw_addr(), hw_addr1, sizeof(hw_addr1)) == 0); + EXPECT_EQ(arp.target_hw_addr(), hw_addr1); } TEST_F(ARPTest, SenderHWAddr) { ARP arp; arp.sender_hw_addr(hw_addr1); - EXPECT_TRUE(memcmp(arp.sender_hw_addr(), hw_addr1, sizeof(hw_addr1)) == 0); + EXPECT_EQ(arp.sender_hw_addr(), hw_addr1); } TEST_F(ARPTest, ProtAddrFormat) { @@ -162,8 +169,8 @@ TEST_F(ARPTest, ConstructorFromBuffer) { EXPECT_EQ(arp1.prot_addr_format(), arp2.prot_addr_format()); EXPECT_EQ(arp1.sender_ip_addr(), arp2.sender_ip_addr()); EXPECT_EQ(arp1.target_ip_addr(), arp2.target_ip_addr()); - EXPECT_TRUE(memcmp(arp1.sender_hw_addr(), arp2.sender_hw_addr(), arp2.hw_addr_length()) == 0); - EXPECT_TRUE(memcmp(arp1.target_hw_addr(), arp2.target_hw_addr(), arp2.hw_addr_length()) == 0); + EXPECT_EQ(arp1.sender_hw_addr(), arp2.sender_hw_addr()); + EXPECT_EQ(arp1.target_hw_addr(), arp2.target_hw_addr()); delete[] buffer; }