1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-28 20:44:26 +01:00

ARP now uses HWAddress. Utils have been updated as well.

This commit is contained in:
Matias Fontanini
2012-08-07 17:28:46 -03:00
parent e64eb11f1c
commit ad11d3c244
5 changed files with 79 additions and 113 deletions

View File

@@ -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);

View File

@@ -33,6 +33,7 @@
#include <stdint.h>
#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.

View File

@@ -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);

View File

@@ -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<ARP*>(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<RouteEntry> entries;
typedef std::vector<RouteEntry> entries_type;
entries_type entries;
uint32_t ip_int = ip;
route_entries(std::back_inserter(entries));
for(std::vector<RouteEntry>::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;
}

View File

@@ -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;
}