From abaa2bf9265eabd448e255410533f04186a3cb9e Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Fri, 19 Oct 2012 12:01:34 -0300 Subject: [PATCH] PacketSender now throws on error. Fixed the documentation on several header files. --- examples/Makefile.in | 2 +- examples/arpspoofing.cpp | 12 +++- examples/traceroute.cpp | 1 + include/arp.h | 43 +++++------ include/dot11.h | 2 +- include/ethernetII.h | 2 +- include/ieee802_3.h | 35 ++++----- include/ip.h | 4 +- include/packet_sender.h | 111 +++++++++++++++++++++-------- include/pdu.h | 2 +- include/radiotap.h | 10 +-- src/arp.cpp | 13 ++-- src/dot11.cpp | 7 +- src/ethernetII.cpp | 4 +- src/ieee802_3.cpp | 7 +- src/ip.cpp | 4 +- src/packet_sender.cpp | 150 ++++++++++++++++++++------------------- src/pdu.cpp | 4 +- src/radiotap.cpp | 4 +- src/utils.cpp | 10 +-- 20 files changed, 251 insertions(+), 176 deletions(-) diff --git a/examples/Makefile.in b/examples/Makefile.in index 78710cc..2b73680 100644 --- a/examples/Makefile.in +++ b/examples/Makefile.in @@ -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 $@ diff --git a/examples/arpspoofing.cpp b/examples/arpspoofing.cpp index 528c39f..f350b19 100644 --- a/examples/arpspoofing.cpp +++ b/examples/arpspoofing.cpp @@ -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; + } } diff --git a/examples/traceroute.cpp b/examples/traceroute.cpp index 798a757..8331523 100644 --- a/examples/traceroute.cpp +++ b/examples/traceroute.cpp @@ -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); diff --git a/include/arp.h b/include/arp.h index dbdda2f..20d6e5e 100644 --- a/include/arp.h +++ b/include/arp.h @@ -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()); diff --git a/include/dot11.h b/include/dot11.h index 446ee2f..3f12b08 100644 --- a/include/dot11.h +++ b/include/dot11.h @@ -386,7 +386,7 @@ namespace Tins { /** * \sa PDU::send() */ - bool send(PacketSender &sender); + void send(PacketSender &sender); #endif // WIN32 /** diff --git a/include/ethernetII.h b/include/ethernetII.h index 1ee4d67..fa49801 100644 --- a/include/ethernetII.h +++ b/include/ethernetII.h @@ -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. diff --git a/include/ieee802_3.h b/include/ieee802_3.h index 7a95d4b..9b323f7 100644 --- a/include/ieee802_3.h +++ b/include/ieee802_3.h @@ -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. diff --git a/include/ip.h b/include/ip.h index f5e06f8..b2d53cc 100644 --- a/include/ip.h +++ b/include/ip.h @@ -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. diff --git a/include/packet_sender.h b/include/packet_sender.h index 333c228..d9d606c 100644 --- a/include/packet_sender.h +++ b/include/packet_sender.h @@ -31,6 +31,8 @@ #define TINS_PACKET_SENDER_H +#include +#include #include #include #include @@ -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 diff --git a/include/pdu.h b/include/pdu.h index 1103710..27e65f2 100644 --- a/include/pdu.h +++ b/include/pdu.h @@ -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. * diff --git a/include/radiotap.h b/include/radiotap.h index a6226a4..94e5eb5 100644 --- a/include/radiotap.h +++ b/include/radiotap.h @@ -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. diff --git a/src/arp.cpp b/src/arp.cpp index 2ed89db..f2f38ba 100644 --- a/src/arp.cpp +++ b/src/arp.cpp @@ -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); } } diff --git a/src/dot11.cpp b/src/dot11.cpp index 43d41ca..f153e08 100644 --- a/src/dot11.cpp +++ b/src/dot11.cpp @@ -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 diff --git a/src/ethernetII.cpp b/src/ethernetII.cpp index 89d51af..4f44ec7 100644 --- a/src/ethernetII.cpp +++ b/src/ethernetII.cpp @@ -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 diff --git a/src/ieee802_3.cpp b/src/ieee802_3.cpp index b9dacf9..3d9e6bb 100644 --- a/src/ieee802_3.cpp +++ b/src/ieee802_3.cpp @@ -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 diff --git a/src/ip.cpp b/src/ip.cpp index 46c3842..dca65f7 100644 --- a/src/ip.cpp +++ b/src/ip.cpp @@ -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) { diff --git a/src/packet_sender.cpp b/src/packet_sender.cpp index c068578..4cb9600 100644 --- a/src/packet_sender.cpp +++ b/src/packet_sender.cpp @@ -37,28 +37,39 @@ #include #include #include + #include #else #include #include #endif #include -#include #include #include #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; } +} diff --git a/src/pdu.cpp b/src/pdu.cpp index dfb4c57..55c2d98 100644 --- a/src/pdu.cpp +++ b/src/pdu.cpp @@ -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 &) { diff --git a/src/radiotap.cpp b/src/radiotap.cpp index e77dfd6..22baa68 100644 --- a/src/radiotap.cpp +++ b/src/radiotap.cpp @@ -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) { diff --git a/src/utils.cpp b/src/utils.cpp index e46bf89..3dc2bfc 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -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 packet(ARP::make_arp_request(iface, ip, info.ip_addr, info.hw_addr)); - std::auto_ptr response(sender.send_recv(*packet)); + EthernetII packet = ARP::make_arp_request(iface, ip, info.ip_addr, info.hw_addr); + std::auto_ptr response(sender.send_recv(packet)); if(response.get()) { ARP *arp_resp = response->find_pdu(); 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 packet(ARP::make_arp_request(iface, ip, info.ip_addr, info.hw_addr)); - std::auto_ptr response(sender.send_recv(*packet)); + EthernetII packet = ARP::make_arp_request(iface, ip, info.ip_addr, info.hw_addr); + std::auto_ptr response(sender.send_recv(packet)); if(response.get()) { const ARP *arp_resp = response->find_pdu(); if(arp_resp)