#pragma once #include "rublon/utils.hpp" #include #include #include #include #include #include #include #include #include namespace rublon { using socket_t = int; constexpr socket_t invalid_socket = -1; class unique_fd { socket_t fd_ = invalid_socket; public: unique_fd() = default; explicit unique_fd(socket_t fd) : fd_(fd) {} ~unique_fd() { close(fd_); } unique_fd(const unique_fd &) = delete; unique_fd & operator=(const unique_fd &) = delete; unique_fd(unique_fd && other) noexcept : fd_(std::exchange(other.fd_, invalid_socket)) {} unique_fd & operator=(unique_fd && other) noexcept { if(this != &other) { close(fd_); fd_ = std::exchange(other.fd_, invalid_socket); } return *this; } socket_t get() const noexcept { return fd_; } socket_t release() noexcept { return std::exchange(fd_, invalid_socket); } void reset(socket_t fd = invalid_socket) noexcept { if(fd_ != fd) { close(fd_); fd_ = fd; } } explicit operator bool() const noexcept { return fd_ != invalid_socket; } }; // this function is a little hack just to fix RSUP-1413 // When loging to rublon from withing the host itself, there is no IP delivered through any 'pam_item' // but we need to log from what place the request did came. tl::expected< std::pmr::string, Error > getDefaultRouteIp(std::pmr::memory_resource * mr) { log(LogLevel::Debug, "Reading default route IP"); unique_fd sock(::socket(AF_INET, SOCK_DGRAM, 0)); if(!sock){ log(LogLevel::Warning, "Cant create socket"); return tl::unexpected{Error{RublonRuntimeException::CantCreateSocket}}; } sockaddr_in remote{}; remote.sin_family = AF_INET; remote.sin_port = htons(53); ::inet_pton(AF_INET, "8.8.8.8", &remote.sin_addr); // we use UDP so no actual connection is estamblished. Only trying to get an interface if(::connect(sock.get(), ( struct sockaddr * ) &remote, sizeof(remote)) < 0) { log(LogLevel::Warning, "Cant connect to socket"); return tl::unexpected{Error{RublonRuntimeException::ConnectionFailed}}; } sockaddr_in local{}; socklen_t len = sizeof(local); if(::getsockname(sock.get(), ( struct sockaddr * ) &local, &len) < 0) { log(LogLevel::Warning, "Cant get socket name"); return tl::unexpected{Error{RublonRuntimeException::CantGetSocketName}}; } char ip[INET_ADDRSTRLEN]; ::inet_ntop(AF_INET, &local.sin_addr, ip, sizeof(ip)); return std::pmr::string{ip, mr}; } } // namespace rublon