mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Added Sniffer class. Added a constructor to eery PDU subclass which creates an instance of the PDU from a byte array.
This commit is contained in:
@@ -52,6 +52,14 @@ namespace Tins {
|
||||
*/
|
||||
ARP(uint32_t target_ip = 0, uint32_t sender_ip = 0, const uint8_t *target_hw = 0, const uint8_t *sender_hw = 0);
|
||||
|
||||
/**
|
||||
* \brief Constructor which creates an TCP object from a buffer and adds all identifiable
|
||||
* PDUs found in the buffer as children of this one.
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
ARP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/* Getters */
|
||||
/**
|
||||
* \brief Getter for the sender's hardware address.
|
||||
@@ -305,7 +313,7 @@ namespace Tins {
|
||||
* \return The cloned PDU.
|
||||
* \sa PDU::clone_packet
|
||||
*/
|
||||
PDU *clone_packet(uint8_t *ptr, uint32_t total_sz);
|
||||
PDU *clone_packet(const uint8_t *ptr, uint32_t total_sz);
|
||||
|
||||
private:
|
||||
struct arphdr {
|
||||
@@ -325,7 +333,7 @@ namespace Tins {
|
||||
*
|
||||
* \param arp_ptr The pointer to the arphdr.
|
||||
*/
|
||||
ARP(arphdr *arp_ptr);
|
||||
ARP(const arphdr *arp_ptr);
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
|
||||
@@ -131,9 +131,28 @@ namespace Tins {
|
||||
* \brief DHCP options struct.
|
||||
*/
|
||||
struct DHCPOption {
|
||||
uint8_t option, length;
|
||||
/**
|
||||
* \brief The option number.
|
||||
*/
|
||||
uint8_t option;
|
||||
/**
|
||||
* \brief The value's length in bytes.
|
||||
*/
|
||||
uint8_t length;
|
||||
/**
|
||||
* \brief The option's value.
|
||||
*/
|
||||
uint8_t *value;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of DHCPOption.
|
||||
*
|
||||
* The option's value is copied, therefore the user should
|
||||
* manually free any memory pointed by the "val" parameter.
|
||||
* \param opt The option number.
|
||||
* \param len The length of the option's value in bytes.
|
||||
* \param val The option's value.
|
||||
*/
|
||||
DHCPOption(uint8_t opt, uint8_t len, const uint8_t *val);
|
||||
};
|
||||
|
||||
@@ -201,7 +220,7 @@ namespace Tins {
|
||||
|
||||
/**
|
||||
* \brief Adds a domain name servers option.
|
||||
* \param routers A list of ip addresses in integer notation.
|
||||
* \param dns A list of ip addresses in integer notation.
|
||||
* \return True if the option was added successfully. \sa DHCP::add_option
|
||||
*/
|
||||
bool add_dns_options(const std::list<uint32_t> &dns);
|
||||
|
||||
@@ -66,6 +66,14 @@ namespace Tins {
|
||||
*/
|
||||
EthernetII(uint32_t iface_index, const uint8_t* mac_dst = 0, const uint8_t* mac_src = 0, PDU* child = 0);
|
||||
|
||||
/**
|
||||
* \brief Constructor which creates an EthernetII object from a buffer and adds all identifiable
|
||||
* PDUs found in the buffer as children of this one.
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
EthernetII(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/* Getters */
|
||||
/**
|
||||
* \brief Getter for the destination's mac address.
|
||||
@@ -88,7 +96,14 @@ namespace Tins {
|
||||
*/
|
||||
inline uint32_t iface() const { return this->_iface_index; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the payload_type
|
||||
* \return The payload type.
|
||||
*/
|
||||
uint16_t payload_type() const;
|
||||
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the destination's MAC.
|
||||
*
|
||||
@@ -177,11 +192,11 @@ namespace Tins {
|
||||
*/
|
||||
EthernetII(ethhdr *eth_ptr);
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
|
||||
ethhdr _eth;
|
||||
uint32_t _iface_index;
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
@@ -57,6 +57,14 @@ namespace Tins {
|
||||
*/
|
||||
ICMP(Flags flag = ECHO_REQUEST);
|
||||
|
||||
/**
|
||||
* \brief Constructor which creates an ICMP object from a buffer and adds all identifiable
|
||||
* PDUs found in the buffer as children of this one.
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
ICMP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Sets the code field.
|
||||
*
|
||||
@@ -273,7 +281,7 @@ namespace Tins {
|
||||
* \return The cloned PDU.
|
||||
* \sa PDU::clone_packet
|
||||
*/
|
||||
PDU *clone_packet(uint8_t *ptr, uint32_t total_sz);
|
||||
PDU *clone_packet(const uint8_t *ptr, uint32_t total_sz);
|
||||
private:
|
||||
static uint16_t global_id, global_seq;
|
||||
|
||||
@@ -298,7 +306,7 @@ namespace Tins {
|
||||
*
|
||||
* \param ptr The icmphdr to clone.
|
||||
*/
|
||||
ICMP(icmphdr *ptr);
|
||||
ICMP(const icmphdr *ptr);
|
||||
|
||||
/** \brief Serialices this ICMP PDU.
|
||||
* \param buffer The buffer in which the PDU will be serialized.
|
||||
|
||||
10
include/ip.h
10
include/ip.h
@@ -100,6 +100,14 @@ namespace Tins {
|
||||
*/
|
||||
IP(uint32_t ip_dst = 0, uint32_t ip_src = 0, PDU *child = 0);
|
||||
|
||||
/**
|
||||
* \brief Constructor which creates an IP object from a buffer and adds all identifiable
|
||||
* PDUs found in the buffer as children of this one.
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
IP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Destructor for IP objects.
|
||||
*
|
||||
@@ -340,7 +348,7 @@ namespace Tins {
|
||||
* \return The cloned PDU.
|
||||
* \sa PDU::clone_packet
|
||||
*/
|
||||
PDU *clone_packet(uint8_t *ptr, uint32_t total_sz);
|
||||
PDU *clone_packet(const uint8_t *ptr, uint32_t total_sz);
|
||||
private:
|
||||
static const uint8_t DEFAULT_TTL;
|
||||
|
||||
|
||||
@@ -164,7 +164,7 @@ namespace Tins {
|
||||
* \param total_sz The size of the buffer.
|
||||
* \return The cloned PDU.
|
||||
*/
|
||||
virtual PDU *clone_packet(uint8_t *ptr, uint32_t total_sz) { return 0; }
|
||||
virtual PDU *clone_packet(const uint8_t *ptr, uint32_t total_sz) { return 0; }
|
||||
protected:
|
||||
/** \brief Serializes this PDU and propagates this action to child PDUs.
|
||||
*
|
||||
@@ -181,7 +181,7 @@ namespace Tins {
|
||||
* \param total_sz The total size of the buffer.
|
||||
* \return Returns the cloned PDU. Will be 0 if cloning failed.
|
||||
*/
|
||||
PDU *clone_inner_pdu(uint8_t *ptr, uint32_t total_sz);
|
||||
PDU *clone_inner_pdu(const uint8_t *ptr, uint32_t total_sz);
|
||||
|
||||
/** \brief Serializes this TCP PDU.
|
||||
*
|
||||
|
||||
@@ -37,14 +37,21 @@ namespace Tins {
|
||||
public:
|
||||
/** \brief Creates an instance of RawPDU.
|
||||
*
|
||||
* The payload is not copied by default, therefore it must be
|
||||
* manually freed by the user. If the payload was to be copied,
|
||||
* then the copy flag must be set to true.
|
||||
* The payload is copied, therefore the original payload's memory
|
||||
* must be freed by the user.
|
||||
* \param pload The payload which the RawPDU will contain.
|
||||
* \param size The size of the payload.
|
||||
* \param copy Flag indicating wether to copy the payload.
|
||||
*/
|
||||
RawPDU(uint8_t *pload, uint32_t size, bool copy = false);
|
||||
RawPDU(const uint8_t *pload, uint32_t size);
|
||||
|
||||
/** \brief Creates an instance of RawPDU.
|
||||
*
|
||||
* The payload is not copied in this constructor, therefore
|
||||
* it must be manually freed by the user.
|
||||
* \param pload The payload which the RawPDU will contain.
|
||||
* \param size The size of the payload.
|
||||
*/
|
||||
RawPDU(uint8_t *pload, uint32_t size);
|
||||
|
||||
/** \brief RawPDU destructor.
|
||||
*
|
||||
|
||||
111
include/sniffer.h
Normal file
111
include/sniffer.h
Normal file
@@ -0,0 +1,111 @@
|
||||
#ifndef __SNIFFER_H
|
||||
#define __SNIFFER_H
|
||||
|
||||
|
||||
#include <pcap.h>
|
||||
#include <string>
|
||||
#include "pdu.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \brief Abstract sniffed packet handler.
|
||||
*
|
||||
* Base class to handle sniffed packets when using Sniffer::sniff_loop.
|
||||
* Users should either inherit this class, or use the template class
|
||||
* SnifferHandler to provide their own handlers.
|
||||
*/
|
||||
class AbstractSnifferHandler {
|
||||
public:
|
||||
/**
|
||||
* \brief AbstractSnifferHandler destructor.
|
||||
*/
|
||||
virtual ~AbstractSnifferHandler() { }
|
||||
/**
|
||||
* \brief Handle a captured PDU.
|
||||
* \return Should return false if no more sniffing is required.
|
||||
*/
|
||||
virtual bool handle(PDU *pdu) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Sniffer class can be used to sniff packets using filters.
|
||||
*/
|
||||
class Sniffer {
|
||||
public:
|
||||
/**
|
||||
* \brief Creates an instance of sniffer.
|
||||
* \param device The device which will be sniffed.
|
||||
* \param max_packet_size The maximum packet size to be read.
|
||||
*/
|
||||
Sniffer(const std::string &device, unsigned max_packet_size);
|
||||
|
||||
/**
|
||||
* \brief Sniffer destructor.
|
||||
* This frees all memory used by the pcap handle.
|
||||
*/
|
||||
~Sniffer();
|
||||
|
||||
/**
|
||||
* \brief Compiles a filter and uses it to capture one packet.
|
||||
*
|
||||
* This method should be used only when expecting few packets.
|
||||
* It's innefficient since it recompiles the filter every time it
|
||||
* is called. To reuse a filter and sniff more efficiently, use
|
||||
* Sniffer::sniff_loop.
|
||||
* \param filter The filter which will be used while sniffing.
|
||||
* \return The captured packet, matching the given filter, 0 if an
|
||||
* error occured(probably compiling the filter).
|
||||
*/
|
||||
PDU *next_pdu(const std::string &filter);
|
||||
|
||||
/**
|
||||
* \brief Starts a sniffing loop, using a callback object for every
|
||||
* sniffed packet.
|
||||
*
|
||||
* Handlers could be user-provided classes which inherit AbstractSnifferHandler,
|
||||
* or it could be a specific SnifferHandler specialization. This method deletes
|
||||
* packets after they are handled, therefore the handlers MUST NOT delete them.
|
||||
* \param filter The filter to use when sniffing.
|
||||
* \param cback_handler The callback handler object which should process packets.
|
||||
* \param max_packets The maximum amount of packets to sniff. 0 == infinite.
|
||||
*/
|
||||
void sniff_loop(const std::string &filter, AbstractSnifferHandler *cback_handler, uint32_t max_packets = 0);
|
||||
private:
|
||||
bool compile_set_filter(const std::string &filter, bpf_program &prog);
|
||||
|
||||
static void callback_handler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
|
||||
|
||||
pcap_t *handle;
|
||||
bpf_u_int32 ip, mask;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Concrete implementation of AbstractSnifferHandler.
|
||||
*
|
||||
* This class is instantiated using a pointer to the actual handler.
|
||||
* Every time a packet is sniffed, operator() (PDU*) will be called on
|
||||
* the given pointer. \sa AbstractSnifferHandler
|
||||
*/
|
||||
template<class T> class SnifferHandler : public AbstractSnifferHandler {
|
||||
public:
|
||||
/**
|
||||
* Creates an instance of SnifferHandler.
|
||||
* \param ptr The pointer to the actual handler.
|
||||
*/
|
||||
SnifferHandler(T *ptr) : handler(ptr) { }
|
||||
|
||||
/**
|
||||
* \brief The overriden AbstractSnifferHandler::handle.
|
||||
* \param pdu The sniffed PDU.
|
||||
* \return False if no more sniffing is required, otherwise true.
|
||||
*/
|
||||
bool handle(PDU *pdu) {
|
||||
return (*handler)(pdu);
|
||||
}
|
||||
private:
|
||||
T *handler;
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -78,15 +78,21 @@ namespace Tins {
|
||||
* \param dport Destination port.
|
||||
* \param sport Source port.
|
||||
* */
|
||||
|
||||
TCP(uint16_t dport = 0, uint16_t sport = 0);
|
||||
|
||||
/**
|
||||
* \brief Constructor which creates an TCP object from a buffer and adds all identifiable
|
||||
* PDUs found in the buffer as children of this one.
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
TCP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief TCP destructor.
|
||||
*
|
||||
* Destructs the TCP instance. Does not free the payload.
|
||||
* */
|
||||
|
||||
~TCP();
|
||||
|
||||
/**
|
||||
@@ -145,6 +151,16 @@ namespace Tins {
|
||||
*/
|
||||
inline uint8_t data_offset() const { return this->_tcp.doff; }
|
||||
|
||||
/**
|
||||
* \brief Gets the value of a flag.
|
||||
*
|
||||
* \param tcp_flag The polled flag.
|
||||
* \return The value of the flag.
|
||||
*/
|
||||
uint8_t get_flag(Flags tcp_flag);
|
||||
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the destination port field.
|
||||
*
|
||||
|
||||
@@ -34,15 +34,24 @@ namespace Tins {
|
||||
*/
|
||||
class UDP : public PDU {
|
||||
public:
|
||||
/** \brief UDP constructor.
|
||||
/**
|
||||
* \brief UDP constructor.
|
||||
*
|
||||
* Creates an instance of UDP. Destination and source port can
|
||||
* be provided, otherwise both will be 0.
|
||||
* \param dport Destination port.
|
||||
* \param sport Source port.
|
||||
* \param child The child PDU(optional).
|
||||
* */
|
||||
UDP(uint16_t dport = 0, uint16_t sport = 0, PDU *child = 0);
|
||||
|
||||
/**
|
||||
* \brief Constructor which creates an UDP object from a buffer and adds all identifiable
|
||||
* PDUs found in the buffer as children of this one.
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
UDP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/** \brief Returns the destination port
|
||||
*/
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace Tins {
|
||||
*
|
||||
* If the lookup fails, false will be returned, true otherwise.
|
||||
* \param iface The interface from which to extract the identifier.
|
||||
* \param flag The interface id will be returned in this parameter.
|
||||
* \param id The interface id will be returned in this parameter.
|
||||
*/
|
||||
bool interface_id(const std::string &iface, uint32_t &id);
|
||||
|
||||
|
||||
132
src/arp.cpp
132
src/arp.cpp
@@ -31,66 +31,9 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
Tins::PDU* Tins::ARP::make_arp_request(const std::string& iface,
|
||||
const std::string& target,
|
||||
const std::string& sender,
|
||||
const uint8_t* hw_snd) {
|
||||
uint32_t target_ip = Tins::Utils::resolve_ip(target);
|
||||
uint32_t sender_ip = Tins::Utils::resolve_ip(sender);
|
||||
return make_arp_request(iface, target_ip, sender_ip, hw_snd);
|
||||
}
|
||||
|
||||
Tins::PDU* Tins::ARP::make_arp_request(const std::string& iface,
|
||||
uint32_t target,
|
||||
uint32_t sender,
|
||||
const uint8_t* 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->opcode(REQUEST);
|
||||
|
||||
/* Create the EthernetII PDU with the ARP PDU as its inner PDU */
|
||||
EthernetII* eth = new EthernetII(iface, Tins::EthernetII::BROADCAST, hw_snd, arp);
|
||||
return eth;
|
||||
}
|
||||
|
||||
Tins::PDU* Tins::ARP::make_arp_reply(const string& iface,
|
||||
const string& target,
|
||||
const string& sender,
|
||||
const uint8_t* hw_tgt,
|
||||
const uint8_t* hw_snd) {
|
||||
|
||||
uint32_t target_ip = Tins::Utils::resolve_ip(target);
|
||||
uint32_t sender_ip = Tins::Utils::resolve_ip(sender);
|
||||
return make_arp_reply(iface, target_ip, sender_ip, hw_tgt, hw_snd);
|
||||
}
|
||||
|
||||
Tins::PDU* Tins::ARP::make_arp_reply(const string& iface,
|
||||
uint32_t target,
|
||||
uint32_t sender,
|
||||
const uint8_t* hw_tgt,
|
||||
const uint8_t* hw_snd) {
|
||||
|
||||
/* Create ARP packet and set its attributes */
|
||||
ARP* arp = new ARP();
|
||||
arp->target_ip_addr(target);
|
||||
arp->sender_ip_addr(sender);
|
||||
arp->target_hw_addr(hw_tgt);
|
||||
arp->sender_hw_addr(hw_snd);
|
||||
arp->opcode(REPLY);
|
||||
|
||||
/* Create the EthernetII PDU with the ARP PDU as its inner PDU */
|
||||
EthernetII* eth = new EthernetII(iface, hw_tgt, hw_snd, arp);
|
||||
return eth;
|
||||
}
|
||||
|
||||
Tins::ARP::ARP(uint32_t target_ip, uint32_t sender_ip, const uint8_t *target_hw, const uint8_t *sender_hw) : PDU(0x0608) {
|
||||
std::memset(&_arp, 0, sizeof(arphdr));
|
||||
memset(&_arp, 0, sizeof(arphdr));
|
||||
hw_addr_format(1);
|
||||
prot_addr_format(0x0800);
|
||||
hw_addr_length(6);
|
||||
@@ -103,7 +46,16 @@ Tins::ARP::ARP(uint32_t target_ip, uint32_t sender_ip, const uint8_t *target_hw,
|
||||
target_hw_addr(target_hw);
|
||||
}
|
||||
|
||||
Tins::ARP::ARP(arphdr *arp_ptr) : PDU(Utils::net_to_host_s(0x0806)) {
|
||||
Tins::ARP::ARP(const uint8_t *buffer, uint32_t total_sz) : PDU(0x0608) {
|
||||
if(total_sz < sizeof(arphdr))
|
||||
throw std::runtime_error("Not enought size for an ARP header in the buffer.");
|
||||
memcpy(&_arp, buffer, sizeof(arphdr));
|
||||
total_sz -= sizeof(arphdr);
|
||||
if(total_sz)
|
||||
inner_pdu(new RawPDU(buffer + sizeof(arphdr), total_sz));
|
||||
}
|
||||
|
||||
Tins::ARP::ARP(const arphdr *arp_ptr) : PDU(Utils::net_to_host_s(0x0806)) {
|
||||
memcpy(&_arp, arp_ptr, sizeof(arphdr));
|
||||
}
|
||||
|
||||
@@ -188,10 +140,10 @@ bool Tins::ARP::matches_response(uint8_t *ptr, uint32_t total_sz) {
|
||||
return arp_ptr->ar_sip == _arp.ar_tip && arp_ptr->ar_tip == _arp.ar_sip;
|
||||
}
|
||||
|
||||
Tins::PDU *Tins::ARP::clone_packet(uint8_t *ptr, uint32_t total_sz) {
|
||||
Tins::PDU *Tins::ARP::clone_packet(const uint8_t *ptr, uint32_t total_sz) {
|
||||
if(total_sz < sizeof(arphdr))
|
||||
return 0;
|
||||
arphdr *arp_ptr = (arphdr*)ptr;
|
||||
const arphdr *arp_ptr = (arphdr*)ptr;
|
||||
PDU *child = 0, *cloned;
|
||||
if(total_sz > sizeof(arphdr)) {
|
||||
if((child = PDU::clone_inner_pdu(ptr + sizeof(arphdr), total_sz - sizeof(arphdr))) == 0)
|
||||
@@ -201,3 +153,61 @@ Tins::PDU *Tins::ARP::clone_packet(uint8_t *ptr, uint32_t total_sz) {
|
||||
cloned->inner_pdu(child);
|
||||
return cloned;
|
||||
}
|
||||
|
||||
Tins::PDU* Tins::ARP::make_arp_request(const string& iface,
|
||||
const string& target,
|
||||
const string& sender,
|
||||
const uint8_t* hw_snd) {
|
||||
uint32_t target_ip = Tins::Utils::resolve_ip(target);
|
||||
uint32_t sender_ip = Tins::Utils::resolve_ip(sender);
|
||||
return make_arp_request(iface, target_ip, sender_ip, hw_snd);
|
||||
}
|
||||
|
||||
Tins::PDU* Tins::ARP::make_arp_request(const std::string& iface,
|
||||
uint32_t target,
|
||||
uint32_t sender,
|
||||
const uint8_t* 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->opcode(REQUEST);
|
||||
|
||||
/* Create the EthernetII PDU with the ARP PDU as its inner PDU */
|
||||
EthernetII* eth = new EthernetII(iface, Tins::EthernetII::BROADCAST, hw_snd, arp);
|
||||
return eth;
|
||||
}
|
||||
|
||||
Tins::PDU* Tins::ARP::make_arp_reply(const string& iface,
|
||||
const string& target,
|
||||
const string& sender,
|
||||
const uint8_t* hw_tgt,
|
||||
const uint8_t* hw_snd) {
|
||||
|
||||
uint32_t target_ip = Tins::Utils::resolve_ip(target);
|
||||
uint32_t sender_ip = Tins::Utils::resolve_ip(sender);
|
||||
return make_arp_reply(iface, target_ip, sender_ip, hw_tgt, hw_snd);
|
||||
}
|
||||
|
||||
Tins::PDU* Tins::ARP::make_arp_reply(const string& iface,
|
||||
uint32_t target,
|
||||
uint32_t sender,
|
||||
const uint8_t* hw_tgt,
|
||||
const uint8_t* hw_snd) {
|
||||
|
||||
/* Create ARP packet and set its attributes */
|
||||
ARP* arp = new ARP();
|
||||
arp->target_ip_addr(target);
|
||||
arp->sender_ip_addr(sender);
|
||||
arp->target_hw_addr(hw_tgt);
|
||||
arp->sender_hw_addr(hw_snd);
|
||||
arp->opcode(REPLY);
|
||||
|
||||
/* Create the EthernetII PDU with the ARP PDU as its inner PDU */
|
||||
EthernetII* eth = new EthernetII(iface, hw_tgt, hw_snd, arp);
|
||||
return eth;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <iostream> //borrame
|
||||
#include "utils.h"
|
||||
#include "dhcp.h"
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#include <stdexcept>
|
||||
#ifndef WIN32
|
||||
#include <net/ethernet.h>
|
||||
#include <netpacket/packet.h>
|
||||
@@ -29,6 +29,8 @@
|
||||
#endif
|
||||
#include "ethernetII.h"
|
||||
#include "rawpdu.h"
|
||||
#include "ip.h"
|
||||
#include "arp.h"
|
||||
#include "utils.h"
|
||||
|
||||
const uint8_t* Tins::EthernetII::BROADCAST = (const uint8_t*)"\xff\xff\xff\xff\xff\xff";
|
||||
@@ -54,10 +56,31 @@ Tins::EthernetII::EthernetII(uint32_t iface_index, const uint8_t* mac_dst, const
|
||||
this->_eth.payload_type = 0;
|
||||
}
|
||||
|
||||
Tins::EthernetII::EthernetII(const uint8_t *buffer, uint32_t total_sz) : PDU(ETHERTYPE_IP) {
|
||||
if(total_sz < sizeof(ethhdr))
|
||||
throw std::runtime_error("Not enought size for an ethernetII header in the buffer.");
|
||||
memcpy(&_eth, buffer, sizeof(ethhdr));
|
||||
PDU *next = 0;
|
||||
switch(payload_type()) {
|
||||
case ETHERTYPE_IP:
|
||||
next = new Tins::IP(buffer + sizeof(ethhdr), total_sz - sizeof(ethhdr));
|
||||
break;
|
||||
case ETHERTYPE_ARP:
|
||||
next = new Tins::ARP(buffer + sizeof(ethhdr), total_sz - sizeof(ethhdr));
|
||||
break;
|
||||
// Other protos plz
|
||||
}
|
||||
inner_pdu(next);
|
||||
}
|
||||
|
||||
Tins::EthernetII::EthernetII(ethhdr *eth_ptr) : PDU(ETHERTYPE_IP) {
|
||||
memcpy(&_eth, eth_ptr, sizeof(ethhdr));
|
||||
}
|
||||
|
||||
uint16_t Tins::EthernetII::payload_type() const {
|
||||
return Utils::net_to_host_s(_eth.payload_type);
|
||||
}
|
||||
|
||||
void Tins::EthernetII::dst_mac(const uint8_t* new_dst_mac) {
|
||||
memcpy(this->_eth.dst_mac, new_dst_mac, 6);
|
||||
}
|
||||
|
||||
21
src/icmp.cpp
21
src/icmp.cpp
@@ -19,12 +19,12 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#ifndef WIN32
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include "icmp.h"
|
||||
#include "rawpdu.h"
|
||||
#include "utils.h"
|
||||
@@ -48,7 +48,16 @@ Tins::ICMP::ICMP(Flags flag) : PDU(IPPROTO_ICMP) {
|
||||
};
|
||||
}
|
||||
|
||||
Tins::ICMP::ICMP(icmphdr *ptr) : PDU(IPPROTO_ICMP) {
|
||||
Tins::ICMP::ICMP(const uint8_t *buffer, uint32_t total_sz) : PDU(IPPROTO_ICMP) {
|
||||
if(total_sz < sizeof(icmphdr))
|
||||
throw std::runtime_error("Not enought size for an ICMP header in the buffer.");
|
||||
std::memcpy(&_icmp, buffer, sizeof(icmphdr));
|
||||
total_sz -= sizeof(icmphdr);
|
||||
if(total_sz)
|
||||
inner_pdu(new RawPDU(buffer + sizeof(icmphdr), total_sz));
|
||||
}
|
||||
|
||||
Tins::ICMP::ICMP(const icmphdr *ptr) : PDU(IPPROTO_ICMP) {
|
||||
std::memcpy(&_icmp, ptr, sizeof(icmphdr));
|
||||
}
|
||||
|
||||
@@ -177,10 +186,10 @@ bool Tins::ICMP::matches_response(uint8_t *ptr, uint32_t total_sz) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Tins::PDU *Tins::ICMP::clone_packet(uint8_t *ptr, uint32_t total_sz) {
|
||||
Tins::PDU *Tins::ICMP::clone_packet(const uint8_t *ptr, uint32_t total_sz) {
|
||||
if(total_sz < sizeof(icmphdr))
|
||||
return 0;
|
||||
icmphdr *icmp_ptr = (icmphdr*)ptr;
|
||||
const icmphdr *icmp_ptr = (icmphdr*)ptr;
|
||||
PDU *child = 0, *cloned;
|
||||
if(total_sz > sizeof(icmphdr)) {
|
||||
if((child = PDU::clone_inner_pdu(ptr + sizeof(icmphdr), total_sz - sizeof(icmphdr))) == 0)
|
||||
|
||||
31
src/ip.cpp
31
src/ip.cpp
@@ -19,12 +19,16 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#ifndef WIN32
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#include "ip.h"
|
||||
#include "tcp.h"
|
||||
#include "udp.h"
|
||||
#include "icmp.h"
|
||||
#include "rawpdu.h"
|
||||
#include "utils.h"
|
||||
|
||||
@@ -42,6 +46,29 @@ Tins::IP::IP(const string &ip_dst, const string &ip_src, PDU *child) : PDU(IPPRO
|
||||
|
||||
}
|
||||
|
||||
Tins::IP::IP(const uint8_t *buffer, uint32_t total_sz) : PDU(IPPROTO_IP) {
|
||||
if(total_sz < sizeof(iphdr))
|
||||
throw std::runtime_error("Not enought size for an IP header in the buffer.");
|
||||
std::memcpy(&_ip, buffer, sizeof(iphdr));
|
||||
/* Options... */
|
||||
buffer += head_len() * sizeof(uint32_t);
|
||||
total_sz -= head_len() * sizeof(uint32_t);
|
||||
switch(_ip.protocol) {
|
||||
case IPPROTO_TCP:
|
||||
inner_pdu(new Tins::TCP(buffer, total_sz));
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
inner_pdu(new Tins::UDP(buffer, total_sz));
|
||||
break;
|
||||
case IPPROTO_ICMP:
|
||||
inner_pdu(new Tins::ICMP(buffer, total_sz));
|
||||
break;
|
||||
default:
|
||||
inner_pdu(new Tins::RawPDU(buffer, total_sz));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Tins::IP::IP(const iphdr *ptr) : PDU(IPPROTO_IP) {
|
||||
std::memcpy(&_ip, ptr, sizeof(iphdr));
|
||||
/* Options... */
|
||||
@@ -241,10 +268,10 @@ bool Tins::IP::matches_response(uint8_t *ptr, uint32_t total_sz) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Tins::PDU *Tins::IP::clone_packet(uint8_t *ptr, uint32_t total_sz) {
|
||||
Tins::PDU *Tins::IP::clone_packet(const uint8_t *ptr, uint32_t total_sz) {
|
||||
if(total_sz < sizeof(iphdr))
|
||||
return 0;
|
||||
iphdr *ip_ptr = (iphdr*)ptr;
|
||||
const iphdr *ip_ptr = (iphdr*)ptr;
|
||||
uint32_t sz = ip_ptr->ihl * sizeof(uint32_t);
|
||||
if(total_sz < sz)
|
||||
return 0;
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream> //borrame
|
||||
#include "utils.h"
|
||||
#include "pdu.h"
|
||||
#include "rawpdu.h"
|
||||
@@ -69,7 +68,7 @@ void Tins::PDU::serialize(uint8_t *buffer, uint32_t total_sz, const PDU *parent)
|
||||
write_serialization(buffer, total_sz, parent);
|
||||
}
|
||||
|
||||
Tins::PDU *Tins::PDU::clone_inner_pdu(uint8_t *ptr, uint32_t total_sz) {
|
||||
Tins::PDU *Tins::PDU::clone_inner_pdu(const uint8_t *ptr, uint32_t total_sz) {
|
||||
PDU *child = 0;
|
||||
if(inner_pdu()) {
|
||||
child = inner_pdu()->clone_packet(ptr, total_sz);
|
||||
@@ -77,7 +76,7 @@ Tins::PDU *Tins::PDU::clone_inner_pdu(uint8_t *ptr, uint32_t total_sz) {
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
child = new RawPDU(ptr, total_sz, true);
|
||||
child = new RawPDU(ptr, total_sz);
|
||||
return child;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,11 +24,13 @@
|
||||
#include "rawpdu.h"
|
||||
|
||||
|
||||
Tins::RawPDU::RawPDU(uint8_t *pload, uint32_t size, bool copy) : PDU(255), _payload(pload), _payload_size(size), _owns_payload(copy) {
|
||||
if(copy) {
|
||||
_payload = new uint8_t[size];
|
||||
std::memcpy(_payload, pload, size);
|
||||
}
|
||||
Tins::RawPDU::RawPDU(const uint8_t *pload, uint32_t size) : PDU(255), _payload_size(size), _owns_payload(true) {
|
||||
_payload = new uint8_t[size];
|
||||
std::memcpy(_payload, pload, size);
|
||||
}
|
||||
|
||||
Tins::RawPDU::RawPDU(uint8_t *pload, uint32_t size) : PDU(255), _payload(pload), _payload_size(size), _owns_payload(false) {
|
||||
|
||||
}
|
||||
|
||||
Tins::RawPDU::~RawPDU() {
|
||||
|
||||
64
src/sniffer.cpp
Normal file
64
src/sniffer.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#include <stdexcept>
|
||||
#include "sniffer.h"
|
||||
#include "ethernetII.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
Tins::Sniffer::Sniffer(const string &device, unsigned max_packet_size) {
|
||||
char error[PCAP_ERRBUF_SIZE];
|
||||
if (pcap_lookupnet(device.c_str(), &ip, &mask, error) == -1)
|
||||
throw runtime_error(error);
|
||||
handle = pcap_open_live(device.c_str(), max_packet_size, 0, 0, error);
|
||||
if(!handle)
|
||||
throw runtime_error(error);
|
||||
}
|
||||
|
||||
Tins::Sniffer::~Sniffer() {
|
||||
if(handle)
|
||||
pcap_close(handle);
|
||||
}
|
||||
|
||||
bool Tins::Sniffer::compile_set_filter(const string &filter, bpf_program &prog) {
|
||||
return (pcap_compile(handle, &prog, filter.c_str(), 0, ip) != -1 && pcap_setfilter(handle, &prog) != -1);
|
||||
}
|
||||
|
||||
Tins::PDU *Tins::Sniffer::next_pdu(const string &filter) {
|
||||
bpf_program prog;
|
||||
if(!compile_set_filter(filter, prog))
|
||||
return 0;
|
||||
pcap_pkthdr header;
|
||||
PDU *ret = 0;
|
||||
while(!ret) {
|
||||
const u_char *content = pcap_next(handle, &header);
|
||||
try {
|
||||
ret = new EthernetII((const uint8_t*)content, header.caplen);
|
||||
}
|
||||
catch(...) {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
pcap_freecode(&prog);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Tins::Sniffer::sniff_loop(const std::string &filter, AbstractSnifferHandler *cback_handler, uint32_t max_packets) {
|
||||
bpf_program prog;
|
||||
if(compile_set_filter(filter, prog)) {
|
||||
pcap_loop(handle, max_packets, Sniffer::callback_handler, (u_char*)cback_handler);
|
||||
pcap_freecode(&prog);
|
||||
}
|
||||
}
|
||||
|
||||
// Static
|
||||
void Tins::Sniffer::callback_handler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) {
|
||||
try {
|
||||
PDU *pdu = new EthernetII((const uint8_t*)packet, header->caplen);
|
||||
reinterpret_cast<AbstractSnifferHandler*>(args)->handle(pdu);
|
||||
delete pdu;
|
||||
}
|
||||
catch(...) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
45
src/tcp.cpp
45
src/tcp.cpp
@@ -19,6 +19,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#ifndef WIN32
|
||||
@@ -41,6 +42,18 @@ Tins::TCP::TCP(uint16_t dport, uint16_t sport) : PDU(IPPROTO_TCP), _options_size
|
||||
this->check(0);
|
||||
}
|
||||
|
||||
Tins::TCP::TCP(const uint8_t *buffer, uint32_t total_sz) : PDU(IPPROTO_TCP) {
|
||||
if(total_sz < sizeof(tcphdr))
|
||||
throw std::runtime_error("Not enought size for an TCP header in the buffer.");
|
||||
std::memcpy(&_tcp, buffer, sizeof(tcphdr));
|
||||
|
||||
/* Options... */
|
||||
|
||||
total_sz -= sizeof(tcphdr);
|
||||
if(total_sz)
|
||||
inner_pdu(new RawPDU(buffer + sizeof(tcphdr), total_sz));
|
||||
}
|
||||
|
||||
Tins::TCP::~TCP() {
|
||||
for(unsigned i(0); i < _options.size(); ++i)
|
||||
delete[] _options[i].data;
|
||||
@@ -92,6 +105,38 @@ void Tins::TCP::set_timestamp(uint32_t value, uint32_t reply) {
|
||||
add_option(TSOPT, 8, (uint8_t*)&buffer);
|
||||
}
|
||||
|
||||
uint8_t Tins::TCP::get_flag(Flags tcp_flag) {
|
||||
switch(tcp_flag) {
|
||||
case FIN:
|
||||
return _tcp.fin;
|
||||
break;
|
||||
case SYN:
|
||||
return _tcp.syn;
|
||||
break;
|
||||
case RST:
|
||||
return _tcp.rst;
|
||||
break;
|
||||
case PSH:
|
||||
return _tcp.psh;
|
||||
break;
|
||||
case ACK:
|
||||
return _tcp.ack;
|
||||
break;
|
||||
case URG:
|
||||
return _tcp.urg;
|
||||
break;
|
||||
case ECE:
|
||||
return _tcp.ece;
|
||||
break;
|
||||
case CWR:
|
||||
return _tcp.cwr;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
void Tins::TCP::set_flag(Flags tcp_flag, uint8_t value) {
|
||||
switch(tcp_flag) {
|
||||
case FIN:
|
||||
|
||||
14
src/udp.cpp
14
src/udp.cpp
@@ -19,11 +19,12 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#ifndef WIN32
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include "utils.h"
|
||||
#include "udp.h"
|
||||
#include "ip.h"
|
||||
@@ -36,6 +37,15 @@ Tins::UDP::UDP(uint16_t dport, uint16_t sport, PDU *child) : PDU(IPPROTO_UDP, ch
|
||||
_udp.len = 0;
|
||||
}
|
||||
|
||||
Tins::UDP::UDP(const uint8_t *buffer, uint32_t total_sz) : PDU(IPPROTO_UDP) {
|
||||
if(total_sz < sizeof(udphdr))
|
||||
throw std::runtime_error("Not enought size for an UDP header in the buffer.");
|
||||
std::memcpy(&_udp, buffer, sizeof(udphdr));
|
||||
total_sz -= sizeof(udphdr);
|
||||
if(total_sz)
|
||||
inner_pdu(new RawPDU(buffer + sizeof(udphdr), total_sz));
|
||||
}
|
||||
|
||||
void Tins::UDP::payload(uint8_t *new_payload, uint32_t new_payload_size) {
|
||||
inner_pdu(new RawPDU(new_payload, new_payload_size));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user