diff --git a/include/rawpdu.h b/include/rawpdu.h index e1897fa..47796fb 100644 --- a/include/rawpdu.h +++ b/include/rawpdu.h @@ -35,6 +35,13 @@ namespace Tins { */ class RawPDU : public PDU { public: + /** \brief Creates an instance of RawPDU. + * + * The payload is NOT copied. Therefore, it must be manually freed by the user. + * \param payload The payload which the RawPDU will contain. + * \param size The size of the payload. + */ + RawPDU(uint8_t *payload, uint32_t size); /** \brief Returns the header size. diff --git a/include/utils.h b/include/utils.h index de225d3..ae7cc63 100644 --- a/include/utils.h +++ b/include/utils.h @@ -23,27 +23,125 @@ #define __UTILS_H +#ifndef WIN32 + #include +#endif #include +#include #include namespace Tins { - /* Utils namespace. */ + /** \brief Network utils namespace. + * + * This namespace provides utils to convert between integer IP addresses + * and dotted notation strings, hw addresses, "net to host" integer + * conversions, interface listing, etc. + */ namespace Utils { + /** \brief Convert a dotted-ip-notation string to an integer. + * + * \param ip A dotted ip notation string + */ uint32_t ip_to_int(const std::string &ip); + + /** \brief Convert an integer ip to a dotted-ip-notation string. + * + * \param ip An integer ip. + */ std::string ip_to_string(uint32_t ip); + + /** \brief Converts a hardware address string into a byte array. + * + * The hardware address must be formatted using the notation 'HH:HH:HH:HH:HH:HH'. + * Where H is a hexadecimal character(0-9, a-f). + * + * \param hw_addr The harware address string. + * \param array The output buffer. It must be at least 6 bytes long. + */ + bool hwaddr_to_byte(const std::string &hw_addr, uint8_t *array); + + /** \brief Converts a byte array representing a hardware address + * into a string. + * + * The input buffer must be at least 6 bytes long. + * \param array The input buffer. + */ + std::string hwaddr_to_string(uint8_t *array); + /** \brief Resolves a domain name and returns its corresponding ip address. + * + * If an ip address is given, its integer representation is returned. + * Otherwise, the domain name is resolved and its ip address is returned. + * + * \param to_resolve The domain name/ip address to resolve. + */ uint32_t resolve_ip(const std::string &to_resolve); - inline uint32_t net_to_host_l(uint32_t address) { - return (((address & 0xff000000) >> 24) | ((address & 0x00ff0000) >> 8) | - ((address & 0x0000ff00) << 8) | ((address & 0x000000ff) << 24)); + /** \brief List all network interfaces. + * + * Returns a set of strings, each of them representing the name + * of a network interface. These names can be used as the input + * interface for Utils::interface_ip, Utils::interface_hwaddr, etc. + */ + std::set network_interfaces(); + + /** \brief Lookup the ip address of the given interface. + * + * If the lookup fails, false will be returned, true otherwise. + * \param iface The interface from which to extract the ip address. + * \param ip The ip address found will be returned in this param. + */ + bool interface_ip(const std::string &iface, uint32_t &ip); + + /** \brief Lookup the hardware address of the given interface. + * + * If the lookup fails, false will be returned, true otherwise. + * \param iface The interface from which to extract the hardware address. + * \param buffer The hw address will be stored in this buffer. It must + * be at least 6 bytes long. + */ + bool interface_hwaddr(const std::string &iface, uint8_t *buffer); + + /** \brief Convert 32 bit integer into network byte order. + * + * \param data The data to convert. + */ + inline uint32_t net_to_host_l(uint32_t data) { + return (((data & 0xff000000) >> 24) | ((data & 0x00ff0000) >> 8) | + ((data & 0x0000ff00) << 8) | ((data & 0x000000ff) << 24)); } - inline uint32_t net_to_host_s(uint16_t address) { - return ((address & 0xff00) >> 8) | ((address & 0x00ff) << 8); + /** \brief Convert 16 bit integer into network byte order. + * + * \param data The data to convert. + */ + inline uint16_t net_to_host_s(uint16_t data) { + return ((data & 0xff00) >> 8) | ((data & 0x00ff) << 8); } + /** \brief Returns the 32 bit crc of the given buffer. + * + * \param data The input buffer. + * \param data_size The size of the input buffer. + */ uint32_t crc32(uint8_t* data, uint32_t data_size); + + /** \brief Generic function to iterate through interface and collect + * data. + * + * The parameter is applied to every interface found, allowing + * the object to collect data from them. + * \param functor An instance of an class which implements operator(struct ifaddrs*). + */ + template void generic_iface_loop(T &functor) { + struct ifaddrs *ifaddrs = 0; + struct ifaddrs *if_it = 0; + getifaddrs(&ifaddrs); + for(if_it = ifaddrs; if_it; if_it = if_it->ifa_next) + functor(if_it); + if(ifaddrs) + freeifaddrs(ifaddrs); + } }; }; diff --git a/src/utils.cpp b/src/utils.cpp index be2963d..3d889c6 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -21,14 +21,57 @@ #include #include +#include #include +#include #ifndef WIN32 #include + #include #endif #include "utils.h" + using namespace std; + +struct InterfaceCollector { + set ifaces; + + void operator() (struct ifaddrs *addr) { + ifaces.insert(addr->ifa_name); + } +}; + +struct IPv4Collector { + uint32_t ip; + bool found; + const char *iface; + + IPv4Collector(const char *interface) : ip(0), found(false), iface(interface) { } + + void operator() (struct ifaddrs *addr) { + if(!found && addr->ifa_addr->sa_family == AF_INET && !strcmp(addr->ifa_name, iface)) { + ip = ((struct sockaddr_in *)addr->ifa_addr)->sin_addr.s_addr; + found = true; + } + } +}; + +struct HWAddressCollector { + uint8_t *result; + bool found; + const char *iface; + + HWAddressCollector(uint8_t *res, const char *interface) : result(res), found(false), iface(interface) { } + + void operator() (struct ifaddrs *addr) { + if(!found && addr->ifa_addr->sa_family == AF_PACKET && !strcmp(addr->ifa_name, iface)) { + memcpy(result, ((struct sockaddr_ll*)addr->ifa_addr)->sll_addr, 6); + found = true; + } + } +}; + uint32_t Tins::Utils::ip_to_int(const string &ip) { uint32_t result(0), i(0), end, bytes_found(0); while(i < ip.size() && bytes_found < 4) { @@ -63,6 +106,47 @@ string Tins::Utils::ip_to_string(uint32_t ip) { return oss.str(); } +bool Tins::Utils::hwaddr_to_byte(const std::string &hw_addr, uint8_t *array) { + if(hw_addr.size() != 17) + return false; + unsigned i(0), arr_index(0); + uint8_t tmp; + while(i < hw_addr.size()) { + unsigned end=i+2; + tmp = 0; + while(i < end) { + if(hw_addr[i] >= 'a' && hw_addr[i] <= 'f') + tmp = (tmp << 4) | (hw_addr[i] - 'a' + 10); + else if(hw_addr[i] >= '0' && hw_addr[i] <= '9') + tmp = (tmp << 4) | (hw_addr[i] - '0'); + else + return false; + i++; + } + array[arr_index++] = tmp; + if(i < hw_addr.size()) { + if(hw_addr[i] == ':') + i++; + else + return false; + } + } + return true; +} + +string Tins::Utils::hwaddr_to_string(uint8_t *array) { + ostringstream oss; + oss << hex; + for(unsigned i(0); i < 6; ++i) { + if(array[i] < 0x10) + oss << '0'; + oss << (unsigned)array[i]; + if(i < 5) + oss << ':'; + } + return oss.str(); +} + uint32_t Tins::Utils::resolve_ip(const string &to_resolve) { struct hostent *data = gethostbyname(to_resolve.c_str()); if(!data) @@ -70,6 +154,25 @@ uint32_t Tins::Utils::resolve_ip(const string &to_resolve) { return ((struct in_addr**)data->h_addr_list)[0]->s_addr; } +set Tins::Utils::network_interfaces() { + InterfaceCollector collector; + generic_iface_loop(collector); + return collector.ifaces; +} + +bool Tins::Utils::interface_ip(const string &iface, uint32_t &ip) { + IPv4Collector collector(iface.c_str()); + generic_iface_loop(collector); + ip = collector.ip; + return collector.found; +} + +bool Tins::Utils::interface_hwaddr(const string &iface, uint8_t *buffer) { + HWAddressCollector collector(buffer, iface.c_str()); + generic_iface_loop(collector); + return collector.found; +} + uint32_t Tins::Utils::crc32(uint8_t* data, uint32_t data_size) { uint32_t i, crc = 0; static uint32_t crc_table[] = {