diff --git a/include/loopback.h b/include/loopback.h index 853e39a..384c8f6 100644 --- a/include/loopback.h +++ b/include/loopback.h @@ -31,6 +31,8 @@ #define TINS_LOOPBACK_H #include "pdu.h" +#include "macros.h" +#include "network_interface.h" namespace Tins { class Loopback : public PDU { @@ -50,10 +52,13 @@ public: /** * \brief Construct a Loopback object. * - * \param family_id The family id to be used. + * The NetworkInterface object will only be used in *BSD, where + * Null/Loopback PDUs can actually be sent. + * + * \param iface The network interface in which to send this PDU. * \param inner_pdu The inner pdu to be set. */ - Loopback(uint32_t family_id, PDU *inner_pdu = 0); + Loopback(const NetworkInterface &iface, PDU *inner_pdu = 0); /** * \brief Construct a Loopback object from a buffer. @@ -86,16 +91,36 @@ public: */ PDUType pdu_type() const { return PDU::IP; } + /** + * \brief Getter for the interface member. + */ + const NetworkInterface &iface() const { return _iface; } + + /** + * \brief Setter for the interface member. + * + * \param new_iface The new interface to be set. + */ + void iface(const NetworkInterface &new_iface); + /** * \sa PDU::clone */ Loopback *clone() const { return new Loopback(*this); } + // Null/Loopback can only be sent in *BSD + #ifdef BSD + /** + * \sa PDU::send() + */ + void send(PacketSender &sender); + #endif // BSD private: void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent); uint32_t _family; + NetworkInterface _iface; }; } diff --git a/src/loopback.cpp b/src/loopback.cpp index c4552a2..5be8c86 100644 --- a/src/loopback.cpp +++ b/src/loopback.cpp @@ -29,14 +29,19 @@ #ifndef WIN32 #include + #ifdef BSD + #include + #include + #include + #endif #endif #include #include +#include #include "loopback.h" #include "packet_sender.h" #include "ip.h" #include "llc.h" -#include "macros.h" #include "rawpdu.h" #if defined(BSD) && !defined(PF_LLC) @@ -51,8 +56,8 @@ Loopback::Loopback() } -Loopback::Loopback(uint32_t family_id, PDU *inner_pdu) -: PDU(inner_pdu), _family(family_id) +Loopback::Loopback(const NetworkInterface &iface, PDU *inner_pdu) +: PDU(inner_pdu), _family(), _iface(iface) { } @@ -85,6 +90,10 @@ void Loopback::family(uint32_t family_id) { _family = family_id; } +void Loopback::iface(const NetworkInterface &new_iface) { + _iface = new_iface; +} + uint32_t Loopback::header_size() const { return sizeof(_family); } @@ -92,6 +101,18 @@ uint32_t Loopback::header_size() const { void Loopback::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) { assert(total_sz >= sizeof(_family)); + if(dynamic_cast(inner_pdu())) + _family = PF_INET; + else if(dynamic_cast(inner_pdu())) + _family = PF_LLC; *reinterpret_cast(buffer) = _family; } +#ifdef BSD +void Loopback::send(PacketSender &sender) { + if(!_iface) + throw std::runtime_error("Interface has not been set"); + + sender.send_l2(*this, 0, 0, _iface); +} +#endif // WIN32 }