diff options
Diffstat (limited to 'src/interface_reader.cpp')
-rw-r--r-- | src/interface_reader.cpp | 61 |
1 files changed, 58 insertions, 3 deletions
diff --git a/src/interface_reader.cpp b/src/interface_reader.cpp index f685ad0..7c976da 100644 --- a/src/interface_reader.cpp +++ b/src/interface_reader.cpp @@ -1,17 +1,72 @@ #include "interface_reader.hpp" +#include "interface.hpp" #include "interface_read_error.hpp" -#include <string> + #include <vector> #include <optional> -#include <sys/types.h> +#include <iostream> +#include <fmt/core.h> + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE /* To get defns of NI_MAXSERV and NI_MAXHOST */ +#endif // _GNU_SOURCE + +#include <arpa/inet.h> #include <ifaddrs.h> +#include <linux/if_link.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <unistd.h> -interface_reader::interface_reader(std::vector<std::string> interfaces) : interfaces(interfaces) { +interface_reader::interface_reader(std::vector<std::string> interfaces) : interface_names(interfaces), interfaces() { } std::optional<interface_read_error> interface_reader::read_interfaces(void) { + struct ifaddrs* interface_addresses; + int getifaddrs_result; + + getifaddrs_result = getifaddrs(&interface_addresses); + + if (getifaddrs_result == -1) { + // error while reading interfaces + return std::optional(interface_read_error("Reading interfaces failed")); + } + + char host[NI_MAXHOST]; + + for (struct ifaddrs *ifa = interface_addresses; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == NULL) + continue; + + std::string interface_name = ifa->ifa_name; + + std::optional<std::string> address; + int family = ifa->ifa_addr->sa_family; + if (family == AF_INET || family == AF_INET6) { + int s = getnameinfo(ifa->ifa_addr, + (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), + host, NI_MAXHOST, + NULL, 0, NI_NUMERICHOST); + + if (s != 0) { + std::string errmsg = fmt::format("getnameinfo() failed for interface '{}': {}", interface_name, gai_strerror(s)); + return std::optional<interface_read_error>(interface_read_error(errmsg)); + } + + address = std::optional<std::string>(std::string(host)); + } + + interface ifc(interface_name, address); + this->interfaces.push_back(ifc); + } + + freeifaddrs(interface_addresses); + return {}; } |