mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Improved documentation on several classes.
This commit is contained in:
@@ -47,10 +47,61 @@ namespace Tins {
|
||||
class PDU;
|
||||
|
||||
/**
|
||||
* \brief Class that enables sending the created PDUs
|
||||
* \class PacketSender
|
||||
* \brief Sends packets through a network interface.
|
||||
*
|
||||
* PacketSender class is responsible for sending the packets using the
|
||||
* correct PDU layer. It is responsible for opening the raw sockets.
|
||||
* This class allows sending packets through a network interface.
|
||||
* It can send basically two types of packets:
|
||||
*
|
||||
* - Those that contain a link layer PDU (EthernetII, SLL, etc). These
|
||||
* will be serialized and sent through an interface that has to be
|
||||
* specified. This can be done by providing it when you call
|
||||
* PacketSender::send, or set a default one using
|
||||
* PacketSender::default_interface.
|
||||
* - Those that don't contain a link layer PDU. In this case, the
|
||||
* kernel will be responsible for picking the appropriate network interface
|
||||
* based on the destination address.
|
||||
*
|
||||
* Sending packets can be done via PacketSender::send:
|
||||
*
|
||||
* \code
|
||||
* // Construct a packet which uses an EthernetII link layer.
|
||||
* EthernetII pkt1 = ...;
|
||||
*
|
||||
* // Construct a packet sender, which we'll use to send packets.
|
||||
* PacketSender sender;
|
||||
*
|
||||
* // Send it through interface eth0
|
||||
* sender.send(pkt1, "eth0");
|
||||
*
|
||||
* // Set the default interface to eth0
|
||||
* sender.default_interface("eth0");
|
||||
*
|
||||
* // This is now equivalent to the previous send.
|
||||
* sender.send(pkt1);
|
||||
*
|
||||
* // Construct a packet which has no link layer protocol.
|
||||
* IP ip = IP("192.168.0.1") / TCP(22, 928);
|
||||
*
|
||||
* // Here the kernel will figure out which interface to use and it will
|
||||
* // append the appropriate link layer protocol PDU. It will also perform
|
||||
* // the necessary ARP lookups in order to use the destination host's
|
||||
* // hardware address.
|
||||
* //
|
||||
* // libtins will find which is the appropriate source IP address to use.
|
||||
* // This will be done by the kernel as well, but it's required when
|
||||
* // calculating checksums.
|
||||
* sender.send(ip);
|
||||
* \endcode
|
||||
*
|
||||
* PacketSender also supports sending a packet and waiting for a response.
|
||||
* This can be done by using PacketSender::send_recv.
|
||||
*
|
||||
* This class opens sockets as it needs to, and closes them when the object
|
||||
* is destructed.
|
||||
*
|
||||
* \sa PacketSender::send
|
||||
* \sa PacketSender::send_recv
|
||||
*/
|
||||
class PacketSender {
|
||||
public:
|
||||
@@ -209,9 +260,19 @@ namespace Tins {
|
||||
* \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
|
||||
* to expect responses for ICMP, ARP, and such packets that are normally
|
||||
* answered by the host that receives the packet.
|
||||
* The packet is sent, and then a response is awaited.
|
||||
* PDU::matches_pdu is called on the packet sent in order to
|
||||
* check whether a packet received is a response.
|
||||
*
|
||||
* This will match every response to a packet. For example,
|
||||
* if you send a TCP packet, any response matching the same
|
||||
* IP addresses and ports will be taken as a response to it.
|
||||
* This also happens for other protocols, such as ARP, ICMP,
|
||||
* DHCP, DNS, IP, etc.
|
||||
*
|
||||
* If you send a packet and get an ICMP response indicating
|
||||
* an error (such as host unreachable, ttl exceeded, etc),
|
||||
* that packet will be considered a response.
|
||||
*
|
||||
* \param pdu The PDU to send.
|
||||
* \return Returns the response PDU, 0 if not response was received.
|
||||
@@ -220,12 +281,11 @@ namespace Tins {
|
||||
|
||||
/**
|
||||
* \brief Sends a PDU and waits for its response.
|
||||
*
|
||||
* Sends a packet and receives a response. This overload takes
|
||||
* a NetworkInterface.
|
||||
*
|
||||
* 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
|
||||
* to expect responses for ICMP, ARP, and such packets that are normally
|
||||
* answered by the host that receives the packet.
|
||||
*
|
||||
* \sa PacketSender::send_recv(PDU&);
|
||||
* \param pdu The PDU to send.
|
||||
* \param iface The network interface in which to send and receive.
|
||||
* \return Returns the response PDU, 0 if not response was received.
|
||||
@@ -235,9 +295,12 @@ namespace Tins {
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \brief Receives a layer 2 PDU response to a previously sent PDU.
|
||||
*
|
||||
* This method is used internally. You should just use PacketSender::send_recv.
|
||||
*
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* \param pdu The PDU which will try to match the responses.
|
||||
* \param link_addr The sockaddr struct which will be used to receive the PDU.
|
||||
@@ -249,6 +312,8 @@ namespace Tins {
|
||||
|
||||
/**
|
||||
* \brief Sends a level 2 PDU.
|
||||
*
|
||||
* This method is used internally. You should just use PacketSender::send.
|
||||
*
|
||||
* This method sends a layer 2 PDU, using a raw socket, open
|
||||
* using the corresponding flag, according to the given type of
|
||||
@@ -266,6 +331,8 @@ namespace Tins {
|
||||
|
||||
/**
|
||||
* \brief Receives a layer 3 PDU response to a previously sent PDU.
|
||||
*
|
||||
* This method is used internally. You should just use PacketSender::send_recv.
|
||||
*
|
||||
* 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.
|
||||
@@ -280,6 +347,8 @@ namespace Tins {
|
||||
|
||||
/**
|
||||
* \brief Sends a level 3 PDU.
|
||||
*
|
||||
* This method is used internally. You should just use PacketSender::send.
|
||||
*
|
||||
* This method sends a layer 3 PDU, using a raw socket, open using the corresponding flag,
|
||||
* according to the given type of protocol.
|
||||
|
||||
@@ -119,7 +119,8 @@ public:
|
||||
/**
|
||||
* \brief Constructs a PacketWriter.
|
||||
*
|
||||
* \deprecated Use the other constructor, which takes a DataLinkType.
|
||||
* \deprecated Use the PacketWriter(const std::string&, const DataLinkType<T>&)
|
||||
* constructor.
|
||||
*
|
||||
* \param file_name The file in which to store the written PDUs.
|
||||
* \param lt The link type which will be written to this file.
|
||||
@@ -158,7 +159,9 @@ public:
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
* \brief Destructor.
|
||||
*
|
||||
* Gracefully closes the output file.
|
||||
*/
|
||||
~PacketWriter();
|
||||
|
||||
|
||||
@@ -53,12 +53,56 @@ namespace Tins {
|
||||
* \class PDU
|
||||
* \brief Base class for protocol data units.
|
||||
*
|
||||
* Every PDU implementation must inherit this class. PDUs can be serialized,
|
||||
* therefore allowing a PacketSender to send them through the corresponding
|
||||
* sockets.
|
||||
* Every PDU implementation inherits from this class.
|
||||
*
|
||||
* PDUs can contain 0 or 1 inner PDU. By stacking several PDUs together,
|
||||
* you can construct packets. These are created upwards: upper layers
|
||||
* will be children of the lower ones.
|
||||
*
|
||||
* If you want to find a specific protocol within a PDU chain, you can use
|
||||
* PDU::find_pdu and PDU::rfind_pdu. Both of them take a template parameter
|
||||
* that indicates the PDU type you are looking for. The first one returns a
|
||||
* pointer to the first object of that type, and the second one returns a
|
||||
* reference (and throws if it is not found).
|
||||
*
|
||||
* PDUs are created upwards: upper layers will be children of the
|
||||
* lower ones.
|
||||
* For example:
|
||||
*
|
||||
* \code
|
||||
* // Take a whole packet from somewhere.
|
||||
* EthernetII packet = ...;
|
||||
*
|
||||
* // Find the IP layer
|
||||
* const IP* ip = packet.find_pdu<IP>();
|
||||
* if(ip) {
|
||||
* // If the pointer is not null, then it will point to the IP layer
|
||||
* }
|
||||
*
|
||||
* // Find the TCP layer. This will throw a pdu_not_found exception
|
||||
* // if there is no TCP layer in this packet.
|
||||
* const TCP& tcp = packet.rfind_pdu<TCP>();
|
||||
* \endcode
|
||||
*
|
||||
* PDU objects can be serialized. Serialization converts the entire PDU
|
||||
* stack into a vector of bytes. This process might modify some parameters
|
||||
* on packets depending on which protocols are used in it. For example:
|
||||
*
|
||||
* - If the lowest protocol layer is IP (this means that there is no
|
||||
* link layer protocol in the packet), then it calculates the source address
|
||||
* that should be used in that IP PDU. \sa IP
|
||||
* - If a protocol contains a checksum field, its value will be calculated
|
||||
* and included in its serialized contents.
|
||||
* - If a protocol contains a "next protocol" field, it is also set based
|
||||
* on the type of the next PDU in the packet.
|
||||
*
|
||||
* If you want to serialize a packet, just use PDU::serialize:
|
||||
*
|
||||
* \code
|
||||
* // Construct a packet
|
||||
* EthernetII packet = EthernetII() / IP() / TCP() / RawPDU("hello");
|
||||
*
|
||||
* // Now serialize it. This is a std::vector<uint8_t>.
|
||||
* PDU::serialization_type buffer = packet.serialize();
|
||||
* \endcode
|
||||
*/
|
||||
class PDU {
|
||||
public:
|
||||
|
||||
@@ -78,7 +78,9 @@ public:
|
||||
cached_size() {}
|
||||
|
||||
/**
|
||||
* Forwards the call to the cached PDU. \sa PDU::header_size.
|
||||
* Forwards the call to the cached PDU.
|
||||
*
|
||||
* \sa PDU::header_size.
|
||||
*/
|
||||
uint32_t header_size() const {
|
||||
if(cached_serialization.empty())
|
||||
@@ -87,42 +89,54 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards the call to the cached PDU. \sa PDU::clone.
|
||||
* Forwards the call to the cached PDU.
|
||||
*
|
||||
* \sa PDU::clone.
|
||||
*/
|
||||
PDUCacher *clone() const {
|
||||
return new PDUCacher<T>(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards the call to the cached PDU. \sa PDU::send.
|
||||
* Forwards the call to the cached PDU.
|
||||
*
|
||||
* \sa PDU::send.
|
||||
*/
|
||||
void send(PacketSender &sender, const NetworkInterface &iface) {
|
||||
cached.send(sender, iface);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards the call to the cached PDU. \sa PDU::recv_responde.
|
||||
* Forwards the call to the cached PDU.
|
||||
*
|
||||
* \sa PDU::recv_responde.
|
||||
*/
|
||||
PDU *recv_response(PacketSender &sender, const NetworkInterface &iface) {
|
||||
return cached.recv_response(sender, iface);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards the call to the cached PDU. \sa PDU::matches_response.
|
||||
* Forwards the call to the cached PDU.
|
||||
*
|
||||
* \sa PDU::matches_response.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||
return cached.matches_response(ptr, total_sz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards the call to the cached PDU. \sa PDU::matches_flag.
|
||||
* Forwards the call to the cached PDU.
|
||||
*
|
||||
* \sa PDU::matches_flag.
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return cached.matches_flag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards the call to the cached PDU. \sa PDU::pdu_type.
|
||||
* Forwards the call to the cached PDU.
|
||||
*
|
||||
* \sa PDU::pdu_type.
|
||||
*/
|
||||
PDUType pdu_type() const {
|
||||
return cached.pdu_type();
|
||||
|
||||
@@ -265,7 +265,8 @@ namespace Tins {
|
||||
class Sniffer : public BaseSniffer {
|
||||
public:
|
||||
/**
|
||||
* \deprecated
|
||||
* \deprecated This enum is no longer necessary. You should use the
|
||||
* Sniffer(const std::string&, const SnifferConfiguration&) constructor.
|
||||
*/
|
||||
enum promisc_type {
|
||||
NON_PROMISC,
|
||||
@@ -293,7 +294,8 @@ namespace Tins {
|
||||
* By default the interface won't be put into promiscuous mode, and won't
|
||||
* be put into monitor mode.
|
||||
*
|
||||
* \deprecated Use the constructor that takes a SnifferConfiguration.
|
||||
* \deprecated Use the Sniffer(const std::string&, const SnifferConfiguration&)
|
||||
* constructor.
|
||||
* \param device The device which will be sniffed.
|
||||
* \param max_packet_size The maximum packet size to be read.
|
||||
* \param promisc bool indicating wether to put the interface in promiscuous mode.(optional)
|
||||
@@ -309,7 +311,8 @@ namespace Tins {
|
||||
* The maximum capture size is set to 65535. By default the interface won't
|
||||
* be put into promiscuous mode, and won't be put into monitor mode.
|
||||
*
|
||||
* \deprecated Use the constructor that takes a SnifferConfiguration.
|
||||
* \deprecated Use the Sniffer(const std::string&, const SnifferConfiguration&)
|
||||
* constructor.
|
||||
* \param device The device which will be sniffed.
|
||||
* \param promisc Indicates if the interface should be put in promiscuous mode.
|
||||
* \param filter A capture filter to be used on the sniffing session.(optional);
|
||||
|
||||
@@ -46,10 +46,30 @@
|
||||
namespace Tins {
|
||||
/**
|
||||
* \class TCP
|
||||
* \brief Class that represents an TCP PDU.
|
||||
* \brief Represents a TCP PDU.
|
||||
*
|
||||
* TCP is the representation of the TCP PDU. Instances of this class
|
||||
* must be sent over a level 3 PDU, this will otherwise fail.
|
||||
* This class represents a TCP PDU.
|
||||
*
|
||||
* When sending TCP PDUs, the checksum is calculated automatically
|
||||
* every time you send the packet.
|
||||
*
|
||||
* While sniffing, the payload sent in each packet will be wrapped
|
||||
* in a RawPDU, which is set as the TCP object's inner_pdu. Therefore,
|
||||
* if you are sniffing and want to see the TCP packet's payload,
|
||||
* you need to do the following:
|
||||
*
|
||||
* \code
|
||||
* // Get a packet from somewhere.
|
||||
* TCP tcp = ...;
|
||||
*
|
||||
* // Extract the RawPDU object.
|
||||
* const RawPDU& raw = tcp.rfind_pdu<RawPDU>();
|
||||
*
|
||||
* // Finally, take the payload (this is a vector<uint8_t>)
|
||||
* const RawPDU::payload_type& payload = raw.payload();
|
||||
* \endcode
|
||||
*
|
||||
* \sa RawPDU
|
||||
*/
|
||||
|
||||
class TCP : public PDU {
|
||||
@@ -78,7 +98,7 @@ namespace Tins {
|
||||
/**
|
||||
* \brief TCP options enum.
|
||||
*
|
||||
* This enum identifies valid options supported by TCP PDU.
|
||||
* This enum defines option types supported by TCP PDU.
|
||||
*/
|
||||
enum OptionTypes {
|
||||
EOL = 0,
|
||||
@@ -120,6 +140,7 @@ namespace Tins {
|
||||
*
|
||||
* Creates an instance of TCP. Destination and source port can
|
||||
* be provided, otherwise both will be 0.
|
||||
*
|
||||
* \param dport Destination port.
|
||||
* \param sport Source port.
|
||||
* */
|
||||
@@ -129,7 +150,7 @@ namespace Tins {
|
||||
* \brief Constructs TCP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for a TCP header, or any of the
|
||||
* TLV options are malformed a malformed_packet exception is
|
||||
* TLV options are malformed, a malformed_packet exception is
|
||||
* thrown.
|
||||
*
|
||||
* Any extra data will be stored in a RawPDU.
|
||||
@@ -142,56 +163,56 @@ namespace Tins {
|
||||
/**
|
||||
* \brief Getter for the destination port field.
|
||||
*
|
||||
* \return The destination port in an uint16_t.
|
||||
* \return The destination port field value.
|
||||
*/
|
||||
uint16_t dport() const { return Endian::be_to_host(_tcp.dport); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the source port field.
|
||||
*
|
||||
* \return The source port in an uint16_t.
|
||||
* \return The source port field value.
|
||||
*/
|
||||
uint16_t sport() const { return Endian::be_to_host(_tcp.sport); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the sequence number field.
|
||||
*
|
||||
* \return The sequence number in an uint32_t.
|
||||
* \return The sequence number field value.
|
||||
*/
|
||||
uint32_t seq() const { return Endian::be_to_host(_tcp.seq); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the acknowledge number field.
|
||||
*
|
||||
* \return The acknowledge number in an uint32_t.
|
||||
* \return The acknowledge number field value.
|
||||
*/
|
||||
uint32_t ack_seq() const { return Endian::be_to_host(_tcp.ack_seq); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the window size field.
|
||||
*
|
||||
* \return The window size in an uint32_t.
|
||||
* \return The window size field value.
|
||||
*/
|
||||
uint16_t window() const { return Endian::be_to_host(_tcp.window); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the checksum field.
|
||||
*
|
||||
* \return The checksum field in an uint16_t.
|
||||
* \return The checksum field value.
|
||||
*/
|
||||
uint16_t checksum() const { return Endian::be_to_host(_tcp.check); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the urgent pointer field.
|
||||
*
|
||||
* \return The urgent pointer in an uint16_t.
|
||||
* \return The urgent pointer field value.
|
||||
*/
|
||||
uint16_t urg_ptr() const { return Endian::be_to_host(_tcp.urg_ptr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the data offset field.
|
||||
*
|
||||
* \return Data offset in an uint8_t.
|
||||
* \return The data offset field value.
|
||||
*/
|
||||
small_uint<4> data_offset() const { return this->_tcp.doff; }
|
||||
|
||||
@@ -204,7 +225,24 @@ namespace Tins {
|
||||
|
||||
/**
|
||||
* \brief Gets the value of a flag.
|
||||
*
|
||||
* This method gets the value of a specific flag. If you
|
||||
* want to check for multiple flags at the same time,
|
||||
* use TCP::flags.
|
||||
*
|
||||
* If you want to check if this PDU has the SYN flag on,
|
||||
* you can do it like this:
|
||||
*
|
||||
* \code
|
||||
* // Get a TCP packet from somewhere.
|
||||
* TCP tcp = ...;
|
||||
*
|
||||
* if(tcp.get_flag(TCP::SYN)) {
|
||||
* // The SYN flag is on!
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \sa TCP::flags
|
||||
* \param tcp_flag The polled flag.
|
||||
* \return The value of the flag.
|
||||
*/
|
||||
@@ -220,8 +258,9 @@ namespace Tins {
|
||||
*
|
||||
* \code
|
||||
* TCP tcp = ...;
|
||||
* if(tcp.flags() == (TCP::SYN | TCP::ACK))
|
||||
* if(tcp.flags() == (TCP::SYN | TCP::ACK)) {
|
||||
* // It's a SYN+ACK!
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \return The value of the flags field.
|
||||
@@ -379,11 +418,13 @@ namespace Tins {
|
||||
* same time.
|
||||
*
|
||||
* \code
|
||||
* // Get a TCP packet from somewhere and set the flags to SYN && ACK
|
||||
* TCP tcp = ...;
|
||||
* tcp.flags(TCP::SYN | TCP::ACK);
|
||||
* // ...
|
||||
* // only set the ACK, keeping the rest of the old flags.
|
||||
* tcp.flags(tcp.flags() | TCP::ACK);
|
||||
*
|
||||
* // Now also set the PSH flag, without modifying
|
||||
* // the rest of the flags.
|
||||
* tcp.flags(tcp.flags() | TCP::PSH);
|
||||
* \endcode
|
||||
*
|
||||
* \param value The new value of the flags.
|
||||
|
||||
@@ -38,10 +38,27 @@ namespace Tins {
|
||||
|
||||
/**
|
||||
* \class UDP
|
||||
* \brief Class that represents an UDP PDU.
|
||||
* \brief Represents an UDP PDU.
|
||||
*
|
||||
* UDP is the representation of the UDP PDU. Instances of this class
|
||||
* must be sent over a level 3 PDU, this will otherwise fail.
|
||||
* This class represents an UDP PDU.
|
||||
*
|
||||
* While sniffing, the payload sent in each packet will be wrapped
|
||||
* in a RawPDU, which is set as the UDP object's inner_pdu. Therefore,
|
||||
* if you are sniffing and want to see the UDP packet's payload,
|
||||
* you need to do the following:
|
||||
*
|
||||
* \code
|
||||
* // Get a packet from somewhere.
|
||||
* UDP udp = ...;
|
||||
*
|
||||
* // Extract the RawPDU object.
|
||||
* const RawPDU& raw = udp.rfind_pdu<RawPDU>();
|
||||
*
|
||||
* // Finally, take the payload (this is a vector<uint8_t>)
|
||||
* const RawPDU::payload_type& payload = raw.payload();
|
||||
* \endcode
|
||||
*
|
||||
* \sa RawPDU
|
||||
*/
|
||||
class UDP : public PDU {
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user