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

PacketSender now throws on error. Fixed the documentation on several header files.

This commit is contained in:
Matias Fontanini
2012-10-19 12:01:34 -03:00
parent 15b58b4f37
commit abaa2bf926
20 changed files with 251 additions and 176 deletions

View File

@@ -19,7 +19,7 @@ portscan:
$(CXX) portscan.cpp -o portscan $(CXXFLAGS) $(LDFLAGS) -lpthread
traceroute:
$(CXX) traceroute.cpp -o traceroute -std=c++0x $(CXXFLAGS) $(LDFLAGS)
$(CXX) traceroute.cpp -o traceroute -std=c++0x $(CXXFLAGS) $(LDFLAGS) -lpthread
.cpp.o:
$(CXX) $(CXXFLAGS) $(INCLUDE) $< -o $@

View File

@@ -80,8 +80,8 @@ int do_arp_spoofing(NetworkInterface iface, IPv4Address gw, IPv4Address victim,
EthernetII to_victim(iface, victim_hw, info.hw_addr, victim_arp);
while(true) {
// Just send them once every 5 seconds.
if(!sender.send(to_gw) || !sender.send(to_victim))
return 7;
sender.send(to_gw);
sender.send(to_victim);
sleep(5);
}
}
@@ -114,6 +114,12 @@ int main(int argc, char *argv[]) {
cout << ex.what() << endl;
return 3;
}
return do_arp_spoofing(iface, gw, victim, info);
try {
return do_arp_spoofing(iface, gw, victim, info);
}
catch(std::runtime_error &ex) {
std::cout << "Runtime error: " << ex.what() << std::endl;
return 7;
}
}

View File

@@ -76,6 +76,7 @@ private:
// ICMPs are icmp-requests by default
IP ip(addr, iface.addresses().ip_addr, new ICMP());
// We'll find at most 10 hops.
for(auto i = 1; i <= 10; ++i) {
// Set this "unique" id
ip.id(i);

View File

@@ -38,6 +38,7 @@
namespace Tins {
class NetworkInterface;
class EthernetII;
/**
* \brief Class that represents an ARP PDU.
@@ -91,63 +92,63 @@ namespace Tins {
/**
* \brief Getter for the sender's hardware address.
*
* \return Returns the sender's hardware address in an uint8_t*.
* \return The sender hardware address.
*/
hwaddress_type sender_hw_addr() const { return _arp.ar_sha; }
/**
* \brief Getter for the sender's IP address.
*
* \return Returns the sender's IP address in an uint32_t.
* \return The sender IP address.
*/
ipaddress_type sender_ip_addr() const { return ipaddress_type(_arp.ar_sip); }
/**
* \brief Getter for the target's hardware address.
*
* \return Returns the target's hardware address in an uint8_t*.
* \return The target hardware address.
*/
hwaddress_type target_hw_addr() const { return _arp.ar_tha; }
/**
* \brief Getter for the target's IP address.
*
* \return Returns the target's IP address in an uint32_t.
* \return The target IP address.
*/
ipaddress_type target_ip_addr() const { return ipaddress_type(_arp.ar_tip); }
/**
* \brief Getter for the hardware address format.
*
* \return Returns the hardware address' format in an uint16_t.
* \return The hardware address format.
*/
uint16_t hw_addr_format() const { return Endian::be_to_host(_arp.ar_hrd); }
/**
* \brief Getter for the protocol address format.
*
* \return Returns the protocol address' format in an uint16_t.
* \return The protocol address format.
*/
uint16_t prot_addr_format() const { return Endian::be_to_host(_arp.ar_pro); }
/**
* \brief Getter for the hardware address length.
*
* \return Returns the hardware address' length in an uint8_t.
* \return The hardware address length.
*/
uint8_t hw_addr_length() const { return _arp.ar_hln; }
/**
* \brief Getter for the protocol address length.
*
* \return Returns the protocol address' length in an uint8_t.
* \return The protocol address length.
*/
uint8_t prot_addr_length() const { return _arp.ar_pln; }
/**
* \brief Getter for the ARP opcode.
*
* \return Returns the ARP opcode in an uint16_t.
* \return The ARP opcode.
*/
uint16_t opcode() const { return Endian::be_to_host(_arp.ar_op); }
@@ -161,56 +162,56 @@ namespace Tins {
/**
* \brief Setter for the sender's hardware address.
*
* \param new_snd_hw_addr uint8_t array containing the new sender's hardware address.
* \param new_snd_hw_addr The new sender hardware address.
*/
void sender_hw_addr(const hwaddress_type &new_snd_hw_addr);
/**
* \brief Setter for the sender's IP address.
*
* \param new_snd_ip_addr IPv4Address containing the new sender's IP address.
* \param new_snd_ip_addr The new sender IP address.
*/
void sender_ip_addr(ipaddress_type new_snd_ip_addr);
/**
* \brief Setter for the target's hardware address.
*
* \param new_tgt_hw_addr uint8_t array containing the new target's hardware address.
* \param new_tgt_hw_addr The new target hardware address.
*/
void target_hw_addr(const hwaddress_type &new_tgt_hw_addr);
/**
* \brief Setter for the target's IP address.
*
* \param new_tgt_ip_addr IPv4Address containing the new target's IP address.
* \param new_tgt_ip_addr The new target IP address.
*/
void target_ip_addr(ipaddress_type new_tgt_ip_addr);
/**
* \brief Setter for the hardware address format.
*
* \param new_hw_addr_fmt uint16_t with the new hardware address' format.
* \param new_hw_addr_fmt The new hardware address format.
*/
void hw_addr_format(uint16_t new_hw_addr_fmt);
/**
* \brief Setter for the protocol address format.
*
* \param new_prot_addr_fmt uint16_t with the new protocol address' format.
* \param new_prot_addr_fmt The new protocol address format.
*/
void prot_addr_format(uint16_t new_prot_addr_fmt);
/**
* \brief Setter for the hardware address length.
*
* \param new_hw_addr_len uint8_t with the new hardware address' length.
* \param new_hw_addr_len The new hardware address length.
*/
void hw_addr_length(uint8_t new_hw_addr_len);
/**
* \brief Setter for the protocol address length.
*
* \param new_prot_addr_len uint8_t with the new protocol address' length.
* \param new_prot_addr_len The new protocol address length.
*/
void prot_addr_length(uint8_t new_prot_addr_len);
@@ -237,9 +238,9 @@ namespace Tins {
* \param target IPv4Address with the target's IP.
* \param sender IPv4Address with the sender's IP.
* \param hw_snd uint8_t array of 6 bytes containing the sender's hardware address.
* \return Returns a PDU* to the new Layer 2 PDU containing the ARP Request.
* \return Returns a EthernetII containing the ARP Request.
*/
static PDU* make_arp_request(const NetworkInterface& iface, ipaddress_type target,
static EthernetII make_arp_request(const NetworkInterface& iface, ipaddress_type target,
ipaddress_type sender, const hwaddress_type &hw_snd = hwaddress_type());
/**
@@ -253,9 +254,9 @@ namespace Tins {
* \param sender IPv4Address with the sender's IP.
* \param hw_tgt uint8_t array of 6 bytes containing the target's hardware address.
* \param hw_snd uint8_t array of 6 bytes containing the sender's hardware address.
* \return Returns a PDU* to the new Layer 2 PDU containing the ARP Replay.
* \return Returns an EthetnetII containing the ARP Replay.
*/
static PDU* make_arp_reply(const NetworkInterface& iface, ipaddress_type target,
static EthernetII make_arp_reply(const NetworkInterface& iface, ipaddress_type target,
ipaddress_type sender, const hwaddress_type &hw_tgt = hwaddress_type(),
const hwaddress_type &hw_snd = hwaddress_type());

View File

@@ -386,7 +386,7 @@ namespace Tins {
/**
* \sa PDU::send()
*/
bool send(PacketSender &sender);
void send(PacketSender &sender);
#endif // WIN32
/**

View File

@@ -157,7 +157,7 @@ namespace Tins {
/**
* \sa PDU::send()
*/
bool send(PacketSender &sender);
void send(PacketSender &sender);
#endif // WIN32
/** \brief Check wether ptr points to a valid response for this PDU.

View File

@@ -66,11 +66,11 @@ namespace Tins {
* destination's and source's MAC.
*
* \param iface string containing the interface's name from where to send the packet.
* \param dst_hw_addr uint8_t array of 6 bytes containing the destination's MAC(optional).
* \param src_hw_addr uint8_t array of 6 bytes containing the source's MAC(optional).
* \param child PDU* with the PDU contained by the ethernet PDU (optional).
* \param dst_hw_addr The destination hardware address.
* \param src_hw_addr The source hardware address.
* \param child The PDU which will be set as the inner PDU.
*/
IEEE802_3(const NetworkInterface& iface,
IEEE802_3(const NetworkInterface& iface = NetworkInterface(),
const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type(),
PDU* child = 0);
@@ -85,23 +85,23 @@ namespace Tins {
/* Getters */
/**
* \brief Getter for the destination's mac address.
* \brief Getter for the destination hardware address.
*
* \return Returns the destination's mac address as a constant uint8_t pointer.
* \return The destination hardware address.
*/
address_type dst_addr() const { return _eth.dst_mac; }
/**
* \brief Getter for the source's mac address.
* \brief Getter for the source hardware address.
*
* \return Returns the source's mac address as a constant uint8_t pointer.
* \return The source hardware address.
*/
address_type src_addr() const { return _eth.src_mac; }
/**
* \brief Getter for the interface.
*
* \return Returns the interface's index as an uint32_t.
* \return The network interface.
*/
const NetworkInterface &iface() const { return this->_iface; }
@@ -114,25 +114,25 @@ namespace Tins {
/* Setters */
/**
* \brief Setter for the destination's MAC.
* \brief Setter for the destination hardware address.
*
* \param new_dst_mac uint8_t array of 6 bytes containing the new destination's MAC.
* \param new_dst_mac The new destination hardware address.
*/
void dst_addr(const address_type &new_dst_mac);
/**
* \brief Setter for the source's MAC.
* \brief Setter for the source hardware address.
*
* \param new_src_mac uint8_t array of 6 bytes containing the new source's MAC.
* \param new_src_mac The new source hardware address.
*/
void src_addr(const address_type &new_src_mac);
/**
* \brief Setter for the interface.
*
* \param new_iface_index uint32_t containing the new interface index.
* \param new_iface The interface in which to send this PDU.
*/
void iface(const NetworkInterface &new_iface_index);
void iface(const NetworkInterface &new_iface);
/**
* \brief Setter for the length field.
@@ -154,7 +154,7 @@ namespace Tins {
/**
* \sa PDU::send()
*/
bool send(PacketSender &sender);
void send(PacketSender &sender);
#endif // WIN32
/** \brief Check wether ptr points to a valid response for this PDU.
@@ -180,7 +180,8 @@ namespace Tins {
*/
PDUType pdu_type() const { return PDU::IEEE802_3; }
/** \brief Clones this pdu, filling the corresponding header with data
/**
* \brief Clones this pdu, filling the corresponding header with data
* extracted from a buffer.
*
* \param ptr The pointer to the from from which the data will be extracted.

View File

@@ -318,7 +318,7 @@ namespace Tins {
/**
* \brief Setter for the header length field.
*
* \param new_head_len uint8_t with the new header length.
* \param new_head_len The new header length.
*/
void head_len(small_uint<4> new_head_len);
@@ -533,7 +533,7 @@ namespace Tins {
/**
* \sa PDU::send()
*/
bool send(PacketSender &sender);
void send(PacketSender &sender);
/**
* \brief Check wether ptr points to a valid response for this PDU.

View File

@@ -31,6 +31,8 @@
#define TINS_PACKET_SENDER_H
#include <string>
#include <stdexcept>
#include <vector>
#include <stdint.h>
#include <map>
@@ -48,11 +50,13 @@ namespace Tins {
*/
class PacketSender {
public:
/** \brief The default timeout for receive actions.
/**
* The default timeout for receive actions.
*/
static const uint32_t DEFAULT_TIMEOUT;
/** \brief Flags to indicate the socket type.
/**
* Flags to indicate the socket type.
*/
enum SocketType {
ETHER_SOCKET,
@@ -69,46 +73,62 @@ namespace Tins {
*/
PacketSender(uint32_t recv_timeout = DEFAULT_TIMEOUT, uint32_t usec = 0);
/** \brief PacketSender destructor.
/**
* \brief PacketSender destructor.
*
* This gracefully closes all open sockets.
*/
~PacketSender();
#ifndef WIN32
/** \brief Opens a layer y socket.
/**
* \brief Opens a layer 2 socket.
*
* \return Returns true if the socket was open successfully, false otherwise.
* If this operation fails, then a SocketOpenError will be thrown.
*/
bool open_l2_socket();
void open_l2_socket();
#endif // WIN32
/** \brief Opens a layer 3 socket, using the corresponding protocol
/**
* \brief Opens a layer 3 socket, using the corresponding protocol
* for the given flag.
*
* If this operation fails, then a SocketOpenError will be thrown.
* If the provided socket type is not valid, a InvalidSocketTypeError
* will be throw.
*
* \param type The type of socket which will be used to pick the protocol flag
* for this socket.
* \return Returns true if the socket was open successfully, false otherwise.
*/
bool open_l3_socket(SocketType type);
void open_l3_socket(SocketType type);
/** \brief Closes the socket associated with the given flag.
/**
* \brief Closes the socket associated with the given flag.
*
* \param flag
* \return Returns true if the socket was closed successfully, false otherwise.
* If the provided type is invalid, meaning no such open socket
* exists, a InvalidSocketTypeError is thrown.
*
* If any socket close errors are encountered, a SocketCloseError
* is thrown.
*
* \param type The type of the socket to be closed.
*/
bool close_socket(uint32_t flag);
void close_socket(SocketType type);
/** \brief Sends a PDU.
/**
* \brief Sends a PDU.
*
* This method is used to send PDUs. It opens the required socket(if it's not open yet).
* This method opens the appropriate socket, if it's not open yet,
* and sends the PDU on the open socket.
*
* \param pdu The PDU to send.
* \return Returns true if the PDU is sent successfully, false otherwise.
* If any send error occurs, then a SocketWriteError is thrown.
*
* \param pdu The PDU to be sent.
*/
bool send(PDU &pdu);
void send(PDU &pdu);
/** \brief Sends a PDU and waits for its response.
/**
* \brief Sends a PDU and waits for its response.
*
* This method is used to send PDUs and receive their response.
* It opens the required socket(if it's not open yet). This can be used
@@ -121,7 +141,8 @@ namespace Tins {
PDU *send_recv(PDU &pdu);
#ifndef WIN32
/** \brief Receives a layer 2 PDU response to a previously sent PDU.
/**
* \brief Receives a layer 2 PDU response to a previously sent PDU.
*
* This PacketSender will receive data from a raw socket, open using the corresponding flag,
* according to the given type of protocol, until a match for the given PDU is received.
@@ -133,20 +154,24 @@ namespace Tins {
*/
PDU *recv_l2(PDU &pdu, struct sockaddr *link_addr, uint32_t len_addr);
/** \brief Sends a level 2 PDU.
/**
* \brief Sends a level 2 PDU.
*
* This method sends a layer 2 PDU, using a raw socket, open using the corresponding flag,
* according to the given type of protocol.
* This method sends a layer 2 PDU, using a raw socket, open
* using the corresponding flag, according to the given type of
* protocol.
*
* If any socket write error occurs, a SocketWriteError is thrown.
*
* \param pdu The PDU to send.
* \param link_addr The sockaddr struct which will be used to send the PDU.
* \param len_addr The sockaddr struct length.
* \return Returns true if the PDU was successfully sent, false otherwise.
*/
bool send_l2(PDU &pdu, struct sockaddr* link_addr, uint32_t len_addr);
void send_l2(PDU &pdu, struct sockaddr* link_addr, uint32_t len_addr);
#endif // WIN32
/** \brief Receives a layer 3 PDU response to a previously sent PDU.
/**
* \brief Receives a layer 3 PDU response to a previously sent PDU.
*
* This PacketSender will receive data from a raw socket, open using the corresponding flag,
* according to the given type of protocol, until a match for the given PDU is received.
@@ -159,18 +184,20 @@ namespace Tins {
*/
PDU *recv_l3(PDU &pdu, struct sockaddr *link_addr, uint32_t len_addr, SocketType type);
/** \brief Sends a level 3 PDU.
/**
* \brief Sends a level 3 PDU.
*
* This method sends a layer 3 PDU, using a raw socket, open using the corresponding flag,
* according to the given type of protocol.
*
* If any socket write error occurs, a SocketWriteError is thrown.
*
* \param pdu The PDU to send.
* \param link_addr The sockaddr struct which will be used to send the PDU.
* \param len_addr The sockaddr struct length.
* \param type The socket protocol type.
* \return Returns true if the PDU was successfully sent, false otherwise.
*/
bool send_l3(PDU &pdu, struct sockaddr *link_addr, uint32_t len_addr, SocketType type);
void send_l3(PDU &pdu, struct sockaddr *link_addr, uint32_t len_addr, SocketType type);
private:
static const int INVALID_RAW_SOCKET;
@@ -185,6 +212,32 @@ namespace Tins {
SocketTypeMap _types;
uint32_t _timeout, _timeout_usec;
};
class SocketOpenError : public std::runtime_error {
public:
SocketOpenError(const std::string &msg)
: std::runtime_error(msg) { }
};
class SocketCloseError : public std::runtime_error {
public:
SocketCloseError(const std::string &msg)
: std::runtime_error(msg) { }
};
class SocketWriteError : public std::runtime_error {
public:
SocketWriteError(const std::string &msg)
: std::runtime_error(msg) { }
};
class InvalidSocketTypeError : public std::exception {
public:
const char *what() const throw() {
return "The provided socket type is invalid";
}
};
};
#endif // TINS_PACKET_SENDER_H

View File

@@ -215,7 +215,7 @@ namespace Tins {
* those methods.
* \param sender The PacketSender which will send the packet.
*/
virtual bool send(PacketSender &sender);
virtual void send(PacketSender &sender);
/** \brief Receives a matching response for this packet.
*

View File

@@ -127,7 +127,7 @@ namespace Tins {
/**
* \sa PDU::send()
*/
bool send(PacketSender &sender);
void send(PacketSender &sender);
/**
* \brief Setter for the version field.
@@ -280,12 +280,14 @@ namespace Tins {
* \brief Getter for the present bit fields.
*
* Use this method and masks created from the values taken from
* the PresentFlags enum to find out which fields are set. If any
* getter is used for a non-initialized field, the return value
* the PresentFlags enum to find out which fields are set.
* Accessing non-initialized fields, the behaviour is undefined
* will be undefined. It is only safe to use the getter of a field
* if its corresponding bit flag is set in the present field.
*/
PresentFlags present() const { return (PresentFlags)*(uint32_t*)(&_radio.it_len + 1); }
PresentFlags present() const {
return (PresentFlags)*(uint32_t*)(&_radio.it_len + 1);
}
/**
* \brief Returns the RadioTap frame's header length.

View File

@@ -132,8 +132,8 @@ PDU *ARP::clone_packet(const uint8_t *ptr, uint32_t total_sz) {
return cloned;
}
PDU* ARP::make_arp_request(const NetworkInterface& iface, ipaddress_type target,
ipaddress_type sender, const hwaddress_type &hw_snd)
EthernetII ARP::make_arp_request(const NetworkInterface& iface,
ipaddress_type target, ipaddress_type sender, const hwaddress_type &hw_snd)
{
/* Create ARP packet and set its attributes */
ARP* arp = new ARP();
@@ -143,11 +143,11 @@ PDU* ARP::make_arp_request(const NetworkInterface& iface, ipaddress_type target,
arp->opcode(REQUEST);
/* Create the EthernetII PDU with the ARP PDU as its inner PDU */
return new EthernetII(iface, EthernetII::BROADCAST, hw_snd, arp);
return EthernetII(iface, EthernetII::BROADCAST, hw_snd, arp);
}
PDU* ARP::make_arp_reply(const NetworkInterface& iface, ipaddress_type target,
ipaddress_type sender, const hwaddress_type &hw_tgt,
EthernetII ARP::make_arp_reply(const NetworkInterface& iface,
ipaddress_type target, ipaddress_type sender, const hwaddress_type &hw_tgt,
const hwaddress_type &hw_snd)
{
/* Create ARP packet and set its attributes */
@@ -155,7 +155,6 @@ PDU* ARP::make_arp_reply(const NetworkInterface& iface, ipaddress_type target,
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;
return EthernetII(iface, hw_tgt, hw_snd, arp);
}
}

View File

@@ -166,7 +166,10 @@ uint32_t Dot11::header_size() const {
}
#ifndef WIN32
bool Dot11::send(PacketSender &sender) {
void Dot11::send(PacketSender &sender) {
if(!_iface)
throw std::runtime_error("Interface has not been set");
struct sockaddr_ll addr;
memset(&addr, 0, sizeof(struct sockaddr_ll));
@@ -177,7 +180,7 @@ bool Dot11::send(PacketSender &sender) {
addr.sll_ifindex = _iface.id();
memcpy(&(addr.sll_addr), _header.addr1, 6);
return sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
}
#endif // WIN32

View File

@@ -104,7 +104,7 @@ uint32_t EthernetII::header_size() const {
}
#ifndef WIN32
bool EthernetII::send(PacketSender &sender) {
void EthernetII::send(PacketSender &sender) {
if(!_iface)
throw std::runtime_error("Interface has not been set");
struct sockaddr_ll addr;
@@ -117,7 +117,7 @@ bool EthernetII::send(PacketSender &sender) {
addr.sll_ifindex = _iface.id();
memcpy(&(addr.sll_addr), _eth.dst_mac, address_type::address_size);
return sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
}
#endif // WIN32

View File

@@ -88,7 +88,10 @@ uint32_t IEEE802_3::header_size() const {
}
#ifndef WIN32
bool IEEE802_3::send(PacketSender &sender) {
void IEEE802_3::send(PacketSender &sender) {
if(!_iface)
throw std::runtime_error("Interface has not been set");
struct sockaddr_ll addr;
memset(&addr, 0, sizeof(struct sockaddr_ll));
@@ -99,7 +102,7 @@ bool IEEE802_3::send(PacketSender &sender) {
addr.sll_ifindex = _iface.id();
memcpy(&(addr.sll_addr), _eth.dst_mac, sizeof(_eth.dst_mac));
return sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
}
#endif // WIN32

View File

@@ -332,7 +332,7 @@ uint32_t IP::header_size() const {
return sizeof(iphdr) + _padded_options_size;
}
bool IP::send(PacketSender& sender) {
void IP::send(PacketSender& sender) {
struct sockaddr_in link_addr;
PacketSender::SocketType type = PacketSender::IP_SOCKET;
link_addr.sin_family = AF_INET;
@@ -341,7 +341,7 @@ bool IP::send(PacketSender& sender) {
if(inner_pdu() && inner_pdu()->pdu_type() == PDU::ICMP)
type = PacketSender::ICMP_SOCKET;
return sender.send_l3(*this, (struct sockaddr*)&link_addr, sizeof(link_addr), type);
sender.send_l3(*this, (struct sockaddr*)&link_addr, sizeof(link_addr), type);
}
PDU *IP::recv_response(PacketSender &sender) {

View File

@@ -37,28 +37,39 @@
#include <linux/if_packet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <errno.h>
#else
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
#include <cassert>
#include <errno.h>
#include <cstring>
#include <ctime>
#include "pdu.h"
#include "packet_sender.h"
const int Tins::PacketSender::INVALID_RAW_SOCKET = -1;
const uint32_t Tins::PacketSender::DEFAULT_TIMEOUT = 2;
namespace Tins {
const int PacketSender::INVALID_RAW_SOCKET = -1;
const uint32_t PacketSender::DEFAULT_TIMEOUT = 2;
Tins::PacketSender::PacketSender(uint32_t recv_timeout, uint32_t usec) :
_sockets(SOCKETS_END, INVALID_RAW_SOCKET), _timeout(recv_timeout), _timeout_usec(usec) {
#ifndef WIN32
const char *make_error_string() {
return strerror(errno);
}
#else
#endif
PacketSender::PacketSender(uint32_t recv_timeout, uint32_t usec) :
_sockets(SOCKETS_END, INVALID_RAW_SOCKET), _timeout(recv_timeout),
_timeout_usec(usec)
{
_types[IP_SOCKET] = IPPROTO_RAW;
_types[ICMP_SOCKET] = IPPROTO_ICMP;
}
Tins::PacketSender::~PacketSender() {
PacketSender::~PacketSender() {
for(unsigned i(0); i < _sockets.size(); ++i) {
if(_sockets[i] != INVALID_RAW_SOCKET)
#ifndef WIN32
@@ -70,101 +81,95 @@ Tins::PacketSender::~PacketSender() {
}
#ifndef WIN32
bool Tins::PacketSender::open_l2_socket() {
if (_sockets[ETHER_SOCKET] != INVALID_RAW_SOCKET)
return true;
int sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sock == -1)
return false;
_sockets[ETHER_SOCKET] = sock;
return true;
void PacketSender::open_l2_socket() {
if (_sockets[ETHER_SOCKET] == INVALID_RAW_SOCKET) {
int sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sock == -1)
throw SocketOpenError(make_error_string());
_sockets[ETHER_SOCKET] = sock;
}
}
#endif // WIN32
bool Tins::PacketSender::open_l3_socket(SocketType type) {
void PacketSender::open_l3_socket(SocketType type) {
int socktype = find_type(type);
if(socktype == -1)
return false;
if(_sockets[type] != INVALID_RAW_SOCKET)
return true;
int sockfd;
sockfd = socket(AF_INET, SOCK_RAW, socktype);
if (sockfd < 0)
return false;
throw InvalidSocketTypeError();
if(_sockets[type] == INVALID_RAW_SOCKET) {
int sockfd;
sockfd = socket(AF_INET, SOCK_RAW, socktype);
if (sockfd < 0)
throw SocketOpenError(make_error_string());
const int on = 1;
const int on = 1;
#ifndef WIN32
typedef const void* option_ptr;
#else
typedef const char* option_ptr;
#endif
setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL,(option_ptr)&on,sizeof(on));
_sockets[type] = sockfd;
}
}
void PacketSender::close_socket(SocketType type) {
if(type >= SOCKETS_END || _sockets[type] == INVALID_RAW_SOCKET)
throw InvalidSocketTypeError();
#ifndef WIN32
typedef const void* option_ptr;
if(close(_sockets[type]) == -1)
throw SocketCloseError(make_error_string());
#else
typedef const char* option_ptr;
closesocket(_sockets[type]);
#endif
setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL,(option_ptr)&on,sizeof(on));
_sockets[type] = sockfd;
return true;
_sockets[type] = INVALID_RAW_SOCKET;
}
bool Tins::PacketSender::close_socket(uint32_t flag) {
if(flag >= SOCKETS_END || _sockets[flag] == INVALID_RAW_SOCKET)
return false;
#ifndef WIN32
close(_sockets[flag]);
#else
closesocket(_sockets[flag]);
#endif
_sockets[flag] = INVALID_RAW_SOCKET;
return true;
void PacketSender::send(PDU &pdu) {
pdu.send(*this);
}
bool Tins::PacketSender::send(PDU &pdu) {
return pdu.send(*this);
}
Tins::PDU *Tins::PacketSender::send_recv(PDU &pdu) {
if(!pdu.send(*this))
PDU *PacketSender::send_recv(PDU &pdu) {
try {
pdu.send(*this);
}
catch(std::runtime_error&) {
return 0;
}
return pdu.recv_response(*this);
}
#ifndef WIN32
bool Tins::PacketSender::send_l2(PDU &pdu, struct sockaddr* link_addr, uint32_t len_addr) {
if(!open_l2_socket())
return false;
void PacketSender::send_l2(PDU &pdu, struct sockaddr* link_addr, uint32_t len_addr) {
open_l2_socket();
int sock = _sockets[ETHER_SOCKET];
PDU::serialization_type buffer = pdu.serialize();
if(buffer.size() == 0)
return false;
bool ret_val = (sendto(sock, &buffer[0], buffer.size(), 0, link_addr, len_addr) != -1);
return ret_val;
if(!buffer.empty()) {
if(sendto(sock, &buffer[0], buffer.size(), 0, link_addr, len_addr) == -1)
throw SocketWriteError(make_error_string());
}
}
Tins::PDU *Tins::PacketSender::recv_l2(PDU &pdu, struct sockaddr *link_addr, uint32_t len_addr) {
if(!open_l2_socket())
return 0;
PDU *PacketSender::recv_l2(PDU &pdu, struct sockaddr *link_addr, uint32_t len_addr) {
open_l2_socket();
return recv_match_loop(_sockets[ETHER_SOCKET], pdu, link_addr, len_addr);
}
#endif // WIN32
Tins::PDU *Tins::PacketSender::recv_l3(PDU &pdu, struct sockaddr* link_addr, uint32_t len_addr, SocketType type) {
if(!open_l3_socket(type))
return 0;
PDU *PacketSender::recv_l3(PDU &pdu, struct sockaddr* link_addr, uint32_t len_addr, SocketType type) {
open_l3_socket(type);
return recv_match_loop(_sockets[type], pdu, link_addr, len_addr);
}
bool Tins::PacketSender::send_l3(PDU &pdu, struct sockaddr* link_addr, uint32_t len_addr, SocketType type) {
bool ret_val = true;
if(!open_l3_socket(type))
ret_val = false;
if (ret_val) {
int sock = _sockets[type];
PDU::serialization_type buffer = pdu.serialize();
ret_val = (sendto(sock, (const char*)&buffer[0], buffer.size(), 0, link_addr, len_addr) != -1);
}
return ret_val;
void PacketSender::send_l3(PDU &pdu, struct sockaddr* link_addr, uint32_t len_addr, SocketType type) {
open_l3_socket(type);
int sock = _sockets[type];
PDU::serialization_type buffer = pdu.serialize();
if(sendto(sock, (const char*)&buffer[0], buffer.size(), 0, link_addr, len_addr) == -1)
throw SocketWriteError(make_error_string());
}
Tins::PDU *Tins::PacketSender::recv_match_loop(int sock, PDU &pdu, struct sockaddr* link_addr, uint32_t addrlen) {
PDU *PacketSender::recv_match_loop(int sock, PDU &pdu, struct sockaddr* link_addr, uint32_t addrlen) {
fd_set readfds;
struct timeval timeout, end_time;
int read;
@@ -195,7 +200,7 @@ Tins::PDU *Tins::PacketSender::recv_match_loop(int sock, PDU &pdu, struct sockad
return 0;
}
int Tins::PacketSender::timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y) {
int PacketSender::timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y) {
/* Perform the carry for the later subtraction by updating y. */
if (x->tv_usec < y->tv_usec) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
@@ -218,10 +223,11 @@ int Tins::PacketSender::timeval_subtract (struct timeval *result, struct timeval
return x->tv_sec < y->tv_sec;
}
int Tins::PacketSender::find_type(SocketType type) {
int PacketSender::find_type(SocketType type) {
SocketTypeMap::iterator it = _types.find(type);
if(it == _types.end())
return -1;
else
return it->second;
}
}

View File

@@ -66,8 +66,8 @@ uint32_t PDU::size() const {
return sz;
}
bool PDU::send(PacketSender &) {
return false;
void PDU::send(PacketSender &) {
}
PDU *PDU::recv_response(PacketSender &) {

View File

@@ -222,7 +222,7 @@ uint32_t RadioTap::trailer_size() const {
return ((_flags & 0x10) != 0) ? sizeof(uint32_t) : 0;
}
bool RadioTap::send(PacketSender &sender) {
void RadioTap::send(PacketSender &sender) {
if(!_iface)
throw std::runtime_error("Interface has not been set");
@@ -241,7 +241,7 @@ bool RadioTap::send(PacketSender &sender) {
std::copy(dot11_addr.begin(), dot11_addr.end(), addr.sll_addr);
}
return sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
}
void RadioTap::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {

View File

@@ -39,8 +39,8 @@
#endif
#include "utils.h"
#include "pdu.h"
#include "ip.h"
#include "arp.h"
#include "ethernetII.h"
#include "endianness.h"
#include "network_interface.h"
#include "packet_sender.h"
@@ -114,8 +114,8 @@ bool Utils::resolve_hwaddr(const NetworkInterface &iface, IPv4Address ip,
{
IPv4Address my_ip;
NetworkInterface::Info info(iface.addresses());
std::auto_ptr<PDU> packet(ARP::make_arp_request(iface, ip, info.ip_addr, info.hw_addr));
std::auto_ptr<PDU> response(sender.send_recv(*packet));
EthernetII packet = ARP::make_arp_request(iface, ip, info.ip_addr, info.hw_addr);
std::auto_ptr<PDU> response(sender.send_recv(packet));
if(response.get()) {
ARP *arp_resp = response->find_pdu<ARP>();
if(arp_resp)
@@ -130,8 +130,8 @@ HWAddress<6> Utils::resolve_hwaddr(const NetworkInterface &iface, IPv4Address ip
{
IPv4Address my_ip;
NetworkInterface::Info info(iface.addresses());
std::auto_ptr<PDU> packet(ARP::make_arp_request(iface, ip, info.ip_addr, info.hw_addr));
std::auto_ptr<PDU> response(sender.send_recv(*packet));
EthernetII packet = ARP::make_arp_request(iface, ip, info.ip_addr, info.hw_addr);
std::auto_ptr<PDU> response(sender.send_recv(packet));
if(response.get()) {
const ARP *arp_resp = response->find_pdu<ARP>();
if(arp_resp)