mirror of
https://github.com/mfontanini/libtins
synced 2026-01-28 12:44:25 +01:00
RAII'd some code. Everything(hopefully) uses IPv4Address now.
This commit is contained in:
@@ -39,7 +39,15 @@ namespace Tins {
|
||||
*/
|
||||
class ARP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* The type of the hardware address.
|
||||
*/
|
||||
typedef HWAddress<6> hwaddress_type;
|
||||
|
||||
/**
|
||||
* The type of the IP address.
|
||||
*/
|
||||
typedef IPv4Address ipaddress_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -60,8 +68,8 @@ namespace Tins {
|
||||
* ARP requests and replies can be constructed easily using
|
||||
* ARP::make_arp_request/reply static functions.
|
||||
*/
|
||||
ARP(IPv4Address target_ip = IPv4Address(),
|
||||
IPv4Address sender_ip = IPv4Address(),
|
||||
ARP(ipaddress_type target_ip = ipaddress_type(),
|
||||
ipaddress_type sender_ip = ipaddress_type(),
|
||||
const hwaddress_type &target_hw = hwaddress_type(),
|
||||
const hwaddress_type &sender_hw = hwaddress_type());
|
||||
|
||||
@@ -86,7 +94,7 @@ namespace Tins {
|
||||
*
|
||||
* \return Returns the sender's IP address in an uint32_t.
|
||||
*/
|
||||
IPv4Address sender_ip_addr() const { return Utils::be_to_host(_arp.ar_sip); }
|
||||
ipaddress_type sender_ip_addr() const { return ipaddress_type(_arp.ar_sip); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the target's hardware address.
|
||||
@@ -100,7 +108,7 @@ namespace Tins {
|
||||
*
|
||||
* \return Returns the target's IP address in an uint32_t.
|
||||
*/
|
||||
IPv4Address target_ip_addr() const { return Utils::be_to_host(_arp.ar_tip); }
|
||||
ipaddress_type target_ip_addr() const { return ipaddress_type(_arp.ar_tip); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the hardware address format.
|
||||
@@ -156,7 +164,7 @@ namespace Tins {
|
||||
*
|
||||
* \param new_snd_ip_addr IPv4Address containing the new sender's IP address.
|
||||
*/
|
||||
void sender_ip_addr(IPv4Address new_snd_ip_addr);
|
||||
void sender_ip_addr(ipaddress_type new_snd_ip_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the target's hardware address.
|
||||
@@ -170,7 +178,7 @@ namespace Tins {
|
||||
*
|
||||
* \param new_tgt_ip_addr IPv4Address containing the new target's IP address.
|
||||
*/
|
||||
void target_ip_addr(IPv4Address new_tgt_ip_addr);
|
||||
void target_ip_addr(ipaddress_type new_tgt_ip_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hardware address format.
|
||||
@@ -225,8 +233,8 @@ namespace Tins {
|
||||
* \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.
|
||||
*/
|
||||
static PDU* make_arp_request(const NetworkInterface& iface, IPv4Address target,
|
||||
IPv4Address sender, const hwaddress_type &hw_snd = hwaddress_type());
|
||||
static PDU* make_arp_request(const NetworkInterface& iface, ipaddress_type target,
|
||||
ipaddress_type sender, const hwaddress_type &hw_snd = hwaddress_type());
|
||||
|
||||
/**
|
||||
* \brief Creates an ARP Reply within a Layer 2 PDU using uint32_t for target and sender.
|
||||
@@ -241,8 +249,8 @@ namespace Tins {
|
||||
* \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.
|
||||
*/
|
||||
static PDU* make_arp_reply(const NetworkInterface& iface, IPv4Address target,
|
||||
IPv4Address sender, const hwaddress_type &hw_tgt = hwaddress_type(),
|
||||
static PDU* 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());
|
||||
|
||||
/** \brief Check wether ptr points to a valid response for this PDU.
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include "pdu.h"
|
||||
#include "utils.h"
|
||||
#include "ipaddress.h"
|
||||
@@ -37,7 +38,21 @@ namespace Tins {
|
||||
*/
|
||||
class BootP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* The type of the IP addresses.
|
||||
*/
|
||||
typedef IPv4Address ipaddress_type;
|
||||
|
||||
/**
|
||||
* The type of the chaddr field.
|
||||
*/
|
||||
typedef HWAddress<16> chaddr_type;
|
||||
|
||||
/**
|
||||
* The type of the vend field.
|
||||
*/
|
||||
typedef std::vector<uint8_t> vend_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
@@ -69,23 +84,6 @@ namespace Tins {
|
||||
*/
|
||||
BootP(const uint8_t *buffer, uint32_t total_sz, uint32_t vend_field_size = 64);
|
||||
|
||||
/**
|
||||
* \brief Copy constructor.
|
||||
*/
|
||||
BootP(const BootP &other);
|
||||
|
||||
/**
|
||||
* \brief Copy assignment operator.
|
||||
*/
|
||||
BootP &operator= (const BootP &other);
|
||||
|
||||
/**
|
||||
* \brief BootP destructor.
|
||||
*
|
||||
* This frees the memory allocated to hold the vend field.
|
||||
*/
|
||||
~BootP();
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
@@ -133,25 +131,25 @@ namespace Tins {
|
||||
* \brief Getter for the ciaddr field.
|
||||
* \return The ciaddr field for this BootP PDU.
|
||||
*/
|
||||
IPv4Address ciaddr() const { return Utils::be_to_host(_bootp.ciaddr); }
|
||||
ipaddress_type ciaddr() const { return ipaddress_type(_bootp.ciaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the yiaddr field.
|
||||
* \return The yiaddr field for this BootP PDU.
|
||||
*/
|
||||
IPv4Address yiaddr() const { return Utils::be_to_host(_bootp.yiaddr); }
|
||||
ipaddress_type yiaddr() const { return ipaddress_type(_bootp.yiaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the siaddr field.
|
||||
* \return The siaddr field for this BootP PDU.
|
||||
*/
|
||||
IPv4Address siaddr() const { return Utils::be_to_host(_bootp.siaddr); }
|
||||
ipaddress_type siaddr() const { return ipaddress_type(_bootp.siaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the giaddr field.
|
||||
* \return The giaddr field for this BootP PDU.
|
||||
*/
|
||||
IPv4Address giaddr() const { return Utils::be_to_host(_bootp.giaddr); }
|
||||
ipaddress_type giaddr() const { return ipaddress_type(_bootp.giaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the chaddr field.
|
||||
@@ -175,12 +173,7 @@ namespace Tins {
|
||||
* \brief Getter for the vend field.
|
||||
* \return The vend field for this BootP PDU.
|
||||
*/
|
||||
uint8_t *vend() { return _vend; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the vend field.
|
||||
*/
|
||||
uint32_t vend_size() const { return _vend_size; }
|
||||
const vend_type &vend() const { return _vend; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the header size.
|
||||
@@ -236,25 +229,25 @@ namespace Tins {
|
||||
* \brief Setter for the ciaddr field.
|
||||
* \param new_ciaddr The ciaddr to be set.
|
||||
*/
|
||||
void ciaddr(IPv4Address new_ciaddr);
|
||||
void ciaddr(ipaddress_type new_ciaddr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the yiaddr field.
|
||||
* \param new_yiaddr The yiaddr to be set.
|
||||
*/
|
||||
void yiaddr(IPv4Address new_yiaddr);
|
||||
void yiaddr(ipaddress_type new_yiaddr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the siaddr field.
|
||||
* \param new_siaddr The siaddr to be set.
|
||||
*/
|
||||
void siaddr(IPv4Address new_siaddr);
|
||||
void siaddr(ipaddress_type new_siaddr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the giaddr field.
|
||||
* \param new_giaddr The giaddr to be set.
|
||||
*/
|
||||
void giaddr(IPv4Address new_giaddr);
|
||||
void giaddr(ipaddress_type new_giaddr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the chaddr field.
|
||||
@@ -288,9 +281,8 @@ namespace Tins {
|
||||
/**
|
||||
* \brief Setter for the vend field.
|
||||
* \param new_vend The vend to be set.
|
||||
* \param size The size of the new vend field.
|
||||
*/
|
||||
void vend(uint8_t *new_vend, uint32_t size);
|
||||
void vend(const vend_type &new_vend);
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
@@ -305,7 +297,16 @@ namespace Tins {
|
||||
return do_clone_pdu<BootP>();
|
||||
}
|
||||
protected:
|
||||
void copy_bootp_fields(const BootP *other);
|
||||
/**
|
||||
* \brief Getter for the vend field.
|
||||
*
|
||||
* This getter can be used by subclasses to avoid copying the
|
||||
* vend field around.
|
||||
*
|
||||
* \return The vend field for this BootP PDU.
|
||||
*/
|
||||
vend_type &vend() { return _vend; }
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
private:
|
||||
/**
|
||||
@@ -329,8 +330,7 @@ namespace Tins {
|
||||
} __attribute__((__packed__));
|
||||
|
||||
bootphdr _bootp;
|
||||
uint8_t *_vend;
|
||||
uint32_t _vend_size;
|
||||
vend_type _vend;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -40,12 +40,12 @@ namespace Tins {
|
||||
class DHCP : public BootP {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
* This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DHCP;
|
||||
|
||||
/**
|
||||
* \brief DHCP flags.
|
||||
* DHCP flags.
|
||||
*/
|
||||
enum Flags {
|
||||
DISCOVER = 1,
|
||||
@@ -147,7 +147,8 @@ namespace Tins {
|
||||
* \param len The length of the option's value in bytes.
|
||||
* \param val The option's value.
|
||||
*/
|
||||
DHCPOption(uint8_t opt, uint8_t len, const uint8_t *val);
|
||||
DHCPOption(uint8_t opt, uint8_t len = 0, const uint8_t *val = 0);
|
||||
|
||||
|
||||
/**
|
||||
* \brief The option number.
|
||||
@@ -228,14 +229,14 @@ namespace Tins {
|
||||
* \param ip The ip of the server.
|
||||
* \return True if the option was added successfully. \sa DHCP::add_option
|
||||
*/
|
||||
bool add_server_identifier(IPv4Address ip);
|
||||
bool add_server_identifier(ipaddress_type ip);
|
||||
|
||||
/**
|
||||
* \brief Searchs for a server identifier option.
|
||||
* \param value A pointer in which the option's value will be stored.
|
||||
* \return True if the option was found, false otherwise.
|
||||
*/
|
||||
bool search_server_identifier(IPv4Address *value);
|
||||
bool search_server_identifier(ipaddress_type *value);
|
||||
|
||||
/**
|
||||
* \brief Adds an IP address lease time option.
|
||||
@@ -284,70 +285,70 @@ namespace Tins {
|
||||
* \param mask The subnet mask.
|
||||
* \return True if the option was added successfully. \sa DHCP::add_option
|
||||
*/
|
||||
bool add_subnet_mask(IPv4Address mask);
|
||||
bool add_subnet_mask(ipaddress_type mask);
|
||||
|
||||
/**
|
||||
* \brief Searchs for a subnet mask option.
|
||||
* \param value A pointer in which the option's value will be stored.
|
||||
* \return True if the option was found, false otherwise.
|
||||
*/
|
||||
bool search_subnet_mask(IPv4Address *value);
|
||||
bool search_subnet_mask(ipaddress_type *value);
|
||||
|
||||
/**
|
||||
* \brief Adds a routers option.
|
||||
* \param routers A list of ip addresses.
|
||||
* \return True if the option was added successfully. \sa DHCP::add_option
|
||||
*/
|
||||
bool add_routers_option(const std::list<IPv4Address> &routers);
|
||||
bool add_routers_option(const std::list<ipaddress_type> &routers);
|
||||
|
||||
/**
|
||||
* \brief Searchs for a routers option.
|
||||
* \param routers A pointer in which the option's value will be stored.
|
||||
* \return True if the option was found, false otherwise.
|
||||
*/
|
||||
bool search_routers_option(std::list<IPv4Address> *routers);
|
||||
bool search_routers_option(std::list<ipaddress_type> *routers);
|
||||
|
||||
/**
|
||||
* \brief Adds a domain name servers option.
|
||||
* \param dns A list of ip addresses.
|
||||
* \return True if the option was added successfully. \sa DHCP::add_option
|
||||
*/
|
||||
bool add_dns_option(const std::list<IPv4Address> &dns);
|
||||
bool add_dns_option(const std::list<ipaddress_type> &dns);
|
||||
|
||||
/**
|
||||
* \brief Searchs for a dns option.
|
||||
* \param dns A pointer in which the option's value will be stored.
|
||||
* \return True if the option was found, false otherwise.
|
||||
*/
|
||||
bool search_dns_option(std::list<IPv4Address> *dns);
|
||||
bool search_dns_option(std::list<ipaddress_type> *dns);
|
||||
|
||||
/**
|
||||
* \brief Adds a broadcast address option.
|
||||
* \param addr The broadcast address.
|
||||
* \return True if the option was added successfully. \sa DHCP::add_option
|
||||
*/
|
||||
bool add_broadcast_option(IPv4Address addr);
|
||||
bool add_broadcast_option(ipaddress_type addr);
|
||||
|
||||
/**
|
||||
* \brief Searchs for a broadcast option.
|
||||
* \param value A pointer in which the option's value will be stored.
|
||||
* \return True if the option was found, false otherwise.
|
||||
*/
|
||||
bool search_broadcast_option(IPv4Address *value);
|
||||
bool search_broadcast_option(ipaddress_type *value);
|
||||
|
||||
/**
|
||||
* \brief Adds a requested address option.
|
||||
* \param addr The requested address.
|
||||
* \return True if the option was added successfully. \sa DHCP::add_option
|
||||
*/
|
||||
bool add_requested_ip_option(IPv4Address addr);
|
||||
bool add_requested_ip_option(ipaddress_type addr);
|
||||
|
||||
/**
|
||||
* \brief Searchs for a requested option.
|
||||
* \param value A pointer in which the option's value will be stored.
|
||||
* \return True if the option was found, false otherwise.
|
||||
*/
|
||||
bool search_requested_ip_option(IPv4Address *value);
|
||||
bool search_requested_ip_option(ipaddress_type *value);
|
||||
|
||||
/**
|
||||
* \brief Adds a domain name option.
|
||||
@@ -389,8 +390,7 @@ namespace Tins {
|
||||
}
|
||||
private:
|
||||
static const uint32_t MAX_DHCP_SIZE;
|
||||
|
||||
void copy_fields(const DHCP *other);
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
template<class T>
|
||||
@@ -403,14 +403,12 @@ namespace Tins {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool generic_search(Options opt, std::list<IPv4Address> *container);
|
||||
bool generic_search(Options opt, std::list<uint32_t> *container);
|
||||
bool generic_search(Options opt, std::list<ipaddress_type> *container);
|
||||
bool generic_search(Options opt, std::string *str);
|
||||
bool generic_search(Options opt, uint32_t *value);
|
||||
bool generic_search(Options opt, IPv4Address *value);
|
||||
bool generic_search(Options opt, ipaddress_type *value);
|
||||
|
||||
uint8_t *serialize_list(const std::list<uint32_t> &int_list, uint32_t &sz);
|
||||
uint8_t *serialize_list(const std::list<IPv4Address> &ip_list, uint32_t &sz);
|
||||
uint8_t *serialize_list(const std::list<ipaddress_type> &ip_list, uint32_t &sz);
|
||||
|
||||
options_type _options;
|
||||
uint32_t _size;
|
||||
|
||||
@@ -213,11 +213,6 @@ namespace Tins {
|
||||
*/
|
||||
Dot11(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Copy assignment operator.
|
||||
*/
|
||||
Dot11 &operator= (const Dot11 &other);
|
||||
|
||||
/**
|
||||
* \brief Getter for the protocol version.
|
||||
*
|
||||
@@ -448,11 +443,17 @@ namespace Tins {
|
||||
|
||||
/**
|
||||
* \brief Allocates an Dot11 PDU from a buffer.
|
||||
*
|
||||
* This can be used somehow as a "virtual constructor". This
|
||||
* method instantiates a subclass of Dot11 from the given buffer.
|
||||
* The allocated class' type will be figured out from the
|
||||
* information provided in the buffer.
|
||||
*
|
||||
* \param buffer The buffer from which to take the PDU data.
|
||||
* \param total_sz The total size of the buffer.
|
||||
* \return The allocated PDU.
|
||||
* \return The allocated Dot11 PDU.
|
||||
*/
|
||||
static PDU *from_bytes(const uint8_t *buffer, uint32_t total_sz);
|
||||
static Dot11 *from_bytes(const uint8_t *buffer, uint32_t total_sz);
|
||||
protected:
|
||||
virtual uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz) { return 0; }
|
||||
virtual uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) { return 0; }
|
||||
|
||||
39
include/ip.h
39
include/ip.h
@@ -44,10 +44,15 @@ namespace Tins {
|
||||
class IP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
* his PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::IP;
|
||||
|
||||
/**
|
||||
* The type used to store addresses.
|
||||
*/
|
||||
typedef IPv4Address address_type;
|
||||
|
||||
/**
|
||||
* \brief IP address size.
|
||||
*/
|
||||
@@ -124,22 +129,20 @@ namespace Tins {
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
* Sets the source and destination port to 0.
|
||||
*/
|
||||
IP();
|
||||
|
||||
/**
|
||||
* \brief Constructor for building the IP PDU taking integer as ip addresses.
|
||||
* \brief Constructor for building the IP PDU.
|
||||
*
|
||||
* Constructor that builds an IP using strings as addresses. They
|
||||
* can be hostnames or IPs.
|
||||
* Both the destination and source IP address can be supplied.
|
||||
* By default, those fields are initialized using the IP
|
||||
* address 0.0.0.0.
|
||||
*
|
||||
* \param ip_dst The destination ip address(optional).
|
||||
* \param ip_src The source ip address(optional).
|
||||
* \param child pointer to a PDU which will be set as the inner_pdu for the packet being constructed(optional).
|
||||
* \param child pointer to a PDU which will be set as the inner_pdu
|
||||
* for the packet being constructed(optional).
|
||||
*/
|
||||
IP(IPv4Address ip_dst, IPv4Address ip_src = IPv4Address(), PDU *child = 0);
|
||||
IP(address_type ip_dst = address_type(),
|
||||
address_type ip_src = address_type(),
|
||||
PDU *child = 0);
|
||||
|
||||
/**
|
||||
* \brief Constructor which creates an IP object from a buffer and adds all identifiable
|
||||
@@ -212,13 +215,13 @@ namespace Tins {
|
||||
*
|
||||
* \return The source address for this IP PDU.
|
||||
*/
|
||||
IPv4Address src_addr() const { return Utils::be_to_host(_ip.saddr); }
|
||||
address_type src_addr() const { return address_type(_ip.saddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the destination address field.
|
||||
* \return The destination address for this IP PDU.
|
||||
*/
|
||||
IPv4Address dst_addr() const { return Utils::be_to_host(_ip.daddr); }
|
||||
address_type dst_addr() const { return address_type(_ip.daddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the version field.
|
||||
@@ -287,16 +290,16 @@ namespace Tins {
|
||||
/**
|
||||
* \brief Setter for the source address field.
|
||||
*
|
||||
* \param ip The ip address in integer notation.
|
||||
* \param ip The source address to be set.
|
||||
*/
|
||||
void src_addr(IPv4Address ip);
|
||||
void src_addr(address_type ip);
|
||||
|
||||
/**
|
||||
* \brief Setter for the destination address field.
|
||||
*
|
||||
* \param ip The ip address in integer notation.
|
||||
* \param ip The destination address to be set.
|
||||
*/
|
||||
void dst_addr(IPv4Address ip);
|
||||
void dst_addr(address_type ip);
|
||||
|
||||
/**
|
||||
* \brief Setter for the version field.
|
||||
|
||||
@@ -29,14 +29,9 @@
|
||||
namespace Tins {
|
||||
class IPv4Address {
|
||||
public:
|
||||
IPv4Address(uint32_t ip = 0);
|
||||
IPv4Address(const char *ip = 0);
|
||||
IPv4Address(const std::string &ip);
|
||||
|
||||
template<size_t n>
|
||||
IPv4Address(const char (&ip)[n])
|
||||
: ip_addr(ip_to_int(ip)) {
|
||||
|
||||
}
|
||||
explicit IPv4Address(uint32_t ip);
|
||||
|
||||
IPv4Address &operator=(uint32_t ip);
|
||||
IPv4Address &operator=(const std::string &ip);
|
||||
|
||||
@@ -71,15 +71,11 @@ public:
|
||||
NetworkInterface(const std::string &name);
|
||||
|
||||
/**
|
||||
* \brief Constructor to allow implicit conversions from string
|
||||
* literals.
|
||||
* \brief Constructor from const char*.
|
||||
*
|
||||
* \param name The name of the interface this object will abstract.
|
||||
*/
|
||||
template<size_t n>
|
||||
NetworkInterface(const char (&name)[n]) {
|
||||
iface_id = resolve_index(name);
|
||||
}
|
||||
NetworkInterface(const char *name);
|
||||
|
||||
/**
|
||||
* \brief Constructs a NetworkInterface from an ip address.
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace Tins {
|
||||
*
|
||||
* \param ip A dotted ip notation string
|
||||
*/
|
||||
uint32_t ip_to_int(const std::string &ip) throw (std::runtime_error);
|
||||
uint32_t ip_to_int(const std::string &ip);
|
||||
|
||||
/**
|
||||
* \brief Convert an integer ip to a dotted-ip-notation string.
|
||||
|
||||
Reference in New Issue
Block a user