mirror of
https://github.com/mfontanini/libtins
synced 2026-01-30 05:24:26 +01:00
Every test now pass on big endian architectures. Ported about half of the library to windows as well.
This commit is contained in:
@@ -146,7 +146,7 @@ namespace Tins {
|
||||
IEEE80211_RADIOTAP = 803, /* IEEE 802.11 + radiotap header. */
|
||||
IEEE802154 = 804, /* IEEE 802.15.4 header. */
|
||||
IEEE802154_PHY = 805, /* IEEE 802.15.4 PHY header. */
|
||||
VOID = 0xFFFF, /* Void type, nothing is known. */
|
||||
VOID_TYPE = 0xFFFF, /* Void type, nothing is known. */
|
||||
NONE = 0xFFFE, /* Zero header length. */
|
||||
};
|
||||
};
|
||||
|
||||
@@ -381,11 +381,13 @@ namespace Tins {
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
bool send(PacketSender &sender);
|
||||
#endif // WIN32
|
||||
|
||||
/**
|
||||
* \brief Adds a new option to this Dot11 PDU.
|
||||
@@ -955,16 +957,28 @@ namespace Tins {
|
||||
/**
|
||||
* \brief Getter for the fragment number.
|
||||
*
|
||||
* \return uint8_t containing the fragment number.
|
||||
* \return The stored fragment number.
|
||||
*/
|
||||
uint8_t frag_num() const { return _ext_header.seq_control.frag_number; }
|
||||
small_uint<4> frag_num() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _ext_header.frag_seq & 0xf;
|
||||
#else
|
||||
return (_ext_header.frag_seq >> 8) & 0xf;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the sequence number.
|
||||
* \brief Getter for the sequence number field.
|
||||
*
|
||||
* \return uint16_t containing the sequence number.
|
||||
* \return The stored sequence number.
|
||||
*/
|
||||
uint16_t seq_num() const { return Endian::le_to_host(_ext_header.seq_control.seq_number); }
|
||||
small_uint<12> seq_num() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return (_ext_header.frag_seq >> 4) & 0xfff;
|
||||
#else
|
||||
return (Endian::le_to_host<uint16_t>(_ext_header.frag_seq) >> 4) & 0xfff;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the fourth address.
|
||||
@@ -992,14 +1006,14 @@ namespace Tins {
|
||||
*
|
||||
* \param new_frag_num The new fragment number.
|
||||
*/
|
||||
void frag_num(uint8_t new_frag_num);
|
||||
void frag_num(small_uint<4> new_frag_num);
|
||||
|
||||
/**
|
||||
* \brief Setter for the sequence number.
|
||||
*
|
||||
* \param new_seq_num The new sequence number.
|
||||
*/
|
||||
void seq_num(uint16_t new_seq_num);
|
||||
void seq_num(small_uint<12> new_seq_num);
|
||||
|
||||
/**
|
||||
* \brief Setter for the fourth address.
|
||||
@@ -1430,15 +1444,7 @@ namespace Tins {
|
||||
struct ExtendedHeader {
|
||||
uint8_t addr2[address_type::address_size];
|
||||
uint8_t addr3[address_type::address_size];
|
||||
struct {
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
uint16_t frag_number:4,
|
||||
seq_number:12;
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
uint16_t seq_number:12,
|
||||
frag_number:4;
|
||||
#endif
|
||||
} __attribute__((__packed__)) seq_control;
|
||||
uint16_t frag_seq;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
|
||||
@@ -2570,14 +2576,26 @@ namespace Tins {
|
||||
*
|
||||
* \return The stored fragment number.
|
||||
*/
|
||||
uint8_t frag_num() const { return _ext_header.seq_control.frag_number; }
|
||||
small_uint<4> frag_num() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _ext_header.frag_seq & 0xf;
|
||||
#else
|
||||
return (_ext_header.frag_seq >> 8) & 0xf;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the sequence number field.
|
||||
*
|
||||
* \return The stored sequence number.
|
||||
*/
|
||||
uint16_t seq_num() const { return Endian::le_to_host(_ext_header.seq_control.seq_number); }
|
||||
small_uint<12> seq_num() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return (_ext_header.frag_seq >> 4) & 0xfff;
|
||||
#else
|
||||
return (Endian::le_to_host<uint16_t>(_ext_header.frag_seq) >> 4) & 0xfff;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the fourth address.
|
||||
@@ -2605,14 +2623,14 @@ namespace Tins {
|
||||
*
|
||||
* \param new_frag_num The fragment number to be set.
|
||||
*/
|
||||
void frag_num(uint8_t new_frag_num);
|
||||
void frag_num(small_uint<4> new_frag_num);
|
||||
|
||||
/**
|
||||
* \brief Setter for the sequence number field.
|
||||
*
|
||||
* \param new_seq_num The sequence number to be set.
|
||||
*/
|
||||
void seq_num(uint16_t new_seq_num);
|
||||
void seq_num(small_uint<12> new_seq_num);
|
||||
|
||||
/**
|
||||
* \brief Setter for the fourth address field.
|
||||
@@ -2656,15 +2674,7 @@ namespace Tins {
|
||||
struct ExtendedHeader {
|
||||
uint8_t addr2[address_type::address_size];
|
||||
uint8_t addr3[address_type::address_size];
|
||||
struct {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
uint16_t frag_number:4,
|
||||
seq_number:12;
|
||||
#elif TINS_IS_BIG_ENDIAN
|
||||
uint16_t frag_number:4,
|
||||
seq_number:12;
|
||||
#endif
|
||||
} __attribute__((__packed__)) seq_control;
|
||||
uint16_t frag_seq;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
@@ -151,11 +151,14 @@ namespace Tins {
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
|
||||
// Windows does not support sending L2 PDUs.
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
bool send(PacketSender &sender);
|
||||
#endif // WIN32
|
||||
|
||||
/** \brief Check wether ptr points to a valid response for this PDU.
|
||||
*
|
||||
@@ -165,12 +168,14 @@ namespace Tins {
|
||||
*/
|
||||
bool matches_response(uint8_t *ptr, uint32_t total_sz);
|
||||
|
||||
#ifndef WIN32
|
||||
/** \brief Receives a matching response for this packet.
|
||||
*
|
||||
* \sa PDU::recv_response
|
||||
* \param sender The packet sender which will receive the packet.
|
||||
*/
|
||||
PDU *recv_response(PacketSender &sender);
|
||||
#endif // WIN32
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
|
||||
@@ -149,11 +149,13 @@ namespace Tins {
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
bool send(PacketSender &sender);
|
||||
#endif // WIN32
|
||||
|
||||
/** \brief Check wether ptr points to a valid response for this PDU.
|
||||
*
|
||||
@@ -163,12 +165,14 @@ namespace Tins {
|
||||
*/
|
||||
bool matches_response(uint8_t *ptr, uint32_t total_sz);
|
||||
|
||||
#ifndef WIN32
|
||||
/** \brief Receives a matching response for this packet.
|
||||
*
|
||||
* \sa PDU::recv_response
|
||||
* \param sender The packet sender which will receive the packet.
|
||||
*/
|
||||
PDU *recv_response(PacketSender &sender);
|
||||
#endif // WIN32
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
|
||||
11
include/ip.h
11
include/ip.h
@@ -114,7 +114,12 @@ namespace Tins {
|
||||
*
|
||||
* Initializes every field to 0.
|
||||
*/
|
||||
option_identifier() : number(0), op_class(0), copied(0) {}
|
||||
option_identifier()
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
: number(0), op_class(0), copied(0) {}
|
||||
#else
|
||||
: copied(0), op_class(0), number(0) {}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Constructs this option from a single uint8_t value.
|
||||
@@ -144,7 +149,11 @@ namespace Tins {
|
||||
*/
|
||||
option_identifier(OptionNumber number, OptionClass op_class,
|
||||
small_uint<1> copied)
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
: number(number), op_class(op_class), copied(copied) {}
|
||||
#else
|
||||
: copied(copied), op_class(op_class), number(number) {}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Equality operator.
|
||||
|
||||
@@ -75,11 +75,13 @@ namespace Tins {
|
||||
*/
|
||||
~PacketSender();
|
||||
|
||||
#ifndef WIN32
|
||||
/** \brief Opens a layer y socket.
|
||||
*
|
||||
* \return Returns true if the socket was open successfully, false otherwise.
|
||||
*/
|
||||
bool open_l2_socket();
|
||||
#endif // WIN32
|
||||
|
||||
/** \brief Opens a layer 3 socket, using the corresponding protocol
|
||||
* for the given flag.
|
||||
@@ -118,6 +120,7 @@ namespace Tins {
|
||||
*/
|
||||
PDU *send_recv(PDU &pdu);
|
||||
|
||||
#ifndef WIN32
|
||||
/** \brief Receives a layer 2 PDU response to a previously sent PDU.
|
||||
*
|
||||
* This PacketSender will receive data from a raw socket, open using the corresponding flag,
|
||||
@@ -141,6 +144,7 @@ namespace Tins {
|
||||
* \return Returns true if the PDU was successfully sent, false otherwise.
|
||||
*/
|
||||
bool send_l2(PDU &pdu, struct sockaddr* link_addr, uint32_t len_addr);
|
||||
#endif // WIN32
|
||||
|
||||
/** \brief Receives a layer 3 PDU response to a previously sent PDU.
|
||||
*
|
||||
|
||||
@@ -105,17 +105,23 @@ namespace Tins {
|
||||
* \brief Getter for the control field.
|
||||
* \return The control field.
|
||||
*/
|
||||
uint8_t control() const { return _snap.control; }
|
||||
uint8_t control() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return (_snap.control_org) & 0xff;
|
||||
#else
|
||||
return (_snap.control_org >> 24) & 0xff;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the org code field.
|
||||
* \return The org code field.
|
||||
*/
|
||||
small_uint<24> org_code() const {
|
||||
#ifdef TINS_IS_LITTLE_ENDIAN
|
||||
return Endian::be_to_host<uint32_t>(_snap.org_code << 8);
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return Endian::be_to_host<uint32_t>(_snap.control_org & 0xffffff00);
|
||||
#else
|
||||
return Endian::be_to_host(_snap.org_code);
|
||||
return _snap.control_org & 0xffffff;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -151,13 +157,14 @@ namespace Tins {
|
||||
struct snaphdr {
|
||||
uint8_t dsap;
|
||||
uint8_t ssap;
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
/*#if TINS_IS_LITTLE_ENDIAN
|
||||
uint32_t control:8,
|
||||
org_code:24;
|
||||
#elif TINS_IS_BIG_ENDIAN
|
||||
uint32_t org_code:24,
|
||||
control:8;
|
||||
#endif
|
||||
#endif*/
|
||||
uint32_t control_org;
|
||||
uint16_t eth_type;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
|
||||
@@ -32,6 +32,10 @@
|
||||
|
||||
#ifndef WIN32
|
||||
#include <ifaddrs.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <iphlpapi.h>
|
||||
#undef interface
|
||||
#endif
|
||||
#include <string>
|
||||
#include <set>
|
||||
@@ -187,6 +191,7 @@ namespace Tins {
|
||||
* the object to collect data from them.
|
||||
* \param functor An instance of an class which implements operator(struct ifaddrs*).
|
||||
*/
|
||||
#ifndef WIN32
|
||||
template<class Functor>
|
||||
void generic_iface_loop(Functor &functor) {
|
||||
struct ifaddrs *ifaddrs = 0;
|
||||
@@ -199,6 +204,22 @@ namespace Tins {
|
||||
if(ifaddrs)
|
||||
freeifaddrs(ifaddrs);
|
||||
}
|
||||
#else // WIN32
|
||||
template<class Functor>
|
||||
void generic_iface_loop(Functor &functor) {
|
||||
ULONG size;
|
||||
::GetAdaptersAddresses(AF_INET, 0, 0, 0, &size);
|
||||
std::vector<uint8_t> buffer(size);
|
||||
if (::GetAdaptersAddresses(AF_INET, 0, 0, (IP_ADAPTER_ADDRESSES *)&buffer[0], &size) == ERROR_SUCCESS) {
|
||||
PIP_ADAPTER_ADDRESSES iface = (IP_ADAPTER_ADDRESSES *)&buffer[0];
|
||||
while(iface) {
|
||||
if(functor(iface))
|
||||
break;
|
||||
iface = iface->Next;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // WIN32
|
||||
|
||||
namespace Internals {
|
||||
void skip_line(std::istream &input);
|
||||
|
||||
@@ -166,6 +166,7 @@ uint32_t Dot11::header_size() const {
|
||||
return sz;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
bool Dot11::send(PacketSender &sender) {
|
||||
struct sockaddr_ll addr;
|
||||
|
||||
@@ -179,6 +180,7 @@ bool Dot11::send(PacketSender &sender) {
|
||||
|
||||
return sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
|
||||
}
|
||||
#endif // WIN32
|
||||
|
||||
void Dot11::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
|
||||
uint32_t my_sz = header_size();
|
||||
@@ -299,12 +301,20 @@ void Dot11ManagementFrame::addr3(const address_type &new_addr3) {
|
||||
std::copy(new_addr3.begin(), new_addr3.end(), _ext_header.addr3);
|
||||
}
|
||||
|
||||
void Dot11ManagementFrame::frag_num(uint8_t new_frag_num) {
|
||||
this->_ext_header.seq_control.frag_number = new_frag_num;
|
||||
void Dot11ManagementFrame::frag_num(small_uint<4> new_frag_num) {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
_ext_header.frag_seq = new_frag_num | (_ext_header.frag_seq & 0xfff0);
|
||||
#else
|
||||
_ext_header.frag_seq = (new_frag_num << 8) | (_ext_header.frag_seq & 0xf0ff);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Dot11ManagementFrame::seq_num(uint16_t new_seq_num) {
|
||||
this->_ext_header.seq_control.seq_number = Endian::host_to_le(new_seq_num);
|
||||
void Dot11ManagementFrame::seq_num(small_uint<12> new_seq_num) {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
_ext_header.frag_seq = (new_seq_num << 4) | (_ext_header.frag_seq & 0xf);
|
||||
#else
|
||||
_ext_header.frag_seq = Endian::host_to_le<uint16_t>(new_seq_num << 4) | (_ext_header.frag_seq & 0xf00);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Dot11ManagementFrame::addr4(const address_type &new_addr4) {
|
||||
@@ -530,12 +540,22 @@ void Dot11ManagementFrame::bss_load(const bss_load_type &data) {
|
||||
uint16_t dummy = Endian::host_to_le(data.station_count);
|
||||
|
||||
//*(uint16_t*)buffer = Endian::host_to_le(data.station_count);
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
buffer[0] = dummy & 0xff;
|
||||
buffer[1] = (dummy >> 8) & 0xff;
|
||||
#else
|
||||
buffer[0] = (dummy >> 8) & 0xff;
|
||||
buffer[1] = dummy & 0xff;
|
||||
#endif
|
||||
buffer[2] = data.channel_utilization;
|
||||
dummy = Endian::host_to_le(data.available_capacity);
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
buffer[3] = dummy & 0xff;
|
||||
buffer[4] = (dummy >> 8) & 0xff;
|
||||
#else
|
||||
buffer[3] = (dummy >> 8) & 0xff;
|
||||
buffer[4] = dummy & 0xff;
|
||||
#endif
|
||||
//*(uint16_t*)(buffer + 3) = Endian::host_to_le(data.available_capacity);
|
||||
add_tagged_option(BSS_LOAD, sizeof(buffer), buffer);
|
||||
}
|
||||
@@ -1242,12 +1262,20 @@ void Dot11Data::addr3(const address_type &new_addr3) {
|
||||
std::copy(new_addr3.begin(), new_addr3.end(), _ext_header.addr3);
|
||||
}
|
||||
|
||||
void Dot11Data::frag_num(uint8_t new_frag_num) {
|
||||
_ext_header.seq_control.frag_number = new_frag_num;
|
||||
void Dot11Data::frag_num(small_uint<4> new_frag_num) {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
_ext_header.frag_seq = new_frag_num | (_ext_header.frag_seq & 0xfff0);
|
||||
#else
|
||||
_ext_header.frag_seq = (new_frag_num << 8) | (_ext_header.frag_seq & 0xf0ff);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Dot11Data::seq_num(uint16_t new_seq_num) {
|
||||
_ext_header.seq_control.seq_number = Endian::host_to_le(new_seq_num);
|
||||
void Dot11Data::seq_num(small_uint<12> new_seq_num) {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
_ext_header.frag_seq = (new_seq_num << 4) | (_ext_header.frag_seq & 0xf);
|
||||
#else
|
||||
_ext_header.frag_seq = Endian::host_to_le<uint16_t>(new_seq_num << 4) | (_ext_header.frag_seq & 0xf00);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Dot11Data::addr4(const address_type &new_addr4) {
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "rawpdu.h"
|
||||
#include "ip.h"
|
||||
#include "arp.h"
|
||||
#include "constants.h"
|
||||
|
||||
namespace Tins {
|
||||
const EthernetII::address_type EthernetII::BROADCAST("ff:ff:ff:ff:ff:ff");
|
||||
@@ -68,10 +69,10 @@ EthernetII::EthernetII(const uint8_t *buffer, uint32_t total_sz)
|
||||
total_sz -= sizeof(ethhdr);
|
||||
if(total_sz) {
|
||||
switch(payload_type()) {
|
||||
case ETHERTYPE_IP:
|
||||
case Constants::Ethernet::IP:
|
||||
next = new Tins::IP(buffer, total_sz);
|
||||
break;
|
||||
case ETHERTYPE_ARP:
|
||||
case Constants::Ethernet::ARP:
|
||||
next = new Tins::ARP(buffer, total_sz);
|
||||
break;
|
||||
default:
|
||||
@@ -102,6 +103,7 @@ uint32_t EthernetII::header_size() const {
|
||||
return sizeof(ethhdr);
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
bool EthernetII::send(PacketSender &sender) {
|
||||
if(!_iface)
|
||||
throw std::runtime_error("Interface has not been set");
|
||||
@@ -117,6 +119,7 @@ bool EthernetII::send(PacketSender &sender) {
|
||||
|
||||
return sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
|
||||
}
|
||||
#endif // WIN32
|
||||
|
||||
bool EthernetII::matches_response(uint8_t *ptr, uint32_t total_sz) {
|
||||
if(total_sz < sizeof(ethhdr))
|
||||
@@ -135,13 +138,13 @@ void EthernetII::write_serialization(uint8_t *buffer, uint32_t total_sz, const P
|
||||
|
||||
/* Inner type defaults to IP */
|
||||
if ((_eth.payload_type == 0) && inner_pdu()) {
|
||||
uint16_t type = ETHERTYPE_IP;
|
||||
uint16_t type = Constants::Ethernet::IP;
|
||||
switch (inner_pdu()->pdu_type()) {
|
||||
case PDU::IP:
|
||||
type = ETHERTYPE_IP;
|
||||
type = Constants::Ethernet::IP;
|
||||
break;
|
||||
case PDU::ARP:
|
||||
type = ETHERTYPE_ARP;
|
||||
type = Constants::Ethernet::ARP;
|
||||
break;
|
||||
default:
|
||||
type = 0;
|
||||
@@ -151,6 +154,7 @@ void EthernetII::write_serialization(uint8_t *buffer, uint32_t total_sz, const P
|
||||
memcpy(buffer, &_eth, sizeof(ethhdr));
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
PDU *EthernetII::recv_response(PacketSender &sender) {
|
||||
struct sockaddr_ll addr;
|
||||
memset(&addr, 0, sizeof(struct sockaddr_ll));
|
||||
@@ -163,6 +167,7 @@ PDU *EthernetII::recv_response(PacketSender &sender) {
|
||||
|
||||
return sender.recv_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
|
||||
}
|
||||
#endif // WIN32
|
||||
|
||||
PDU *EthernetII::clone_packet(const uint8_t *ptr, uint32_t total_sz) {
|
||||
if(total_sz < sizeof(_eth))
|
||||
|
||||
@@ -87,6 +87,7 @@ uint32_t IEEE802_3::header_size() const {
|
||||
return sizeof(ethhdr);
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
bool IEEE802_3::send(PacketSender &sender) {
|
||||
struct sockaddr_ll addr;
|
||||
|
||||
@@ -100,6 +101,7 @@ bool IEEE802_3::send(PacketSender &sender) {
|
||||
|
||||
return sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
|
||||
}
|
||||
#endif // WIN32
|
||||
|
||||
bool IEEE802_3::matches_response(uint8_t *ptr, uint32_t total_sz) {
|
||||
if(total_sz < sizeof(ethhdr))
|
||||
@@ -125,6 +127,7 @@ void IEEE802_3::write_serialization(uint8_t *buffer, uint32_t total_sz, const PD
|
||||
_eth.length = 0;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
PDU *IEEE802_3::recv_response(PacketSender &sender) {
|
||||
struct sockaddr_ll addr;
|
||||
memset(&addr, 0, sizeof(struct sockaddr_ll));
|
||||
@@ -137,6 +140,7 @@ PDU *IEEE802_3::recv_response(PacketSender &sender) {
|
||||
|
||||
return sender.recv_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
|
||||
}
|
||||
#endif // WIN32
|
||||
|
||||
PDU *IEEE802_3::clone_packet(const uint8_t *ptr, uint32_t total_sz) {
|
||||
if(total_sz < sizeof(_eth))
|
||||
|
||||
16
src/ip.cpp
16
src/ip.cpp
@@ -34,6 +34,8 @@
|
||||
#ifndef WIN32
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
#include "ip.h"
|
||||
#include "tcp.h"
|
||||
@@ -128,13 +130,13 @@ IP::IP(const uint8_t *buffer, uint32_t total_sz)
|
||||
total_sz -= head_len() * sizeof(uint32_t);
|
||||
if (total_sz) {
|
||||
switch(_ip.protocol) {
|
||||
case IPPROTO_TCP:
|
||||
case Constants::IP::PROTO_TCP:
|
||||
inner_pdu(new Tins::TCP(buffer, total_sz));
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
case Constants::IP::PROTO_UDP:
|
||||
inner_pdu(new Tins::UDP(buffer, total_sz));
|
||||
break;
|
||||
case IPPROTO_ICMP:
|
||||
case Constants::IP::PROTO_ICMP:
|
||||
inner_pdu(new Tins::ICMP(buffer, total_sz));
|
||||
break;
|
||||
default:
|
||||
@@ -361,16 +363,16 @@ void IP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU* pare
|
||||
uint32_t new_flag;
|
||||
switch(inner_pdu()->pdu_type()) {
|
||||
case PDU::IP:
|
||||
new_flag = IPPROTO_IPIP;
|
||||
new_flag = Constants::IP::PROTO_IPIP;
|
||||
break;
|
||||
case PDU::TCP:
|
||||
new_flag = IPPROTO_TCP;
|
||||
new_flag = Constants::IP::PROTO_TCP;
|
||||
break;
|
||||
case PDU::UDP:
|
||||
new_flag = IPPROTO_UDP;
|
||||
new_flag = Constants::IP::PROTO_UDP;
|
||||
break;
|
||||
case PDU::ICMP:
|
||||
new_flag = IPPROTO_ICMP;
|
||||
new_flag = Constants::IP::PROTO_ICMP;
|
||||
break;
|
||||
default:
|
||||
// check for other protos
|
||||
|
||||
@@ -58,6 +58,7 @@ Loopback::Loopback(const uint8_t *buffer, uint32_t total_sz)
|
||||
_family = *reinterpret_cast<const uint32_t*>(buffer);
|
||||
buffer += sizeof(uint32_t);
|
||||
total_sz -= sizeof(uint32_t);
|
||||
#ifndef WIN32
|
||||
if(total_sz) {
|
||||
switch(_family) {
|
||||
case PF_INET:
|
||||
@@ -71,6 +72,7 @@ Loopback::Loopback(const uint8_t *buffer, uint32_t total_sz)
|
||||
break;
|
||||
};
|
||||
}
|
||||
#endif // WIN32
|
||||
}
|
||||
|
||||
void Loopback::family(uint32_t family_id) {
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
#include <linux/if_packet.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
#include "network_interface.h"
|
||||
#include "utils.h"
|
||||
@@ -49,8 +51,9 @@ struct InterfaceInfoCollector {
|
||||
|
||||
InterfaceInfoCollector(info_type *res, int id, const char* if_name)
|
||||
: info(res), iface_id(id), iface_name(if_name), found(false) { }
|
||||
|
||||
bool operator() (struct ifaddrs *addr) {
|
||||
|
||||
#ifndef WIN32
|
||||
bool operator() (const struct ifaddrs *addr) {
|
||||
using Tins::Endian::host_to_be;
|
||||
using Tins::IPv4Address;
|
||||
const struct sockaddr_ll* addr_ptr = ((struct sockaddr_ll*)addr->ifa_addr);
|
||||
@@ -68,13 +71,33 @@ struct InterfaceInfoCollector {
|
||||
}
|
||||
return found;
|
||||
}
|
||||
#else // WIN32
|
||||
bool operator() (const IP_ADAPTER_ADDRESSES *iface) {
|
||||
using Tins::IPv4Address;
|
||||
// This surely doesn't work
|
||||
if(iface_id == iface->IfIndex) {
|
||||
std::copy(iface->PhysicalAddress, iface->PhysicalAddress + 6, info->hw_addr.begin());
|
||||
const IP_ADAPTER_PREFIX *prefix_ptr = iface->FirstPrefix;
|
||||
for(size_t i = 0; prefix_ptr; prefix_ptr = prefix_ptr->Next, i++) {
|
||||
if(i == 0)
|
||||
info->ip_addr = IPv4Address(((const struct sockaddr_in *)prefix_ptr->Address.lpSockaddr)->sin_addr.s_addr);
|
||||
else if(i == 2)
|
||||
info->bcast_addr = IPv4Address(((const struct sockaddr_in *)prefix_ptr->Address.lpSockaddr)->sin_addr.s_addr);
|
||||
}
|
||||
// (?????)
|
||||
info->netmask = IPv4Address(info->ip_addr - info->bcast_addr);
|
||||
found = true;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
#endif // WIN32
|
||||
};
|
||||
/** \endcond */
|
||||
|
||||
namespace Tins {
|
||||
// static
|
||||
NetworkInterface NetworkInterface::default_interface() {
|
||||
return NetworkInterface(0);
|
||||
return NetworkInterface(IPv4Address(uint32_t(0)));
|
||||
}
|
||||
|
||||
NetworkInterface::NetworkInterface() : iface_id(0) {
|
||||
@@ -102,7 +125,7 @@ NetworkInterface::NetworkInterface(IPv4Address ip) : iface_id(0) {
|
||||
for(entries_type::const_iterator it(entries.begin()); it != entries.end(); ++it) {
|
||||
if((ip_int & it->mask) == it->destination) {
|
||||
if(!best_match || it->mask > best_match->mask)
|
||||
iface_id = if_nametoindex(it->interface.c_str());
|
||||
iface_id = resolve_index(it->interface.c_str());
|
||||
}
|
||||
}
|
||||
if(best_match)
|
||||
@@ -111,10 +134,14 @@ NetworkInterface::NetworkInterface(IPv4Address ip) : iface_id(0) {
|
||||
}
|
||||
|
||||
std::string NetworkInterface::name() const {
|
||||
#ifndef WIN32
|
||||
char iface_name[IF_NAMESIZE];
|
||||
if(!if_indextoname(iface_id, iface_name))
|
||||
throw std::runtime_error("Error fetching this interface's name");
|
||||
return iface_name;
|
||||
#else // WIN32
|
||||
return "Not implemented";
|
||||
#endif // WIN32
|
||||
}
|
||||
|
||||
NetworkInterface::Info NetworkInterface::addresses() const {
|
||||
@@ -128,9 +155,26 @@ NetworkInterface::Info NetworkInterface::addresses() const {
|
||||
}
|
||||
|
||||
NetworkInterface::id_type NetworkInterface::resolve_index(const char *name) {
|
||||
#ifndef WIN32
|
||||
id_type id = if_nametoindex(name);
|
||||
if(!id)
|
||||
throw std::runtime_error("Invalid interface error");
|
||||
#else // WIN32
|
||||
id_type id;
|
||||
ULONG size;
|
||||
GetAdaptersInfo(0, &size);
|
||||
std::vector<uint8_t> buffer(size);
|
||||
if ( GetAdaptersInfo((IP_ADAPTER_INFO *)&buffer[0], &size) == ERROR_SUCCESS) {
|
||||
PIP_ADAPTER_INFO iface = (IP_ADAPTER_INFO *)&buffer[0];
|
||||
while(iface) {
|
||||
if(!strcmp(iface->AdapterName, name)) {
|
||||
id = iface->Index;
|
||||
break;
|
||||
}
|
||||
iface = iface->Next;
|
||||
}
|
||||
}
|
||||
#endif // WIN32
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,9 @@
|
||||
#include <linux/if_packet.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
#include <cassert>
|
||||
#include <errno.h>
|
||||
@@ -57,11 +60,16 @@ Tins::PacketSender::PacketSender(uint32_t recv_timeout, uint32_t usec) :
|
||||
|
||||
Tins::PacketSender::~PacketSender() {
|
||||
for(unsigned i(0); i < _sockets.size(); ++i) {
|
||||
if(_sockets[i] != INVALID_RAW_SOCKET)
|
||||
if(_sockets[i] != INVALID_RAW_SOCKET)
|
||||
#ifndef WIN32
|
||||
::close(_sockets[i]);
|
||||
#else
|
||||
::closesocket(_sockets[i]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
bool Tins::PacketSender::open_l2_socket() {
|
||||
if (_sockets[ETHER_SOCKET] != INVALID_RAW_SOCKET)
|
||||
return true;
|
||||
@@ -71,6 +79,7 @@ bool Tins::PacketSender::open_l2_socket() {
|
||||
_sockets[ETHER_SOCKET] = sock;
|
||||
return true;
|
||||
}
|
||||
#endif // WIN32
|
||||
|
||||
bool Tins::PacketSender::open_l3_socket(SocketType type) {
|
||||
int socktype = find_type(type);
|
||||
@@ -84,7 +93,12 @@ bool Tins::PacketSender::open_l3_socket(SocketType type) {
|
||||
return false;
|
||||
|
||||
const int on = 1;
|
||||
setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL,(const void *)&on,sizeof(on));
|
||||
#ifndef WIN32
|
||||
typedef const void* option_ptr;
|
||||
#else
|
||||
typedef const char* option_ptr;
|
||||
#endif
|
||||
setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL,(option_ptr)&on,sizeof(on));
|
||||
|
||||
_sockets[type] = sockfd;
|
||||
return true;
|
||||
@@ -93,7 +107,11 @@ bool Tins::PacketSender::open_l3_socket(SocketType type) {
|
||||
bool Tins::PacketSender::close_socket(uint32_t flag) {
|
||||
if(flag >= SOCKETS_END || _sockets[flag] == INVALID_RAW_SOCKET)
|
||||
return false;
|
||||
#ifndef WIN32
|
||||
close(_sockets[flag]);
|
||||
#else
|
||||
closesocket(_sockets[flag]);
|
||||
#endif
|
||||
_sockets[flag] = INVALID_RAW_SOCKET;
|
||||
return true;
|
||||
}
|
||||
@@ -107,7 +125,7 @@ Tins::PDU *Tins::PacketSender::send_recv(PDU &pdu) {
|
||||
return 0;
|
||||
return pdu.recv_response(*this);
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
bool Tins::PacketSender::send_l2(PDU &pdu, struct sockaddr* link_addr, uint32_t len_addr) {
|
||||
if(!open_l2_socket())
|
||||
return false;
|
||||
@@ -126,6 +144,7 @@ Tins::PDU *Tins::PacketSender::recv_l2(PDU &pdu, struct sockaddr *link_addr, uin
|
||||
return 0;
|
||||
return recv_match_loop(_sockets[ETHER_SOCKET], pdu, link_addr, len_addr);
|
||||
}
|
||||
#endif // WIN32
|
||||
|
||||
Tins::PDU *Tins::PacketSender::recv_l3(PDU &pdu, struct sockaddr* link_addr, uint32_t len_addr, SocketType type) {
|
||||
if(!open_l3_socket(type))
|
||||
@@ -140,7 +159,7 @@ bool Tins::PacketSender::send_l3(PDU &pdu, struct sockaddr* link_addr, uint32_t
|
||||
if (ret_val) {
|
||||
int sock = _sockets[type];
|
||||
PDU::serialization_type buffer = pdu.serialize();
|
||||
ret_val = (sendto(sock, &buffer[0], buffer.size(), 0, link_addr, len_addr) != -1);
|
||||
ret_val = (sendto(sock, (const char*)&buffer[0], buffer.size(), 0, link_addr, len_addr) != -1);
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
@@ -160,7 +179,7 @@ Tins::PDU *Tins::PacketSender::recv_match_loop(int sock, PDU &pdu, struct sockad
|
||||
return 0;
|
||||
}
|
||||
if(FD_ISSET(sock, &readfds)) {
|
||||
ssize_t size = recvfrom(sock, buffer, 2048, 0, link_addr, &addrlen);
|
||||
ssize_t size = recvfrom(sock, (char*)buffer, 2048, 0, link_addr, &addrlen);
|
||||
if(pdu.matches_response(buffer, size)) {
|
||||
return pdu.clone_packet(buffer, size);
|
||||
}
|
||||
|
||||
16
src/snap.cpp
16
src/snap.cpp
@@ -44,7 +44,7 @@ Tins::SNAP::SNAP(PDU *child) : PDU(child)
|
||||
{
|
||||
std::memset(&_snap, 0, sizeof(_snap));
|
||||
_snap.dsap = _snap.ssap = 0xaa;
|
||||
_snap.control = 3;
|
||||
control(3);
|
||||
}
|
||||
|
||||
Tins::SNAP::SNAP(const uint8_t *buffer, uint32_t total_sz)
|
||||
@@ -70,16 +70,18 @@ Tins::SNAP::SNAP(const uint8_t *buffer, uint32_t total_sz)
|
||||
}
|
||||
|
||||
void Tins::SNAP::control(uint8_t new_control) {
|
||||
_snap.control = new_control;
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
_snap.control_org = (_snap.control_org & 0xffffff00) | (new_control);
|
||||
#else
|
||||
_snap.control_org = (_snap.control_org & 0xffffff) | (new_control << 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Tins::SNAP::org_code(small_uint<24> new_org) {
|
||||
// little endian fix, it was the only way to make it work.
|
||||
// check on big endian?
|
||||
#ifdef TINS_IS_LITTLE_ENDIAN
|
||||
_snap.org_code = Endian::host_to_be<uint32_t>(new_org) >> 8;
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
_snap.control_org = Endian::host_to_be<uint32_t>(new_org) | control();
|
||||
#else
|
||||
_snap.org_code = Endian::host_to_be<uint32_t>(new_org);
|
||||
_snap.control_org = new_org | (control() << 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -97,6 +97,20 @@ TEST_F(Dot11BeaconTest, CopyAssignmentOperator) {
|
||||
test_equals(dot1, dot2);
|
||||
}
|
||||
|
||||
TEST_F(Dot11BeaconTest, FragNum) {
|
||||
Dot11Beacon dot11;
|
||||
dot11.frag_num(0x3);
|
||||
EXPECT_EQ(0x3, dot11.frag_num());
|
||||
EXPECT_EQ(0, dot11.seq_num());
|
||||
}
|
||||
|
||||
TEST_F(Dot11BeaconTest, SeqNum) {
|
||||
Dot11Beacon dot11;
|
||||
dot11.seq_num(0x1f2);
|
||||
EXPECT_EQ(0x1f2, dot11.seq_num());
|
||||
EXPECT_EQ(0, dot11.frag_num());
|
||||
}
|
||||
|
||||
TEST_F(Dot11BeaconTest, FromBytes) {
|
||||
std::auto_ptr<PDU> dot11(Dot11::from_bytes(expected_packet, sizeof(expected_packet)));
|
||||
ASSERT_TRUE(dot11.get());
|
||||
|
||||
@@ -26,7 +26,6 @@ const uint8_t Dot11DataTest::expected_packet[] = {
|
||||
TEST_F(Dot11DataTest, Constructor) {
|
||||
Dot11Data dot11;
|
||||
test_equals_empty(dot11);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(Dot11DataTest, ConstructorFromBuffer) {
|
||||
@@ -47,6 +46,20 @@ TEST_F(Dot11DataTest, CopyAssignmentOperator) {
|
||||
test_equals(dot1, dot2);
|
||||
}
|
||||
|
||||
TEST_F(Dot11DataTest, FragNum) {
|
||||
Dot11Data dot11;
|
||||
dot11.frag_num(0x3);
|
||||
EXPECT_EQ(0x3, dot11.frag_num());
|
||||
EXPECT_EQ(0, dot11.seq_num());
|
||||
}
|
||||
|
||||
TEST_F(Dot11DataTest, SeqNum) {
|
||||
Dot11Data dot11;
|
||||
dot11.seq_num(0x1f2);
|
||||
EXPECT_EQ(0x1f2, dot11.seq_num());
|
||||
EXPECT_EQ(0, dot11.frag_num());
|
||||
}
|
||||
|
||||
TEST_F(Dot11DataTest, ClonePDU) {
|
||||
Dot11Data dot1(expected_packet, sizeof(expected_packet));
|
||||
std::auto_ptr<Dot11Data> dot2(dot1.clone());
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
};
|
||||
|
||||
const uint8_t SNAPTest::expected_packet[] = {
|
||||
'\xaa', '\xaa', '\x03', '\x00', '\x00', '\x00', '\x08', '\x00'
|
||||
'\xaa', '\xaa', '\x03', '\x00', '\x00', '\x01', '\x08', '\x00'
|
||||
};
|
||||
|
||||
TEST_F(SNAPTest, DefaultConstructor) {
|
||||
@@ -52,6 +52,15 @@ TEST_F(SNAPTest, OrgCode) {
|
||||
snap.org_code(0xfab1c3);
|
||||
|
||||
EXPECT_EQ(snap.org_code(), 0xfab1c3);
|
||||
EXPECT_EQ(snap.control(), 3);
|
||||
}
|
||||
|
||||
TEST_F(SNAPTest, Control) {
|
||||
SNAP snap;
|
||||
snap.control(0xfa);
|
||||
|
||||
EXPECT_EQ(snap.control(), 0xfa);
|
||||
EXPECT_EQ(snap.org_code(), 0);
|
||||
}
|
||||
|
||||
TEST_F(SNAPTest, EthType) {
|
||||
@@ -89,11 +98,11 @@ TEST_F(SNAPTest, ConstructorFromBuffer) {
|
||||
SNAP snap1(expected_packet, sizeof(expected_packet));
|
||||
PDU::serialization_type buffer = snap1.serialize();
|
||||
|
||||
EXPECT_EQ(snap1.control(), 3);
|
||||
EXPECT_EQ(snap1.dsap(), 0xaa);
|
||||
EXPECT_EQ(snap1.ssap(), 0xaa);
|
||||
EXPECT_EQ(snap1.eth_type(), 0x0800);
|
||||
EXPECT_EQ(snap1.org_code(), 0);
|
||||
EXPECT_EQ(3, snap1.control());
|
||||
EXPECT_EQ(0xaa, snap1.dsap());
|
||||
EXPECT_EQ(0xaa, snap1.ssap());
|
||||
EXPECT_EQ(0x0800, snap1.eth_type());
|
||||
EXPECT_EQ(1, snap1.org_code());
|
||||
|
||||
SNAP snap2(&buffer[0], buffer.size());
|
||||
test_equals(snap1, snap2);
|
||||
|
||||
Reference in New Issue
Block a user