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 $(CXX) portscan.cpp -o portscan $(CXXFLAGS) $(LDFLAGS) -lpthread
traceroute: traceroute:
$(CXX) traceroute.cpp -o traceroute -std=c++0x $(CXXFLAGS) $(LDFLAGS) $(CXX) traceroute.cpp -o traceroute -std=c++0x $(CXXFLAGS) $(LDFLAGS) -lpthread
.cpp.o: .cpp.o:
$(CXX) $(CXXFLAGS) $(INCLUDE) $< -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); EthernetII to_victim(iface, victim_hw, info.hw_addr, victim_arp);
while(true) { while(true) {
// Just send them once every 5 seconds. // Just send them once every 5 seconds.
if(!sender.send(to_gw) || !sender.send(to_victim)) sender.send(to_gw);
return 7; sender.send(to_victim);
sleep(5); sleep(5);
} }
} }
@@ -114,6 +114,12 @@ int main(int argc, char *argv[]) {
cout << ex.what() << endl; cout << ex.what() << endl;
return 3; 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 // ICMPs are icmp-requests by default
IP ip(addr, iface.addresses().ip_addr, new ICMP()); IP ip(addr, iface.addresses().ip_addr, new ICMP());
// We'll find at most 10 hops. // We'll find at most 10 hops.
for(auto i = 1; i <= 10; ++i) { for(auto i = 1; i <= 10; ++i) {
// Set this "unique" id // Set this "unique" id
ip.id(i); ip.id(i);

View File

@@ -38,6 +38,7 @@
namespace Tins { namespace Tins {
class NetworkInterface; class NetworkInterface;
class EthernetII;
/** /**
* \brief Class that represents an ARP PDU. * \brief Class that represents an ARP PDU.
@@ -91,63 +92,63 @@ namespace Tins {
/** /**
* \brief Getter for the sender's hardware address. * \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; } hwaddress_type sender_hw_addr() const { return _arp.ar_sha; }
/** /**
* \brief Getter for the sender's IP address. * \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); } ipaddress_type sender_ip_addr() const { return ipaddress_type(_arp.ar_sip); }
/** /**
* \brief Getter for the target's hardware address. * \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; } hwaddress_type target_hw_addr() const { return _arp.ar_tha; }
/** /**
* \brief Getter for the target's IP address. * \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); } ipaddress_type target_ip_addr() const { return ipaddress_type(_arp.ar_tip); }
/** /**
* \brief Getter for the hardware address format. * \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); } uint16_t hw_addr_format() const { return Endian::be_to_host(_arp.ar_hrd); }
/** /**
* \brief Getter for the protocol address format. * \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); } uint16_t prot_addr_format() const { return Endian::be_to_host(_arp.ar_pro); }
/** /**
* \brief Getter for the hardware address length. * \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; } uint8_t hw_addr_length() const { return _arp.ar_hln; }
/** /**
* \brief Getter for the protocol address length. * \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; } uint8_t prot_addr_length() const { return _arp.ar_pln; }
/** /**
* \brief Getter for the ARP opcode. * \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); } 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. * \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); void sender_hw_addr(const hwaddress_type &new_snd_hw_addr);
/** /**
* \brief Setter for the sender's IP address. * \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); void sender_ip_addr(ipaddress_type new_snd_ip_addr);
/** /**
* \brief Setter for the target's hardware address. * \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); void target_hw_addr(const hwaddress_type &new_tgt_hw_addr);
/** /**
* \brief Setter for the target's IP address. * \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); void target_ip_addr(ipaddress_type new_tgt_ip_addr);
/** /**
* \brief Setter for the hardware address format. * \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); void hw_addr_format(uint16_t new_hw_addr_fmt);
/** /**
* \brief Setter for the protocol address format. * \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); void prot_addr_format(uint16_t new_prot_addr_fmt);
/** /**
* \brief Setter for the hardware address length. * \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); void hw_addr_length(uint8_t new_hw_addr_len);
/** /**
* \brief Setter for the protocol address length. * \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); 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 target IPv4Address with the target's IP.
* \param sender IPv4Address with the sender'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. * \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()); 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 sender IPv4Address with the sender's IP.
* \param hw_tgt uint8_t array of 6 bytes containing the target's hardware address. * \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. * \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(), ipaddress_type sender, const hwaddress_type &hw_tgt = hwaddress_type(),
const hwaddress_type &hw_snd = hwaddress_type()); const hwaddress_type &hw_snd = hwaddress_type());

View File

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

View File

@@ -157,7 +157,7 @@ namespace Tins {
/** /**
* \sa PDU::send() * \sa PDU::send()
*/ */
bool send(PacketSender &sender); void send(PacketSender &sender);
#endif // WIN32 #endif // WIN32
/** \brief Check wether ptr points to a valid response for this PDU. /** \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. * destination's and source's MAC.
* *
* \param iface string containing the interface's name from where to send the packet. * \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 dst_hw_addr The destination hardware address.
* \param src_hw_addr uint8_t array of 6 bytes containing the source's MAC(optional). * \param src_hw_addr The source hardware address.
* \param child PDU* with the PDU contained by the ethernet PDU (optional). * \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 &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type(), const address_type &src_hw_addr = address_type(),
PDU* child = 0); PDU* child = 0);
@@ -85,23 +85,23 @@ namespace Tins {
/* Getters */ /* 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; } 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; } address_type src_addr() const { return _eth.src_mac; }
/** /**
* \brief Getter for the interface. * \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; } const NetworkInterface &iface() const { return this->_iface; }
@@ -114,25 +114,25 @@ namespace Tins {
/* Setters */ /* 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); 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); void src_addr(const address_type &new_src_mac);
/** /**
* \brief Setter for the interface. * \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. * \brief Setter for the length field.
@@ -154,7 +154,7 @@ namespace Tins {
/** /**
* \sa PDU::send() * \sa PDU::send()
*/ */
bool send(PacketSender &sender); void send(PacketSender &sender);
#endif // WIN32 #endif // WIN32
/** \brief Check wether ptr points to a valid response for this PDU. /** \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; } 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. * extracted from a buffer.
* *
* \param ptr The pointer to the from from which the data will be extracted. * \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. * \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); void head_len(small_uint<4> new_head_len);
@@ -533,7 +533,7 @@ namespace Tins {
/** /**
* \sa PDU::send() * \sa PDU::send()
*/ */
bool send(PacketSender &sender); void send(PacketSender &sender);
/** /**
* \brief Check wether ptr points to a valid response for this PDU. * \brief Check wether ptr points to a valid response for this PDU.

View File

@@ -31,6 +31,8 @@
#define TINS_PACKET_SENDER_H #define TINS_PACKET_SENDER_H
#include <string>
#include <stdexcept>
#include <vector> #include <vector>
#include <stdint.h> #include <stdint.h>
#include <map> #include <map>
@@ -48,11 +50,13 @@ namespace Tins {
*/ */
class PacketSender { class PacketSender {
public: public:
/** \brief The default timeout for receive actions. /**
* The default timeout for receive actions.
*/ */
static const uint32_t DEFAULT_TIMEOUT; static const uint32_t DEFAULT_TIMEOUT;
/** \brief Flags to indicate the socket type. /**
* Flags to indicate the socket type.
*/ */
enum SocketType { enum SocketType {
ETHER_SOCKET, ETHER_SOCKET,
@@ -69,46 +73,62 @@ namespace Tins {
*/ */
PacketSender(uint32_t recv_timeout = DEFAULT_TIMEOUT, uint32_t usec = 0); PacketSender(uint32_t recv_timeout = DEFAULT_TIMEOUT, uint32_t usec = 0);
/** \brief PacketSender destructor. /**
* \brief PacketSender destructor.
* *
* This gracefully closes all open sockets. * This gracefully closes all open sockets.
*/ */
~PacketSender(); ~PacketSender();
#ifndef WIN32 #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 #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. * 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 * \param type The type of socket which will be used to pick the protocol flag
* for this socket. * 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 * If the provided type is invalid, meaning no such open socket
* \return Returns true if the socket was closed successfully, false otherwise. * 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. * If any send error occurs, then a SocketWriteError is thrown.
* \return Returns true if the PDU is sent successfully, false otherwise. *
* \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. * 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 * 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); PDU *send_recv(PDU &pdu);
#ifndef WIN32 #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, * 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. * 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); 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, * This method sends a layer 2 PDU, using a raw socket, open
* according to the given type of protocol. * 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 pdu The PDU to send.
* \param link_addr The sockaddr struct which will be used to send the PDU. * \param link_addr The sockaddr struct which will be used to send the PDU.
* \param len_addr The sockaddr struct length. * \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 #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, * 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. * 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); 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, * This method sends a layer 3 PDU, using a raw socket, open using the corresponding flag,
* according to the given type of protocol. * according to the given type of protocol.
* *
* If any socket write error occurs, a SocketWriteError is thrown.
*
* \param pdu The PDU to send. * \param pdu The PDU to send.
* \param link_addr The sockaddr struct which will be used to send the PDU. * \param link_addr The sockaddr struct which will be used to send the PDU.
* \param len_addr The sockaddr struct length. * \param len_addr The sockaddr struct length.
* \param type The socket protocol type. * \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: private:
static const int INVALID_RAW_SOCKET; static const int INVALID_RAW_SOCKET;
@@ -185,6 +212,32 @@ namespace Tins {
SocketTypeMap _types; SocketTypeMap _types;
uint32_t _timeout, _timeout_usec; 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 #endif // TINS_PACKET_SENDER_H

View File

@@ -215,7 +215,7 @@ namespace Tins {
* those methods. * those methods.
* \param sender The PacketSender which will send the packet. * \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. /** \brief Receives a matching response for this packet.
* *

View File

@@ -127,7 +127,7 @@ namespace Tins {
/** /**
* \sa PDU::send() * \sa PDU::send()
*/ */
bool send(PacketSender &sender); void send(PacketSender &sender);
/** /**
* \brief Setter for the version field. * \brief Setter for the version field.
@@ -280,12 +280,14 @@ namespace Tins {
* \brief Getter for the present bit fields. * \brief Getter for the present bit fields.
* *
* Use this method and masks created from the values taken from * Use this method and masks created from the values taken from
* the PresentFlags enum to find out which fields are set. If any * the PresentFlags enum to find out which fields are set.
* getter is used for a non-initialized field, the return value * Accessing non-initialized fields, the behaviour is undefined
* will be undefined. It is only safe to use the getter of a field * 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. * 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. * \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; return cloned;
} }
PDU* ARP::make_arp_request(const NetworkInterface& iface, ipaddress_type target, EthernetII ARP::make_arp_request(const NetworkInterface& iface,
ipaddress_type sender, const hwaddress_type &hw_snd) ipaddress_type target, ipaddress_type sender, const hwaddress_type &hw_snd)
{ {
/* Create ARP packet and set its attributes */ /* Create ARP packet and set its attributes */
ARP* arp = new ARP(); ARP* arp = new ARP();
@@ -143,11 +143,11 @@ PDU* ARP::make_arp_request(const NetworkInterface& iface, ipaddress_type target,
arp->opcode(REQUEST); arp->opcode(REQUEST);
/* Create the EthernetII PDU with the ARP PDU as its inner PDU */ /* 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, EthernetII ARP::make_arp_reply(const NetworkInterface& iface,
ipaddress_type sender, const hwaddress_type &hw_tgt, ipaddress_type target, ipaddress_type sender, const hwaddress_type &hw_tgt,
const hwaddress_type &hw_snd) const hwaddress_type &hw_snd)
{ {
/* Create ARP packet and set its attributes */ /* 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); arp->opcode(REPLY);
/* Create the EthernetII PDU with the ARP PDU as its inner PDU */ /* Create the EthernetII PDU with the ARP PDU as its inner PDU */
EthernetII* eth = new EthernetII(iface, hw_tgt, hw_snd, arp); return EthernetII(iface, hw_tgt, hw_snd, arp);
return eth;
} }
} }

View File

@@ -166,7 +166,10 @@ uint32_t Dot11::header_size() const {
} }
#ifndef WIN32 #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; struct sockaddr_ll addr;
memset(&addr, 0, sizeof(struct sockaddr_ll)); memset(&addr, 0, sizeof(struct sockaddr_ll));
@@ -177,7 +180,7 @@ bool Dot11::send(PacketSender &sender) {
addr.sll_ifindex = _iface.id(); addr.sll_ifindex = _iface.id();
memcpy(&(addr.sll_addr), _header.addr1, 6); 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 #endif // WIN32

View File

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

View File

@@ -88,7 +88,10 @@ uint32_t IEEE802_3::header_size() const {
} }
#ifndef WIN32 #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; struct sockaddr_ll addr;
memset(&addr, 0, sizeof(struct sockaddr_ll)); memset(&addr, 0, sizeof(struct sockaddr_ll));
@@ -99,7 +102,7 @@ bool IEEE802_3::send(PacketSender &sender) {
addr.sll_ifindex = _iface.id(); addr.sll_ifindex = _iface.id();
memcpy(&(addr.sll_addr), _eth.dst_mac, sizeof(_eth.dst_mac)); 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 #endif // WIN32

View File

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

View File

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

View File

@@ -66,8 +66,8 @@ uint32_t PDU::size() const {
return sz; return sz;
} }
bool PDU::send(PacketSender &) { void PDU::send(PacketSender &) {
return false;
} }
PDU *PDU::recv_response(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; return ((_flags & 0x10) != 0) ? sizeof(uint32_t) : 0;
} }
bool RadioTap::send(PacketSender &sender) { void RadioTap::send(PacketSender &sender) {
if(!_iface) if(!_iface)
throw std::runtime_error("Interface has not been set"); 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); 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) { void RadioTap::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {

View File

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