From 583214ec98443dd7670de257270535e8439057e0 Mon Sep 17 00:00:00 2001 From: sitzmaa Date: Fri, 14 Feb 2025 10:32:10 -0800 Subject: [PATCH 1/7] added plugin support for main.cpp --- README.md | 6 ++ backend/CMakeLists.txt | 1 + backend/include/plugin.hpp | 28 ++++++++ .../include/{ => utilities}/dns_lookup.hpp | 0 .../include/{ => utilities}/network_scan.hpp | 0 backend/include/utilities/nmap.hpp | 13 ++++ backend/include/utilities/nping.hpp | 0 backend/include/{ => utilities}/ping.hpp | 0 .../include/{ => utilities}/traceroute.hpp | 0 backend/src/main.cpp | 63 ++++++++++++++++- backend/src/utilities/nmap.cpp | 68 +++++++++++++++++++ backend/src/utilities/nping.cpp | 25 +++++++ 12 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 backend/include/plugin.hpp rename backend/include/{ => utilities}/dns_lookup.hpp (100%) rename backend/include/{ => utilities}/network_scan.hpp (100%) create mode 100644 backend/include/utilities/nmap.hpp create mode 100644 backend/include/utilities/nping.hpp rename backend/include/{ => utilities}/ping.hpp (100%) rename backend/include/{ => utilities}/traceroute.hpp (100%) create mode 100644 backend/src/utilities/nmap.cpp create mode 100644 backend/src/utilities/nping.cpp diff --git a/README.md b/README.md index 043b6af..36c01ed 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,12 @@ Javascript web server fnctionality to allow easy status checks #### Packaging Create official packages for release +#### Storage Efficiency + +Currently the persistant storage is in the form of JSON + +-- Look into if SQLite would work better + ## Installation 1. Clone the repository: diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index 8a1a92e..f834b11 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -13,6 +13,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED True) # Add the include directories for libraries include_directories(${CMAKE_SOURCE_DIR}/include) +include_directories(${CMAKE_SOURCE_DIR}/include/utilities) include_directories(${CMAKE_SOURCE_DIR}/externals) # Importing Boost diff --git a/backend/include/plugin.hpp b/backend/include/plugin.hpp new file mode 100644 index 0000000..f8aca89 --- /dev/null +++ b/backend/include/plugin.hpp @@ -0,0 +1,28 @@ +#ifndef PLUGIN_HPP +#define PLUGIN_HPP + +#include + +class Plugin { +public: + virtual ~Plugin() {} + + // Initialize the plugin + virtual void initialize() = 0; + + // Execute the plugin (e.g., update stats or provide functionality) + virtual void execute() = 0; + + // Return a name or description for the plugin + virtual std::string name() const = 0; + + // Cleanup any resources used by the plugin + virtual void cleanup() = 0; +}; + +extern "C" { + Plugin* create_plugin(); + void destroy_plugin(Plugin* plugin); +} + +#endif // PLUGIN_HPP \ No newline at end of file diff --git a/backend/include/dns_lookup.hpp b/backend/include/utilities/dns_lookup.hpp similarity index 100% rename from backend/include/dns_lookup.hpp rename to backend/include/utilities/dns_lookup.hpp diff --git a/backend/include/network_scan.hpp b/backend/include/utilities/network_scan.hpp similarity index 100% rename from backend/include/network_scan.hpp rename to backend/include/utilities/network_scan.hpp diff --git a/backend/include/utilities/nmap.hpp b/backend/include/utilities/nmap.hpp new file mode 100644 index 0000000..57c737c --- /dev/null +++ b/backend/include/utilities/nmap.hpp @@ -0,0 +1,13 @@ +#ifndef NMAP_H +#define NMAP_H + +#include +#include +#include + +bool scanHost(const std::string& target); +bool scanHosts(const std::vector& targets); +std::unordered_map getOpenPorts(const std::string& target); +bool pingHost(const std::string& target); + +#endif // NMAP_H \ No newline at end of file diff --git a/backend/include/utilities/nping.hpp b/backend/include/utilities/nping.hpp new file mode 100644 index 0000000..e69de29 diff --git a/backend/include/ping.hpp b/backend/include/utilities/ping.hpp similarity index 100% rename from backend/include/ping.hpp rename to backend/include/utilities/ping.hpp diff --git a/backend/include/traceroute.hpp b/backend/include/utilities/traceroute.hpp similarity index 100% rename from backend/include/traceroute.hpp rename to backend/include/utilities/traceroute.hpp diff --git a/backend/src/main.cpp b/backend/src/main.cpp index b8b26cd..23b5a88 100644 --- a/backend/src/main.cpp +++ b/backend/src/main.cpp @@ -1,6 +1,63 @@ #include "network_server.hpp" +#include "plugin.hpp" #include -#include // For std::stoi +#include +#include // For dynamic loading on Linux/macOS +#include // For reading directories +#include +#include + +void loadPlugins(const std::string& pluginFolder) { + DIR* dir = opendir(pluginFolder.c_str()); + if (dir == nullptr) { + std::cerr << "Error opening plugin directory: " << pluginFolder << std::endl; + return; + } + + struct dirent* entry; + while ((entry = readdir(dir)) != nullptr) { + // Only process files that have .so extension + std::string filename(entry->d_name); + if (filename.substr(filename.find_last_of(".") + 1) == "so") { + std::string pluginPath = pluginFolder + "/" + filename; + + // Load the plugin dynamically + void* handle = dlopen(pluginPath.c_str(), RTLD_LAZY); + if (!handle) { + std::cerr << "Error loading plugin " << pluginPath << ": " << dlerror() << std::endl; + continue; // Skip this plugin and continue with the others + } + + // Load the 'create_plugin' and 'destroy_plugin' functions + typedef Plugin* (*CreatePlugin)(); + typedef void (*DestroyPlugin)(Plugin*); + CreatePlugin create_plugin = (CreatePlugin) dlsym(handle, "create_plugin"); + DestroyPlugin destroy_plugin = (DestroyPlugin) dlsym(handle, "destroy_plugin"); + + if (!create_plugin || !destroy_plugin) { + std::cerr << "Error loading functions from plugin " << pluginPath << ": " << dlerror() << std::endl; + dlclose(handle); + continue; + } + + // Create the plugin and initialize it + Plugin* plugin = create_plugin(); + plugin->initialize(); + + // Execute the plugin + plugin->execute(); + + std::cout << "Loaded plugin: " << plugin->name() << std::endl; + + // Cleanup and unload the plugin + plugin->cleanup(); + destroy_plugin(plugin); + dlclose(handle); + } + } + + closedir(dir); +} int main(int argc, char* argv[]) { if (argc != 2) { @@ -15,6 +72,10 @@ int main(int argc, char* argv[]) { // Create the server object and start it NetworkServer server(port); server.start(); + + // Load and execute plugins from the ../plugins directory + loadPlugins("../plugins"); + } catch (const std::invalid_argument& e) { std::cerr << "Error: Invalid port number. Please provide a valid integer." << std::endl; return 1; diff --git a/backend/src/utilities/nmap.cpp b/backend/src/utilities/nmap.cpp new file mode 100644 index 0000000..523adb0 --- /dev/null +++ b/backend/src/utilities/nmap.cpp @@ -0,0 +1,68 @@ +#include "nmap.h" +#include +#include +#include +#include +#include +#include +#include + +bool scanHost(const std::string& target) { + std::cout << "Scanning host: " << target << std::endl; + + // First, check if the host is reachable + if (!pingHost(target)) { + std::cerr << "Host " << target << " is not reachable." << std::endl; + return false; + } + + // Scan open ports + auto openPorts = getOpenPorts(target); + if (openPorts.empty()) { + std::cout << "No open ports found on " << target << std::endl; + return false; + } + + std::cout << "Open ports for " << target << ":" << std::endl; + for (const auto& port : openPorts) { + std::cout << "Port " << port.first << ": " << port.second << std::endl; + } + return true; +} + +bool scanHosts(const std::vector& targets) { + for (const auto& target : targets) { + scanHost(target); + } + return true; +} + +std::unordered_map getOpenPorts(const std::string& target) { + std::unordered_map openPorts; + // Implement port scanning logic here (simple example) + for (int port = 20; port <= 1024; ++port) { + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd == -1) { + std::cerr << "Socket creation failed." << std::endl; + continue; + } + + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = inet_addr(target.c_str()); + + int connection = connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)); + if (connection == 0) { + openPorts[port] = "Open"; + } + close(sockfd); + } + return openPorts; +} + +bool pingHost(const std::string& target) { + std::string cmd = "ping -c 1 " + target + " > /dev/null 2>&1"; + return system(cmd.c_str()) == 0; +} \ No newline at end of file diff --git a/backend/src/utilities/nping.cpp b/backend/src/utilities/nping.cpp new file mode 100644 index 0000000..9e1a81f --- /dev/null +++ b/backend/src/utilities/nping.cpp @@ -0,0 +1,25 @@ +#include "nping.hpp" +#include "nmap.hpp" +#include + +void advancedPing(const std::string& target) { + std::cout << "Performing advanced ping on " << target << std::endl; + + // First, ping the target + if (pingHost(target)) { + std::cout << target << " is alive!" << std::endl; + } else { + std::cout << target << " is not reachable!" << std::endl; + } + + // Then, check open ports + auto openPorts = getOpenPorts(target); + if (!openPorts.empty()) { + std::cout << "Open ports on " << target << ":" << std::endl; + for (const auto& port : openPorts) { + std::cout << "Port " << port.first << ": " << port.second << std::endl; + } + } else { + std::cout << "No open ports found on " << target << std::endl; + } +} \ No newline at end of file From c39867b201007da1e49065ff90f679fac237813b Mon Sep 17 00:00:00 2001 From: sitzmaa Date: Fri, 14 Feb 2025 10:37:27 -0800 Subject: [PATCH 2/7] removed redundant message in network_server:handle_client --- backend/src/network_server.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/network_server.cpp b/backend/src/network_server.cpp index 27e3265..48f8542 100644 --- a/backend/src/network_server.cpp +++ b/backend/src/network_server.cpp @@ -16,7 +16,6 @@ void NetworkServer::start() { void NetworkServer::handle_client(tcp::socket socket) { try { - std::cout << "Client connected" << std::endl; // Read initial message to determine client type asio::streambuf buffer; From 87841cb0d6ad3ba82933282ad71936f623908749 Mon Sep 17 00:00:00 2001 From: sitzmaa Date: Fri, 14 Feb 2025 11:25:45 -0800 Subject: [PATCH 3/7] added more utility function interfaces --- README.md | 4 +- backend/include/utilities/dig_x.hpp | 23 ++++ backend/include/utilities/dns_lookup.hpp | 5 - backend/include/utilities/network_scan.hpp | 5 - backend/include/utilities/nmap.hpp | 13 -- backend/include/utilities/nmap_x.hpp | 28 ++++ backend/include/utilities/ping.hpp | 5 - backend/include/utilities/ping_x.hpp | 14 ++ backend/include/utilities/traceroute.hpp | 5 - backend/include/utilities/traceroute_x.hpp | 13 ++ backend/src/utilities/dig_x.cpp | 70 ++++++++++ backend/src/utilities/dns_lookup.cpp | 11 -- backend/src/utilities/network_scan.cpp | 6 - backend/src/utilities/nmap.cpp | 68 --------- backend/src/utilities/nmap_x.cpp | 152 +++++++++++++++++++++ backend/src/utilities/ping.cpp | 6 - backend/src/utilities/ping_x.cpp | 58 ++++++++ backend/src/utilities/traceroute.cpp | 6 - backend/src/utilities/traceroute_x.cpp | 51 +++++++ 19 files changed, 411 insertions(+), 132 deletions(-) create mode 100644 backend/include/utilities/dig_x.hpp delete mode 100644 backend/include/utilities/dns_lookup.hpp delete mode 100644 backend/include/utilities/network_scan.hpp delete mode 100644 backend/include/utilities/nmap.hpp create mode 100644 backend/include/utilities/nmap_x.hpp delete mode 100644 backend/include/utilities/ping.hpp create mode 100644 backend/include/utilities/ping_x.hpp delete mode 100644 backend/include/utilities/traceroute.hpp create mode 100644 backend/include/utilities/traceroute_x.hpp create mode 100644 backend/src/utilities/dig_x.cpp delete mode 100644 backend/src/utilities/dns_lookup.cpp delete mode 100644 backend/src/utilities/network_scan.cpp delete mode 100644 backend/src/utilities/nmap.cpp create mode 100644 backend/src/utilities/nmap_x.cpp delete mode 100644 backend/src/utilities/ping.cpp create mode 100644 backend/src/utilities/ping_x.cpp delete mode 100644 backend/src/utilities/traceroute.cpp create mode 100644 backend/src/utilities/traceroute_x.cpp diff --git a/README.md b/README.md index 36c01ed..a252bf3 100644 --- a/README.md +++ b/README.md @@ -72,12 +72,12 @@ cd netmap Mac-OS ``` bash - brew install boost nlohmann-json + brew install boost nlohmann-json tinyxml2 ``` Debian ``` bash - sudo apt install nlohmann-json3-dev boost + sudo apt install nlohmann-json3-dev boost libtinyxml2.6.2-dev ``` -- the boost library is required for the ASIO library to work with CMake, however ASIO is also included with Clang if you would rather use that diff --git a/backend/include/utilities/dig_x.hpp b/backend/include/utilities/dig_x.hpp new file mode 100644 index 0000000..c39fecd --- /dev/null +++ b/backend/include/utilities/dig_x.hpp @@ -0,0 +1,23 @@ +#ifndef DIG_X_HPP +#define DIG_X_HPP + +#include + +// Define bitwise flags for Dig options +#define DIG_A_RECORD (1 << 0) // 00001 +#define DIG_MX_RECORD (1 << 1) // 00010 +#define DIG_CNAME_RECORD (1 << 2) // 00100 +#define DIG_NS_RECORD (1 << 3) // 01000 +#define DIG_SOA_RECORD (1 << 4) // 10000 + +// Function that interacts with dig and parses results based on bitwise options +std::string dig_x(const std::string& domain, int options); + +// Helper functions to parse dig response +std::string parse_a_record(const std::string& raw_response); +std::string parse_mx_record(const std::string& raw_response); +std::string parse_cname_record(const std::string& raw_response); +std::string parse_ns_record(const std::string& raw_response); +std::string parse_soa_record(const std::string& raw_response); + +#endif // DIG_X_HPP \ No newline at end of file diff --git a/backend/include/utilities/dns_lookup.hpp b/backend/include/utilities/dns_lookup.hpp deleted file mode 100644 index f9c5219..0000000 --- a/backend/include/utilities/dns_lookup.hpp +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef DNS_LOOKUP_HPP -#define DNS_LOOKUP_HPP -#include -std::string dns_lookup(const std::string& hostname); -#endif \ No newline at end of file diff --git a/backend/include/utilities/network_scan.hpp b/backend/include/utilities/network_scan.hpp deleted file mode 100644 index 7c1e416..0000000 --- a/backend/include/utilities/network_scan.hpp +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef NETWORK_SCAN_HPP -#define NETWORK_SCAN_HPP -#include -std::vector scan_network(); -#endif \ No newline at end of file diff --git a/backend/include/utilities/nmap.hpp b/backend/include/utilities/nmap.hpp deleted file mode 100644 index 57c737c..0000000 --- a/backend/include/utilities/nmap.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef NMAP_H -#define NMAP_H - -#include -#include -#include - -bool scanHost(const std::string& target); -bool scanHosts(const std::vector& targets); -std::unordered_map getOpenPorts(const std::string& target); -bool pingHost(const std::string& target); - -#endif // NMAP_H \ No newline at end of file diff --git a/backend/include/utilities/nmap_x.hpp b/backend/include/utilities/nmap_x.hpp new file mode 100644 index 0000000..d364642 --- /dev/null +++ b/backend/include/utilities/nmap_x.hpp @@ -0,0 +1,28 @@ +#ifndef NMAP_X_HPP +#define NMAP_X_HPP + +#include +#include +#include + +// Define bitwise flags for Nmap options +constexpr uint8_t NMAP_OPEN_PORT = 0x01; +constexpr uint8_t NMAP_PUBLIC_IP = 0x02; +constexpr uint8_t NMAP_MAC_ADDRESS = 0x04; +constexpr uint8_t NMAP_DOMAIN = 0x08; +constexpr uint8_t NMAP_OS = 0x10; + +class NmapX { +public: + // Main function to execute the scan and parse the result + static std::vector scan(const std::string& target, uint8_t options); + +private: + // Helper function to run the nmap scan and return the XML output + static std::string run_nmap(const std::string& target, uint8_t options); + + // Function to parse the nmap XML result and extract requested data + static std::vector parse_nmap_xml(const std::string& xml_data, uint8_t options); +}; + +#endif // NMAP_X_HPP diff --git a/backend/include/utilities/ping.hpp b/backend/include/utilities/ping.hpp deleted file mode 100644 index a863bf4..0000000 --- a/backend/include/utilities/ping.hpp +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef PING_HPP -#define PING_HPP -#include -std::string ping(const std::string& ip); -#endif \ No newline at end of file diff --git a/backend/include/utilities/ping_x.hpp b/backend/include/utilities/ping_x.hpp new file mode 100644 index 0000000..e5a5083 --- /dev/null +++ b/backend/include/utilities/ping_x.hpp @@ -0,0 +1,14 @@ +#ifndef PING_X_HPP +#define PING_X_HPP + +#include + +// Define bitwise flags for Ping options +#define PING_LATENCY (1 << 0) // Extract latency (RTT) +#define PING_PACKET_LOSS (1 << 1) // Extract packet loss percentage +#define PING_TTL (1 << 2) // Extract TTL (Time to Live) +#define PING_IP (1 << 3) // Extract target IP address + +std::string ping_x(const std::string& ip, int options); + +#endif // PING_X_HPP \ No newline at end of file diff --git a/backend/include/utilities/traceroute.hpp b/backend/include/utilities/traceroute.hpp deleted file mode 100644 index ccb3879..0000000 --- a/backend/include/utilities/traceroute.hpp +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef TRACEROUTE_HPP -#define TRACEROUTE_HPP -#include -std::string traceroute(const std::string& ip); -#endif \ No newline at end of file diff --git a/backend/include/utilities/traceroute_x.hpp b/backend/include/utilities/traceroute_x.hpp new file mode 100644 index 0000000..d05dbf6 --- /dev/null +++ b/backend/include/utilities/traceroute_x.hpp @@ -0,0 +1,13 @@ +#ifndef TRACEROUTE_X_HPP +#define TRACEROUTE_X_HPP + +#include + +// Define bitwise flags for Traceroute options +#define TRACE_HOPS (1 << 0) // Extract number of hops +#define TRACE_LATENCY (1 << 1) // Extract per-hop latency +#define TRACE_IPS (1 << 2) // Extract IP addresses in the route + +std::string traceroute_x(const std::string& target, int options); + +#endif // TRACEROUTE_X_HPP \ No newline at end of file diff --git a/backend/src/utilities/dig_x.cpp b/backend/src/utilities/dig_x.cpp new file mode 100644 index 0000000..53ea93f --- /dev/null +++ b/backend/src/utilities/dig_x.cpp @@ -0,0 +1,70 @@ +#include "dig_x.hpp" +#include +#include +#include +#include +#include "dns_lookup.hpp" // Assuming dns_lookup.hpp defines the base DNS lookup function + +std::string dig_x(const std::string& domain, int options) { + // Call the base DNS lookup function (assumed to execute dig) + std::string raw_response = dns_lookup(domain); + + std::string result; + if (options & DIG_A_RECORD) result += parse_a_record(raw_response); + if (options & DIG_MX_RECORD) result += parse_mx_record(raw_response); + if (options & DIG_CNAME_RECORD) result += parse_cname_record(raw_response); + if (options & DIG_NS_RECORD) result += parse_ns_record(raw_response); + if (options & DIG_SOA_RECORD) result += parse_soa_record(raw_response); + + return result.empty() ? "No matching records found\n" : result; +} + +// Helper function to extract A record (IPv4) +std::string parse_a_record(const std::string& raw_response) { + std::regex re("\\b([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})\\b"); + std::smatch match; + if (std::regex_search(raw_response, match, re)) { + return "A Record: " + match[1].str() + "\n"; + } + return ""; +} + +// Helper function to extract MX record +std::string parse_mx_record(const std::string& raw_response) { + std::regex re("([0-9]+)\\s+IN\\s+MX\\s+([a-zA-Z0-9.-]+)"); + std::smatch match; + if (std::regex_search(raw_response, match, re)) { + return "MX Record: " + match[2].str() + " (Priority: " + match[1].str() + ")\n"; + } + return ""; +} + +// Helper function to extract CNAME record +std::string parse_cname_record(const std::string& raw_response) { + std::regex re("CNAME\\s+([a-zA-Z0-9.-]+)"); + std::smatch match; + if (std::regex_search(raw_response, match, re)) { + return "CNAME Record: " + match[1].str() + "\n"; + } + return ""; +} + +// Helper function to extract NS record +std::string parse_ns_record(const std::string& raw_response) { + std::regex re("IN\\s+NS\\s+([a-zA-Z0-9.-]+)"); + std::smatch match; + if (std::regex_search(raw_response, match, re)) { + return "NS Record: " + match[1].str() + "\n"; + } + return ""; +} + +// Helper function to extract SOA record +std::string parse_soa_record(const std::string& raw_response) { + std::regex re("SOA\\s+([a-zA-Z0-9.-]+)\\s+([a-zA-Z0-9.-]+)"); + std::smatch match; + if (std::regex_search(raw_response, match, re)) { + return "SOA Record: " + match[1].str() + " " + match[2].str() + "\n"; + } + return ""; +} \ No newline at end of file diff --git a/backend/src/utilities/dns_lookup.cpp b/backend/src/utilities/dns_lookup.cpp deleted file mode 100644 index af8bef0..0000000 --- a/backend/src/utilities/dns_lookup.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "dns_lookup.hpp" -#include -#include -#include -#include - -std::string dns_lookup(const std::string& hostname) { - struct hostent *he = gethostbyname(hostname.c_str()); - if (he == nullptr) return "DNS lookup failed"; - return std::string(inet_ntoa(*(struct in_addr*)he->h_addr)); -} \ No newline at end of file diff --git a/backend/src/utilities/network_scan.cpp b/backend/src/utilities/network_scan.cpp deleted file mode 100644 index f321c72..0000000 --- a/backend/src/utilities/network_scan.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "network_scan.hpp" -#include - -std::vector scan_network() { - return {"192.168.1.1", "192.168.1.2"}; -} \ No newline at end of file diff --git a/backend/src/utilities/nmap.cpp b/backend/src/utilities/nmap.cpp deleted file mode 100644 index 523adb0..0000000 --- a/backend/src/utilities/nmap.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "nmap.h" -#include -#include -#include -#include -#include -#include -#include - -bool scanHost(const std::string& target) { - std::cout << "Scanning host: " << target << std::endl; - - // First, check if the host is reachable - if (!pingHost(target)) { - std::cerr << "Host " << target << " is not reachable." << std::endl; - return false; - } - - // Scan open ports - auto openPorts = getOpenPorts(target); - if (openPorts.empty()) { - std::cout << "No open ports found on " << target << std::endl; - return false; - } - - std::cout << "Open ports for " << target << ":" << std::endl; - for (const auto& port : openPorts) { - std::cout << "Port " << port.first << ": " << port.second << std::endl; - } - return true; -} - -bool scanHosts(const std::vector& targets) { - for (const auto& target : targets) { - scanHost(target); - } - return true; -} - -std::unordered_map getOpenPorts(const std::string& target) { - std::unordered_map openPorts; - // Implement port scanning logic here (simple example) - for (int port = 20; port <= 1024; ++port) { - int sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (sockfd == -1) { - std::cerr << "Socket creation failed." << std::endl; - continue; - } - - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = inet_addr(target.c_str()); - - int connection = connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)); - if (connection == 0) { - openPorts[port] = "Open"; - } - close(sockfd); - } - return openPorts; -} - -bool pingHost(const std::string& target) { - std::string cmd = "ping -c 1 " + target + " > /dev/null 2>&1"; - return system(cmd.c_str()) == 0; -} \ No newline at end of file diff --git a/backend/src/utilities/nmap_x.cpp b/backend/src/utilities/nmap_x.cpp new file mode 100644 index 0000000..96cbf2a --- /dev/null +++ b/backend/src/utilities/nmap_x.cpp @@ -0,0 +1,152 @@ +#include "nmap_x.hpp" +#include +#include +#include +#include +#include +#include +#include + +using namespace tinyxml2; + +// Helper function to run the nmap scan and return the XML output +std::string run_nmap(const std::string& target, int options) { + std::ostringstream cmd_stream; + cmd_stream << "nmap -oX - "; // Use standard output in XML format + + // Add options to the command based on bitwise flags + if (options & NMAP_OPEN_PORT) { + cmd_stream << "-p- "; // Scan all ports + } + if (options & NMAP_PUBLIC_IP) { + cmd_stream << "--unprivileged "; // Optional: run nmap without root privileges + } + if (options & NMAP_MAC_ADDRESS) { + cmd_stream << "--osscan-guess "; // Guess OS based on MAC address + } + if (options & NMAP_DOMAIN) { + cmd_stream << "--dns-servers "; // Optionally specify DNS server + } + if (options & NMAP_OS) { + cmd_stream << "-O "; // Enable OS detection + } + + cmd_stream << target; + + std::string cmd = cmd_stream.str(); + std::array buffer; + std::string result; + std::shared_ptr pipe(popen(cmd.c_str(), "r"), fclose); + + if (!pipe) { + throw std::runtime_error("Failed to run nmap command"); + } + + while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { + result += buffer.data(); + } + + return result; +} + +// Function to parse the nmap XML result and extract requested data +std::vector parse_nmap_xml(const std::string& xml_data, int options) { + XMLDocument doc; + std::vector results; + + // Parse the XML data + if (doc.Parse(xml_data.c_str()) != XML_SUCCESS) { + throw std::runtime_error("Failed to parse XML data from nmap"); + } + + XMLElement* root = doc.RootElement(); + if (root == nullptr) { + throw std::runtime_error("Failed to find root element in nmap XML"); + } + + // Extract the requested information based on bitwise flags + if (options & NMAP_OPEN_PORT) { + XMLElement* host = root->FirstChildElement("host"); + while (host) { + XMLElement* ports = host->FirstChildElement("ports"); + if (ports) { + for (XMLElement* port = ports->FirstChildElement("port"); port; port = port->NextSiblingElement("port")) { + const char* port_str = port->Attribute("portid"); + if (port_str) { + results.push_back("Open Port: " + std::string(port_str)); + } + } + } + host = host->NextSiblingElement("host"); + } + } + if (options & NMAP_PUBLIC_IP) { + XMLElement* host = root->FirstChildElement("host"); + while (host) { + XMLElement* address = host->FirstChildElement("address"); + if (address) { + const char* ip = address->Attribute("addr"); + if (ip) { + results.push_back("Public IP: " + std::string(ip)); + } + } + host = host->NextSiblingElement("host"); + } + } + if (options & NMAP_MAC_ADDRESS) { + XMLElement* host = root->FirstChildElement("host"); + while (host) { + XMLElement* hostnames = host->FirstChildElement("hostnames"); + if (hostnames) { + for (XMLElement* hostname = hostnames->FirstChildElement("hostname"); hostname; hostname = hostname->NextSiblingElement("hostname")) { + const char* mac = hostname->Attribute("mac"); + if (mac) { + results.push_back("MAC Address: " + std::string(mac)); + } + } + } + host = host->NextSiblingElement("host"); + } + } + if (options & NMAP_DOMAIN) { + XMLElement* host = root->FirstChildElement("host"); + while (host) { + XMLElement* hostnames = host->FirstChildElement("hostnames"); + if (hostnames) { + for (XMLElement* hostname = hostnames->FirstChildElement("hostname"); hostname; hostname = hostname->NextSiblingElement("hostname")) { + const char* domain = hostname->Attribute("name"); + if (domain) { + results.push_back("Domain: " + std::string(domain)); + } + } + } + host = host->NextSiblingElement("host"); + } + } + if (options & NMAP_OS) { + XMLElement* host = root->FirstChildElement("host"); + while (host) { + XMLElement* os = host->FirstChildElement("os-fingerprint"); + if (os) { + const char* os_name = os->Attribute("os"); + if (os_name) { + results.push_back("OS: " + std::string(os_name)); + } + } + host = host->NextSiblingElement("host"); + } + } + + return results; +} + +// Main function to execute the scan and parse the result +std::vector nmap_x(const std::string& target, int options) { + try { + std::string scan_result = run_nmap(target, options); + return parse_nmap_xml(scan_result, options); + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return {}; // Return empty list on error + } +} diff --git a/backend/src/utilities/ping.cpp b/backend/src/utilities/ping.cpp deleted file mode 100644 index 051367e..0000000 --- a/backend/src/utilities/ping.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "ping.hpp" -#include - -std::string ping(const std::string& ip) { - return "Ping response from " + ip; -} \ No newline at end of file diff --git a/backend/src/utilities/ping_x.cpp b/backend/src/utilities/ping_x.cpp new file mode 100644 index 0000000..0ec8b78 --- /dev/null +++ b/backend/src/utilities/ping_x.cpp @@ -0,0 +1,58 @@ +#include "ping_x.hpp" +#include +#include +#include +#include + +std::string execute_ping(const std::string& ip) { + std::string command = "ping -c 4 " + ip + " 2>&1"; + FILE* pipe = popen(command.c_str(), "r"); + if (!pipe) throw std::runtime_error("Failed to execute ping command"); + + char buffer[128]; + std::string result; + while (fgets(buffer, sizeof(buffer), pipe) != nullptr) { + result += buffer; + } + pclose(pipe); + return result; +} + +std::string parse_ping_latency(const std::string& response) { + std::regex re("min/avg/max/mdev = ([0-9.]+)/([0-9.]+)/([0-9.]+)/([0-9.]+)"); + std::smatch match; + if (std::regex_search(response, match, re)) { + return "Latency (RTT): " + match[2].str() + " ms\n"; + } + return ""; +} + +std::string parse_ping_packet_loss(const std::string& response) { + std::regex re("([0-9]+)% packet loss"); + std::smatch match; + if (std::regex_search(response, match, re)) { + return "Packet Loss: " + match[1].str() + "%\n"; + } + return ""; +} + +std::string parse_ping_ttl(const std::string& response) { + std::regex re("ttl=([0-9]+)"); + std::smatch match; + if (std::regex_search(response, match, re)) { + return "TTL: " + match[1].str() + "\n"; + } + return ""; +} + +std::string ping_x(const std::string& ip, int options) { + std::string response = execute_ping(ip); + std::string result; + + if (options & PING_LATENCY) result += parse_ping_latency(response); + if (options & PING_PACKET_LOSS) result += parse_ping_packet_loss(response); + if (options & PING_TTL) result += parse_ping_ttl(response); + if (options & PING_IP) result += "Target IP: " + ip + "\n"; + + return result.empty() ? "No matching ping results\n" : result; +} \ No newline at end of file diff --git a/backend/src/utilities/traceroute.cpp b/backend/src/utilities/traceroute.cpp deleted file mode 100644 index 4f3ab5d..0000000 --- a/backend/src/utilities/traceroute.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "traceroute.hpp" -#include - -std::string traceroute(const std::string& ip) { - return "Traceroute result for " + ip; -} \ No newline at end of file diff --git a/backend/src/utilities/traceroute_x.cpp b/backend/src/utilities/traceroute_x.cpp new file mode 100644 index 0000000..f01a4b2 --- /dev/null +++ b/backend/src/utilities/traceroute_x.cpp @@ -0,0 +1,51 @@ +#include "traceroute_x.hpp" +#include +#include +#include +#include + +std::string execute_traceroute(const std::string& target) { + std::string command = "traceroute -n " + target + " 2>&1"; + FILE* pipe = popen(command.c_str(), "r"); + if (!pipe) throw std::runtime_error("Failed to execute traceroute command"); + + char buffer[256]; + std::string result; + while (fgets(buffer, sizeof(buffer), pipe) != nullptr) { + result += buffer; + } + pclose(pipe); + return result; +} + +std::string parse_hop_count(const std::string& response) { + std::istringstream stream(response); + std::string line; + int hop_count = 0; + while (std::getline(stream, line)) hop_count++; + return "Total Hops: " + std::to_string(hop_count) + "\n"; +} + +std::string parse_ips(const std::string& response) { + std::regex re("\\b(\\d+\\.\\d+\\.\\d+\\.\\d+)\\b"); + std::smatch match; + std::string result = "Traceroute IPs: "; + bool found = false; + while (std::regex_search(response, match, re)) { + result += match[1].str() + " -> "; + response = match.suffix().str(); + found = true; + } + return found ? result + "End\n" : ""; +} + +std::string traceroute_x(const std::string& target, int options) { + std::string response = execute_traceroute(target); + std::string result; + + if (options & TRACE_HOPS) result += parse_hop_count(response); + if (options & TRACE_LATENCY) result += response; // Return raw latency info + if (options & TRACE_IPS) result += parse_ips(response); + + return result.empty() ? "No matching traceroute results\n" : result; +} \ No newline at end of file From 3b025defe5c64fd373babe824c1ffcf84753762b Mon Sep 17 00:00:00 2001 From: sitzmaa Date: Fri, 14 Feb 2025 11:39:09 -0800 Subject: [PATCH 4/7] stable build --- backend/CMakeLists.txt | 12 ++--- backend/include/utilities/dig_x.hpp | 30 ++++++------ backend/src/utilities/dig_x.cpp | 65 +++++++++++++++++--------- backend/src/utilities/traceroute_x.cpp | 2 +- 4 files changed, 67 insertions(+), 42 deletions(-) diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index f834b11..ccf0434 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -30,10 +30,10 @@ find_package(nlohmann_json REQUIRED) include_directories(${nlohmann_json_INCLUDE_DIRS}) # Add the libraries -add_library(traceroute src/utilities/traceroute.cpp) -add_library(ping src/utilities/ping.cpp) -add_library(dns_lookup src/utilities/dns_lookup.cpp) -add_library(network_scan src/utilities/network_scan.cpp) +add_library(traceroute src/utilities/traceroute_x.cpp) +add_library(ping src/utilities/ping_x.cpp) +add_library(dig src/utilities/dig_x.cpp) +add_library(nmap src/utilities/nmap_x.cpp) add_library(server src/network_server.cpp) target_link_libraries(server ${Boost_LIBRARIES}) @@ -45,7 +45,7 @@ target_link_libraries(netmap_backend server traceroute ping - dns_lookup - network_scan + dig + nmap nlohmann_json::nlohmann_json ) diff --git a/backend/include/utilities/dig_x.hpp b/backend/include/utilities/dig_x.hpp index c39fecd..6e63065 100644 --- a/backend/include/utilities/dig_x.hpp +++ b/backend/include/utilities/dig_x.hpp @@ -3,21 +3,23 @@ #include -// Define bitwise flags for Dig options -#define DIG_A_RECORD (1 << 0) // 00001 -#define DIG_MX_RECORD (1 << 1) // 00010 -#define DIG_CNAME_RECORD (1 << 2) // 00100 -#define DIG_NS_RECORD (1 << 3) // 01000 -#define DIG_SOA_RECORD (1 << 4) // 10000 +#define DIG_A_RECORD 0x01 +#define DIG_MX_RECORD 0x02 +#define DIG_CNAME_RECORD 0x04 +#define DIG_NS_RECORD 0x08 +#define DIG_SOA_RECORD 0x10 -// Function that interacts with dig and parses results based on bitwise options -std::string dig_x(const std::string& domain, int options); +class DigX { +public: + static std::string dig_x(const std::string& domain, int options); -// Helper functions to parse dig response -std::string parse_a_record(const std::string& raw_response); -std::string parse_mx_record(const std::string& raw_response); -std::string parse_cname_record(const std::string& raw_response); -std::string parse_ns_record(const std::string& raw_response); -std::string parse_soa_record(const std::string& raw_response); +private: + static std::string execute_dig(const std::string& domain); + static std::string parse_a_record(const std::string& raw_response); + static std::string parse_mx_record(const std::string& raw_response); + static std::string parse_cname_record(const std::string& raw_response); + static std::string parse_ns_record(const std::string& raw_response); + static std::string parse_soa_record(const std::string& raw_response); +}; #endif // DIG_X_HPP \ No newline at end of file diff --git a/backend/src/utilities/dig_x.cpp b/backend/src/utilities/dig_x.cpp index 53ea93f..65ac981 100644 --- a/backend/src/utilities/dig_x.cpp +++ b/backend/src/utilities/dig_x.cpp @@ -3,11 +3,10 @@ #include #include #include -#include "dns_lookup.hpp" // Assuming dns_lookup.hpp defines the base DNS lookup function +#include -std::string dig_x(const std::string& domain, int options) { - // Call the base DNS lookup function (assumed to execute dig) - std::string raw_response = dns_lookup(domain); +std::string DigX::dig_x(const std::string& domain, int options) { + std::string raw_response = execute_dig(domain); std::string result; if (options & DIG_A_RECORD) result += parse_a_record(raw_response); @@ -19,28 +18,49 @@ std::string dig_x(const std::string& domain, int options) { return result.empty() ? "No matching records found\n" : result; } +// Function to execute the dig command and return the output +std::string DigX::execute_dig(const std::string& domain) { + std::string command = "dig " + domain + " ANY +short 2>&1"; + FILE* pipe = popen(command.c_str(), "r"); + if (!pipe) throw std::runtime_error("Failed to execute dig command"); + + char buffer[256]; + std::string result; + while (fgets(buffer, sizeof(buffer), pipe) != nullptr) { + result += buffer; + } + pclose(pipe); + return result; +} + // Helper function to extract A record (IPv4) -std::string parse_a_record(const std::string& raw_response) { +std::string DigX::parse_a_record(const std::string& raw_response) { std::regex re("\\b([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})\\b"); - std::smatch match; - if (std::regex_search(raw_response, match, re)) { - return "A Record: " + match[1].str() + "\n"; + std::string result; + std::sregex_iterator begin(raw_response.begin(), raw_response.end(), re); + std::sregex_iterator end; + + for (auto it = begin; it != end; ++it) { + result += "A Record: " + it->str() + "\n"; } - return ""; + return result; } // Helper function to extract MX record -std::string parse_mx_record(const std::string& raw_response) { +std::string DigX::parse_mx_record(const std::string& raw_response) { std::regex re("([0-9]+)\\s+IN\\s+MX\\s+([a-zA-Z0-9.-]+)"); - std::smatch match; - if (std::regex_search(raw_response, match, re)) { - return "MX Record: " + match[2].str() + " (Priority: " + match[1].str() + ")\n"; + std::string result; + std::sregex_iterator begin(raw_response.begin(), raw_response.end(), re); + std::sregex_iterator end; + + for (auto it = begin; it != end; ++it) { + result += "MX Record: " + (*it)[2].str() + " (Priority: " + (*it)[1].str() + ")\n"; } - return ""; + return result; } // Helper function to extract CNAME record -std::string parse_cname_record(const std::string& raw_response) { +std::string DigX::parse_cname_record(const std::string& raw_response) { std::regex re("CNAME\\s+([a-zA-Z0-9.-]+)"); std::smatch match; if (std::regex_search(raw_response, match, re)) { @@ -50,17 +70,20 @@ std::string parse_cname_record(const std::string& raw_response) { } // Helper function to extract NS record -std::string parse_ns_record(const std::string& raw_response) { +std::string DigX::parse_ns_record(const std::string& raw_response) { std::regex re("IN\\s+NS\\s+([a-zA-Z0-9.-]+)"); - std::smatch match; - if (std::regex_search(raw_response, match, re)) { - return "NS Record: " + match[1].str() + "\n"; + std::string result; + std::sregex_iterator begin(raw_response.begin(), raw_response.end(), re); + std::sregex_iterator end; + + for (auto it = begin; it != end; ++it) { + result += "NS Record: " + (*it)[1].str() + "\n"; } - return ""; + return result; } // Helper function to extract SOA record -std::string parse_soa_record(const std::string& raw_response) { +std::string DigX::parse_soa_record(const std::string& raw_response) { std::regex re("SOA\\s+([a-zA-Z0-9.-]+)\\s+([a-zA-Z0-9.-]+)"); std::smatch match; if (std::regex_search(raw_response, match, re)) { diff --git a/backend/src/utilities/traceroute_x.cpp b/backend/src/utilities/traceroute_x.cpp index f01a4b2..6105d4d 100644 --- a/backend/src/utilities/traceroute_x.cpp +++ b/backend/src/utilities/traceroute_x.cpp @@ -26,7 +26,7 @@ std::string parse_hop_count(const std::string& response) { return "Total Hops: " + std::to_string(hop_count) + "\n"; } -std::string parse_ips(const std::string& response) { +std::string parse_ips(std::string response) { std::regex re("\\b(\\d+\\.\\d+\\.\\d+\\.\\d+)\\b"); std::smatch match; std::string result = "Traceroute IPs: "; From fe168e1d8115dff323c83712b1878c86128a27d2 Mon Sep 17 00:00:00 2001 From: sitzmaa Date: Fri, 14 Feb 2025 13:27:06 -0800 Subject: [PATCH 5/7] cli converted into c++ --- build.sh | 63 ++++++++++++++++++++++ core/run.py | 2 +- frontend/cli.py | 30 ----------- frontend/netmap_cli/CMakeLists.txt | 22 ++++++++ frontend/netmap_cli/cli.cpp | 69 ++++++++++++++++++++++++ frontend/netmap_cli/cli.hpp | 19 +++++++ frontend/netmap_cli/main.cpp | 85 ++++++++++++++++++++++++++++++ 7 files changed, 259 insertions(+), 31 deletions(-) create mode 100755 build.sh delete mode 100644 frontend/cli.py create mode 100644 frontend/netmap_cli/CMakeLists.txt create mode 100644 frontend/netmap_cli/cli.cpp create mode 100644 frontend/netmap_cli/cli.hpp create mode 100644 frontend/netmap_cli/main.cpp diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..0cd93c5 --- /dev/null +++ b/build.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +# Function to display usage instructions +usage() { + echo "Usage: $0 [-c] [-s]" + echo "Options:" + echo " -c Build the CLI frontend (located at ./frontend/netmap_cli/build)" + echo " -s Build the backend program (located at ./backend/build)" + echo " --help Display this help message" + exit 1 +} + +# Parse command-line arguments +while getopts "cs" opt; do + case ${opt} in + c) + BUILD_CLI=true + ;; + s) + BUILD_BACKEND=true + ;; + *) + usage + ;; + esac +done + +# Build the CLI +if [ "$BUILD_CLI" = true ]; then + echo "Building the CLI frontend..." + cd ./frontend/netmap_cli + mkdir -p build + cd build + make + if [ $? -eq 0 ]; then + echo "CLI frontend built successfully!" + else + echo "Error building the CLI frontend!" + exit 1 + fi + cd ../../.. +fi + +# Build the backend +if [ "$BUILD_BACKEND" = true ]; then + echo "Building the backend program..." + cd ./backend + mkdir -p build + cd build + make + if [ $? -eq 0 ]; then + echo "Backend program built successfully!" + else + echo "Error building the backend program!" + exit 1 + fi + cd ../../.. +fi + +# If neither -c nor -s is provided, show usage +if [ "$BUILD_CLI" != true ] && [ "$BUILD_BACKEND" != true ]; then + usage +fi \ No newline at end of file diff --git a/core/run.py b/core/run.py index 7af5c94..df71d25 100644 --- a/core/run.py +++ b/core/run.py @@ -36,7 +36,7 @@ def main(): time.sleep(0.5) if not args.server_only: if not args.no_cli: - cli_cmd = f"python3 ./frontend/cli.py --port {port}" + cli_cmd = f"./frontend/netmap_cli/build/netmap_cli -H localhost {port}" open_terminal(cli_cmd) if not args.no_gui: diff --git a/frontend/cli.py b/frontend/cli.py deleted file mode 100644 index 140107b..0000000 --- a/frontend/cli.py +++ /dev/null @@ -1,30 +0,0 @@ -import socket -import argparse - -class CLI: - def __init__(self, port): - self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.socket.connect(("localhost", port)) - # Send 'False' to indicate that it's a CLI client - self.socket.sendall(b"0\n") - - def run(self): - while True: - command = input("netmap> ") - if command == "exit": - self.socket.close() - break - self.send_command(command) - - def send_command(self, command): - self.socket.sendall(command.encode() + b"\n") - response = self.socket.recv(1024).decode() - print(f"Server Response: {response}") - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description="CLI client for NetMap") - parser.add_argument("--port", type=int, default=12345, help="Specify the server port (default: 12345)") - args = parser.parse_args() - - cli = CLI(args.port) - cli.run() \ No newline at end of file diff --git a/frontend/netmap_cli/CMakeLists.txt b/frontend/netmap_cli/CMakeLists.txt new file mode 100644 index 0000000..f2102ea --- /dev/null +++ b/frontend/netmap_cli/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.10) +project(NetMapCLI) + +# Set C++ standard +set(CMAKE_CXX_STANDARD 17) + +# Add the source files +set(SOURCES + main.cpp + cli.cpp +) + +# Add the header files directory +include_directories(${CMAKE_SOURCE_DIR}) + +# Create the executable +add_executable(netmap_cli ${SOURCES}) + +# Link with necessary libraries +if(UNIX) + target_link_libraries(netmap_cli pthread) # Link pthread for Unix systems +endif() \ No newline at end of file diff --git a/frontend/netmap_cli/cli.cpp b/frontend/netmap_cli/cli.cpp new file mode 100644 index 0000000..c25b198 --- /dev/null +++ b/frontend/netmap_cli/cli.cpp @@ -0,0 +1,69 @@ +#include "cli.hpp" +#include +#include +#include +#include +#include + +CLI::CLI(const std::string& host, int port) { + // Create socket + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { + perror("Error opening socket"); + exit(EXIT_FAILURE); + } + + // Set up the server address structure + sockaddr_in server_addr; + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(port); + + // Convert IP address to binary form + if (inet_pton(AF_INET, host.c_str(), &server_addr.sin_addr) <= 0) { + perror("Invalid address"); + exit(EXIT_FAILURE); + } + + // Connect to the server + if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { + perror("Connection failed"); + exit(EXIT_FAILURE); + } + + // Send 'False' to indicate this is a CLI client + std::string message = "0\n"; + send(sockfd, message.c_str(), message.length(), 0); +} + +CLI::~CLI() { + close(sockfd); +} + +void CLI::run() { + std::string command; + while (true) { + std::cout << "netmap> "; + std::getline(std::cin, command); + + if (command == "exit") { + break; + } + + send_command(command); + } +} + +void CLI::send_command(const std::string& command) { + // Send the command + send(sockfd, command.c_str(), command.length(), 0); + send(sockfd, "\n", 1, 0); + + // Receive the response + char buffer[1024] = {0}; + int n = recv(sockfd, buffer, sizeof(buffer) - 1, 0); + if (n > 0) { + buffer[n] = '\0'; // Null-terminate the string + std::cout << "Server Response: " << buffer << std::endl; + } +} \ No newline at end of file diff --git a/frontend/netmap_cli/cli.hpp b/frontend/netmap_cli/cli.hpp new file mode 100644 index 0000000..010b3fc --- /dev/null +++ b/frontend/netmap_cli/cli.hpp @@ -0,0 +1,19 @@ +#ifndef CLI_HPP +#define CLI_HPP + +#include + +class CLI { +public: + CLI(const std::string& host, int port); + ~CLI(); + + void run(); + +private: + int sockfd; + + void send_command(const std::string& command); +}; + +#endif // CLI_HPP \ No newline at end of file diff --git a/frontend/netmap_cli/main.cpp b/frontend/netmap_cli/main.cpp new file mode 100644 index 0000000..b913dbd --- /dev/null +++ b/frontend/netmap_cli/main.cpp @@ -0,0 +1,85 @@ +#include "cli.hpp" +#include +#include +#include +#include +#include +#include + +void display_help() { + std::cout << "Usage: netmap_cli [options]\n"; + std::cout << "Options:\n"; + std::cout << " -h Specify the target IP address (default: localhost)\n"; + std::cout << " -H Specify the target domain to resolve to an IP\n"; + std::cout << " -p Specify the port (default: 12345)\n"; + std::cout << " --help Display this help message\n"; +} + +std::string resolve_hostname(const std::string& domain) { + struct addrinfo hints, *res; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; // IPv4 + hints.ai_socktype = SOCK_STREAM; + + int err = getaddrinfo(domain.c_str(), nullptr, &hints, &res); + if (err != 0) { + std::cerr << "Error resolving domain: " << gai_strerror(err) << std::endl; + exit(EXIT_FAILURE); + } + + // Convert the first resolved address to a string + char ip_str[INET_ADDRSTRLEN]; + struct sockaddr_in* sockaddr_in = (struct sockaddr_in*)res->ai_addr; + inet_ntop(AF_INET, &sockaddr_in->sin_addr, ip_str, sizeof(ip_str)); + + freeaddrinfo(res); // Free the resolved info + return std::string(ip_str); +} + +int main(int argc, char* argv[]) { + int port = 12345; + std::string host = "localhost"; // Default IP address + bool resolve_dns = false; + std::string domain; + + // Handle command-line arguments + int opt; + while ((opt = getopt(argc, argv, "h:H:p:")) != -1) { + switch (opt) { + case 'h': + host = optarg; + break; + case 'H': + resolve_dns = true; + domain = optarg; + break; + case 'p': + port = std::stoi(optarg); + break; + case '?': + display_help(); + return EXIT_SUCCESS; + default: + display_help(); + return EXIT_FAILURE; + } + } + + // Check for --help flag + if (argc == 2 && std::string(argv[1]) == "--help") { + display_help(); + return EXIT_SUCCESS; + } + + // If DNS resolution is requested, resolve the domain + if (resolve_dns) { + host = resolve_hostname(domain); + std::cout << "Resolved DNS: " << domain << " to IP: " << host << std::endl; + } + + // Create and run the CLI + CLI cli(host, port); + cli.run(); + + return 0; +} \ No newline at end of file From 40e42d5ed197f4bfc452f4c19882d1696d7d8227 Mon Sep 17 00:00:00 2001 From: sitzmaa Date: Fri, 14 Feb 2025 13:28:16 -0800 Subject: [PATCH 6/7] updated README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a252bf3..8f1dd6e 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,8 @@ cd netmap To launch the graphical user interface (GUI) and start visualizing networks: ``` bash -python3 run.py +./build.sh -cs +python3 -m core.run ``` ## Contributing From c62e92c213345c8a6c30d6ebc325fbcf7a41e2b5 Mon Sep 17 00:00:00 2001 From: sitzmaa Date: Fri, 14 Feb 2025 15:16:59 -0800 Subject: [PATCH 7/7] updated commands --- backend/CMakeLists.txt | 56 ++++--- backend/include/commands.hpp | 12 ++ backend/include/utilities/dig_x.hpp | 25 --- backend/include/utilities/nmap_x.hpp | 28 ---- backend/include/utilities/nping.hpp | 0 backend/src/network_server.cpp | 69 +++++--- backend/src/utilities/nmap_x.cpp | 152 ------------------ backend/src/utilities/nping.cpp | 25 --- backend/utilities/include/dig_x.hpp | 20 +++ backend/utilities/include/nmap_x.hpp | 20 +++ .../include}/ping_x.hpp | 8 +- .../include}/traceroute_x.hpp | 6 +- .../utilities => utilities/src}/dig_x.cpp | 57 ++++--- backend/utilities/src/nmap_x.cpp | 134 +++++++++++++++ .../utilities => utilities/src}/ping_x.cpp | 20 ++- .../src}/traceroute_x.cpp | 17 ++ 16 files changed, 356 insertions(+), 293 deletions(-) create mode 100644 backend/include/commands.hpp delete mode 100644 backend/include/utilities/dig_x.hpp delete mode 100644 backend/include/utilities/nmap_x.hpp delete mode 100644 backend/include/utilities/nping.hpp delete mode 100644 backend/src/utilities/nmap_x.cpp delete mode 100644 backend/src/utilities/nping.cpp create mode 100644 backend/utilities/include/dig_x.hpp create mode 100644 backend/utilities/include/nmap_x.hpp rename backend/{include/utilities => utilities/include}/ping_x.hpp (74%) rename backend/{include/utilities => utilities/include}/traceroute_x.hpp (75%) rename backend/{src/utilities => utilities/src}/dig_x.cpp (70%) create mode 100644 backend/utilities/src/nmap_x.cpp rename backend/{src/utilities => utilities/src}/ping_x.cpp (75%) rename backend/{src/utilities => utilities/src}/traceroute_x.cpp (75%) diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index ccf0434..b6ff115 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -11,41 +11,61 @@ project(netmap_backend) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) -# Add the include directories for libraries -include_directories(${CMAKE_SOURCE_DIR}/include) -include_directories(${CMAKE_SOURCE_DIR}/include/utilities) -include_directories(${CMAKE_SOURCE_DIR}/externals) +# Define include directories +include_directories( + ${CMAKE_SOURCE_DIR}/include + ${CMAKE_SOURCE_DIR}/utilities/include + ${CMAKE_SOURCE_DIR}/externals +) -# Importing Boost +# Import Boost set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost REQUIRED COMPONENTS system) - include_directories(${Boost_INCLUDE_DIRS}) # Import nlohmann-json find_package(nlohmann_json REQUIRED) include_directories(${nlohmann_json_INCLUDE_DIRS}) -# Add the libraries -add_library(traceroute src/utilities/traceroute_x.cpp) -add_library(ping src/utilities/ping_x.cpp) -add_library(dig src/utilities/dig_x.cpp) -add_library(nmap src/utilities/nmap_x.cpp) +# Import tinyxml2 +find_package(tinyxml2 REQUIRED) + +# Find all .cpp files in utilities/src +file(GLOB UTILITIES_SRC_FILES "utilities/src/*.cpp") + +# Define libraries based on the .cpp files +foreach(SOURCE_FILE ${UTILITIES_SRC_FILES}) + get_filename_component(LIBRARY_NAME ${SOURCE_FILE} NAME_WE) + + # Create a library for each source file + add_library(${LIBRARY_NAME} ${SOURCE_FILE}) + + # Ensure it has access to the include directories + target_include_directories(${LIBRARY_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/utilities/include) +endforeach() + +# Add the server library add_library(server src/network_server.cpp) target_link_libraries(server ${Boost_LIBRARIES}) -# Create an executable for the main program that links with the server library -add_executable(netmap_backend src/main.cpp src/network_state.cpp src/node.cpp) +# Create the executable for the main program +add_executable(netmap_backend + src/main.cpp + src/network_state.cpp + src/node.cpp +) -# Link the server library to the executable target_link_libraries(netmap_backend server - traceroute - ping - dig - nmap nlohmann_json::nlohmann_json + tinyxml2::tinyxml2 ) + +# Link all dynamically created libraries +foreach(SOURCE_FILE ${UTILITIES_SRC_FILES}) + get_filename_component(LIBRARY_NAME ${SOURCE_FILE} NAME_WE) + target_link_libraries(netmap_backend ${LIBRARY_NAME}) +endforeach() \ No newline at end of file diff --git a/backend/include/commands.hpp b/backend/include/commands.hpp new file mode 100644 index 0000000..188a6b2 --- /dev/null +++ b/backend/include/commands.hpp @@ -0,0 +1,12 @@ +#ifndef COMMANDS_HPP +#define COMMANDS_HPP + +#include // For std::string +#include // For std::vector +#include "dig_x.hpp" +#include "nmap_x.hpp" +#include "ping_x.hpp" +#include "traceroute_x.hpp" + + +#endif // COMMANDS_HPP \ No newline at end of file diff --git a/backend/include/utilities/dig_x.hpp b/backend/include/utilities/dig_x.hpp deleted file mode 100644 index 6e63065..0000000 --- a/backend/include/utilities/dig_x.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef DIG_X_HPP -#define DIG_X_HPP - -#include - -#define DIG_A_RECORD 0x01 -#define DIG_MX_RECORD 0x02 -#define DIG_CNAME_RECORD 0x04 -#define DIG_NS_RECORD 0x08 -#define DIG_SOA_RECORD 0x10 - -class DigX { -public: - static std::string dig_x(const std::string& domain, int options); - -private: - static std::string execute_dig(const std::string& domain); - static std::string parse_a_record(const std::string& raw_response); - static std::string parse_mx_record(const std::string& raw_response); - static std::string parse_cname_record(const std::string& raw_response); - static std::string parse_ns_record(const std::string& raw_response); - static std::string parse_soa_record(const std::string& raw_response); -}; - -#endif // DIG_X_HPP \ No newline at end of file diff --git a/backend/include/utilities/nmap_x.hpp b/backend/include/utilities/nmap_x.hpp deleted file mode 100644 index d364642..0000000 --- a/backend/include/utilities/nmap_x.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef NMAP_X_HPP -#define NMAP_X_HPP - -#include -#include -#include - -// Define bitwise flags for Nmap options -constexpr uint8_t NMAP_OPEN_PORT = 0x01; -constexpr uint8_t NMAP_PUBLIC_IP = 0x02; -constexpr uint8_t NMAP_MAC_ADDRESS = 0x04; -constexpr uint8_t NMAP_DOMAIN = 0x08; -constexpr uint8_t NMAP_OS = 0x10; - -class NmapX { -public: - // Main function to execute the scan and parse the result - static std::vector scan(const std::string& target, uint8_t options); - -private: - // Helper function to run the nmap scan and return the XML output - static std::string run_nmap(const std::string& target, uint8_t options); - - // Function to parse the nmap XML result and extract requested data - static std::vector parse_nmap_xml(const std::string& xml_data, uint8_t options); -}; - -#endif // NMAP_X_HPP diff --git a/backend/include/utilities/nping.hpp b/backend/include/utilities/nping.hpp deleted file mode 100644 index e69de29..0000000 diff --git a/backend/src/network_server.cpp b/backend/src/network_server.cpp index 48f8542..0f280a1 100644 --- a/backend/src/network_server.cpp +++ b/backend/src/network_server.cpp @@ -1,7 +1,21 @@ #include "network_server.hpp" +#include "commands.hpp" // Universal import for all command header files #include +#include +#include #include +// Function to parse command input into a vector of arguments +std::vector parse_command(const std::string& input) { + std::vector tokens; + std::istringstream iss(input); + std::string token; + while (iss >> token) { + tokens.push_back(token); + } + return tokens; +} + NetworkServer::NetworkServer(short port) : io_context(), acceptor(io_context, tcp::endpoint(tcp::v4(), port)) {} @@ -16,12 +30,9 @@ void NetworkServer::start() { void NetworkServer::handle_client(tcp::socket socket) { try { - - // Read initial message to determine client type asio::streambuf buffer; asio::read_until(socket, buffer, "\n"); std::istream input(&buffer); - std::string client_type; std::getline(input, client_type); @@ -52,18 +63,36 @@ void NetworkServer::handle_cli(tcp::socket socket) { std::string command; std::getline(input, command); - if (command == "ping") { - send_response(socket, "Pinging the network..."); - } - else if (command == "traceroute") { - send_response(socket, "Running traceroute..."); - } - else if (command == "exit") { + if (command == "exit") { break; + } + + std::vector args = parse_command(command); + if (args.empty()) { + send_response(socket, "Invalid command"); + continue; + } + + std::string response; + std::string cmd = args[0]; + + if (cmd == "ping") { + response = Ping::run(args); + } + else if (cmd == "traceroute") { + response = Traceroute::run(args); } + else if (cmd == "nmap") { + response = Nmap::run(args); + } + else if (cmd == "dig") { + response = Dig::run(args); + } else { - send_response(socket, "Unknown CLI command"); + response = "Unknown CLI command"; } + + send_response(socket, response); } } catch (const std::exception& e) { std::cerr << "CLI client error: " << e.what() << std::endl; @@ -77,22 +106,14 @@ void NetworkServer::handle_gui(tcp::socket socket) { asio::read_until(socket, buffer, "\n"); std::istream input(&buffer); - std::string request; - std::getline(input, request); + std::string gui_data; + std::getline(input, gui_data); - // GUI messages might be JSON or structured differently - if (request == "get_network_state") { - send_response(socket, "{ \"status\": \"ok\", \"message\": \"Network state fetched\" }"); - } - else if (request == "highlight_node") { - send_response(socket, "{ \"status\": \"ok\", \"message\": \"Node highlighted\" }"); - } - else if (request == "exit") { + if (gui_data == "exit") { break; - } - else { - send_response(socket, "{ \"status\": \"error\", \"message\": \"Unknown GUI request\" }"); } + + std::cout << "Received GUI data: " << gui_data << std::endl; } } catch (const std::exception& e) { std::cerr << "GUI client error: " << e.what() << std::endl; diff --git a/backend/src/utilities/nmap_x.cpp b/backend/src/utilities/nmap_x.cpp deleted file mode 100644 index 96cbf2a..0000000 --- a/backend/src/utilities/nmap_x.cpp +++ /dev/null @@ -1,152 +0,0 @@ -#include "nmap_x.hpp" -#include -#include -#include -#include -#include -#include -#include - -using namespace tinyxml2; - -// Helper function to run the nmap scan and return the XML output -std::string run_nmap(const std::string& target, int options) { - std::ostringstream cmd_stream; - cmd_stream << "nmap -oX - "; // Use standard output in XML format - - // Add options to the command based on bitwise flags - if (options & NMAP_OPEN_PORT) { - cmd_stream << "-p- "; // Scan all ports - } - if (options & NMAP_PUBLIC_IP) { - cmd_stream << "--unprivileged "; // Optional: run nmap without root privileges - } - if (options & NMAP_MAC_ADDRESS) { - cmd_stream << "--osscan-guess "; // Guess OS based on MAC address - } - if (options & NMAP_DOMAIN) { - cmd_stream << "--dns-servers "; // Optionally specify DNS server - } - if (options & NMAP_OS) { - cmd_stream << "-O "; // Enable OS detection - } - - cmd_stream << target; - - std::string cmd = cmd_stream.str(); - std::array buffer; - std::string result; - std::shared_ptr pipe(popen(cmd.c_str(), "r"), fclose); - - if (!pipe) { - throw std::runtime_error("Failed to run nmap command"); - } - - while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { - result += buffer.data(); - } - - return result; -} - -// Function to parse the nmap XML result and extract requested data -std::vector parse_nmap_xml(const std::string& xml_data, int options) { - XMLDocument doc; - std::vector results; - - // Parse the XML data - if (doc.Parse(xml_data.c_str()) != XML_SUCCESS) { - throw std::runtime_error("Failed to parse XML data from nmap"); - } - - XMLElement* root = doc.RootElement(); - if (root == nullptr) { - throw std::runtime_error("Failed to find root element in nmap XML"); - } - - // Extract the requested information based on bitwise flags - if (options & NMAP_OPEN_PORT) { - XMLElement* host = root->FirstChildElement("host"); - while (host) { - XMLElement* ports = host->FirstChildElement("ports"); - if (ports) { - for (XMLElement* port = ports->FirstChildElement("port"); port; port = port->NextSiblingElement("port")) { - const char* port_str = port->Attribute("portid"); - if (port_str) { - results.push_back("Open Port: " + std::string(port_str)); - } - } - } - host = host->NextSiblingElement("host"); - } - } - if (options & NMAP_PUBLIC_IP) { - XMLElement* host = root->FirstChildElement("host"); - while (host) { - XMLElement* address = host->FirstChildElement("address"); - if (address) { - const char* ip = address->Attribute("addr"); - if (ip) { - results.push_back("Public IP: " + std::string(ip)); - } - } - host = host->NextSiblingElement("host"); - } - } - if (options & NMAP_MAC_ADDRESS) { - XMLElement* host = root->FirstChildElement("host"); - while (host) { - XMLElement* hostnames = host->FirstChildElement("hostnames"); - if (hostnames) { - for (XMLElement* hostname = hostnames->FirstChildElement("hostname"); hostname; hostname = hostname->NextSiblingElement("hostname")) { - const char* mac = hostname->Attribute("mac"); - if (mac) { - results.push_back("MAC Address: " + std::string(mac)); - } - } - } - host = host->NextSiblingElement("host"); - } - } - if (options & NMAP_DOMAIN) { - XMLElement* host = root->FirstChildElement("host"); - while (host) { - XMLElement* hostnames = host->FirstChildElement("hostnames"); - if (hostnames) { - for (XMLElement* hostname = hostnames->FirstChildElement("hostname"); hostname; hostname = hostname->NextSiblingElement("hostname")) { - const char* domain = hostname->Attribute("name"); - if (domain) { - results.push_back("Domain: " + std::string(domain)); - } - } - } - host = host->NextSiblingElement("host"); - } - } - if (options & NMAP_OS) { - XMLElement* host = root->FirstChildElement("host"); - while (host) { - XMLElement* os = host->FirstChildElement("os-fingerprint"); - if (os) { - const char* os_name = os->Attribute("os"); - if (os_name) { - results.push_back("OS: " + std::string(os_name)); - } - } - host = host->NextSiblingElement("host"); - } - } - - return results; -} - -// Main function to execute the scan and parse the result -std::vector nmap_x(const std::string& target, int options) { - try { - std::string scan_result = run_nmap(target, options); - return parse_nmap_xml(scan_result, options); - } catch (const std::exception& e) { - std::cerr << "Error: " << e.what() << std::endl; - return {}; // Return empty list on error - } -} diff --git a/backend/src/utilities/nping.cpp b/backend/src/utilities/nping.cpp deleted file mode 100644 index 9e1a81f..0000000 --- a/backend/src/utilities/nping.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "nping.hpp" -#include "nmap.hpp" -#include - -void advancedPing(const std::string& target) { - std::cout << "Performing advanced ping on " << target << std::endl; - - // First, ping the target - if (pingHost(target)) { - std::cout << target << " is alive!" << std::endl; - } else { - std::cout << target << " is not reachable!" << std::endl; - } - - // Then, check open ports - auto openPorts = getOpenPorts(target); - if (!openPorts.empty()) { - std::cout << "Open ports on " << target << ":" << std::endl; - for (const auto& port : openPorts) { - std::cout << "Port " << port.first << ": " << port.second << std::endl; - } - } else { - std::cout << "No open ports found on " << target << std::endl; - } -} \ No newline at end of file diff --git a/backend/utilities/include/dig_x.hpp b/backend/utilities/include/dig_x.hpp new file mode 100644 index 0000000..6b7fb54 --- /dev/null +++ b/backend/utilities/include/dig_x.hpp @@ -0,0 +1,20 @@ +#ifndef DIG_X_HPP +#define DIG_X_HPP + +#include "commands.hpp" +#include +#include + +// Define bitwise flags for Dig options +#define DIG_A_RECORD (1 << 0) // Extract A record +#define DIG_MX_RECORD (1 << 1) // Extract MX record +#define DIG_CNAME_RECORD (1 << 2) // Extract CNAME record +#define DIG_NS_RECORD (1 << 3) // Extract NS record +#define DIG_SOA_RECORD (1 << 4) // Extract SOA record + +class Dig{ +public: + static std::string run(const std::vector& args); +}; + +#endif // DIG_X_HPP \ No newline at end of file diff --git a/backend/utilities/include/nmap_x.hpp b/backend/utilities/include/nmap_x.hpp new file mode 100644 index 0000000..aaa5211 --- /dev/null +++ b/backend/utilities/include/nmap_x.hpp @@ -0,0 +1,20 @@ +#ifndef NMAP_X_HPP +#define NMAP_X_HPP + +#include "commands.hpp" +#include +#include + +// Define bitwise flags for Nmap options +#define NMAP_OPEN_PORT (1 << 0) // Extract open ports +#define NMAP_PUBLIC_IP (1 << 1) // Extract public IP +#define NMAP_MAC_ADDRESS (1 << 2) // Extract MAC address +#define NMAP_DOMAIN (1 << 3) // Extract domain name +#define NMAP_OS (1 << 4) // Extract OS information + +class Nmap{ +public: + static std::string run(const std::vector& args); +}; + +#endif // NMAP_X_HPP \ No newline at end of file diff --git a/backend/include/utilities/ping_x.hpp b/backend/utilities/include/ping_x.hpp similarity index 74% rename from backend/include/utilities/ping_x.hpp rename to backend/utilities/include/ping_x.hpp index e5a5083..0407b06 100644 --- a/backend/include/utilities/ping_x.hpp +++ b/backend/utilities/include/ping_x.hpp @@ -1,6 +1,8 @@ #ifndef PING_X_HPP #define PING_X_HPP +#include "commands.hpp" +#include #include // Define bitwise flags for Ping options @@ -9,6 +11,10 @@ #define PING_TTL (1 << 2) // Extract TTL (Time to Live) #define PING_IP (1 << 3) // Extract target IP address -std::string ping_x(const std::string& ip, int options); +class Ping{ +public: + static std::string run(const std::vector& args); +}; + #endif // PING_X_HPP \ No newline at end of file diff --git a/backend/include/utilities/traceroute_x.hpp b/backend/utilities/include/traceroute_x.hpp similarity index 75% rename from backend/include/utilities/traceroute_x.hpp rename to backend/utilities/include/traceroute_x.hpp index d05dbf6..7e20c2e 100644 --- a/backend/include/utilities/traceroute_x.hpp +++ b/backend/utilities/include/traceroute_x.hpp @@ -1,6 +1,7 @@ #ifndef TRACEROUTE_X_HPP #define TRACEROUTE_X_HPP +#include #include // Define bitwise flags for Traceroute options @@ -8,6 +9,9 @@ #define TRACE_LATENCY (1 << 1) // Extract per-hop latency #define TRACE_IPS (1 << 2) // Extract IP addresses in the route -std::string traceroute_x(const std::string& target, int options); +class Traceroute{ +public: + static std::string run(const std::vector& args); +}; #endif // TRACEROUTE_X_HPP \ No newline at end of file diff --git a/backend/src/utilities/dig_x.cpp b/backend/utilities/src/dig_x.cpp similarity index 70% rename from backend/src/utilities/dig_x.cpp rename to backend/utilities/src/dig_x.cpp index 65ac981..3df6a24 100644 --- a/backend/src/utilities/dig_x.cpp +++ b/backend/utilities/src/dig_x.cpp @@ -5,21 +5,9 @@ #include #include -std::string DigX::dig_x(const std::string& domain, int options) { - std::string raw_response = execute_dig(domain); - - std::string result; - if (options & DIG_A_RECORD) result += parse_a_record(raw_response); - if (options & DIG_MX_RECORD) result += parse_mx_record(raw_response); - if (options & DIG_CNAME_RECORD) result += parse_cname_record(raw_response); - if (options & DIG_NS_RECORD) result += parse_ns_record(raw_response); - if (options & DIG_SOA_RECORD) result += parse_soa_record(raw_response); - - return result.empty() ? "No matching records found\n" : result; -} // Function to execute the dig command and return the output -std::string DigX::execute_dig(const std::string& domain) { +std::string execute_dig(const std::string& domain) { std::string command = "dig " + domain + " ANY +short 2>&1"; FILE* pipe = popen(command.c_str(), "r"); if (!pipe) throw std::runtime_error("Failed to execute dig command"); @@ -34,7 +22,7 @@ std::string DigX::execute_dig(const std::string& domain) { } // Helper function to extract A record (IPv4) -std::string DigX::parse_a_record(const std::string& raw_response) { +std::string parse_a_record(const std::string& raw_response) { std::regex re("\\b([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})\\b"); std::string result; std::sregex_iterator begin(raw_response.begin(), raw_response.end(), re); @@ -47,7 +35,7 @@ std::string DigX::parse_a_record(const std::string& raw_response) { } // Helper function to extract MX record -std::string DigX::parse_mx_record(const std::string& raw_response) { +std::string parse_mx_record(const std::string& raw_response) { std::regex re("([0-9]+)\\s+IN\\s+MX\\s+([a-zA-Z0-9.-]+)"); std::string result; std::sregex_iterator begin(raw_response.begin(), raw_response.end(), re); @@ -60,7 +48,7 @@ std::string DigX::parse_mx_record(const std::string& raw_response) { } // Helper function to extract CNAME record -std::string DigX::parse_cname_record(const std::string& raw_response) { +std::string parse_cname_record(const std::string& raw_response) { std::regex re("CNAME\\s+([a-zA-Z0-9.-]+)"); std::smatch match; if (std::regex_search(raw_response, match, re)) { @@ -70,7 +58,7 @@ std::string DigX::parse_cname_record(const std::string& raw_response) { } // Helper function to extract NS record -std::string DigX::parse_ns_record(const std::string& raw_response) { +std::string parse_ns_record(const std::string& raw_response) { std::regex re("IN\\s+NS\\s+([a-zA-Z0-9.-]+)"); std::string result; std::sregex_iterator begin(raw_response.begin(), raw_response.end(), re); @@ -83,11 +71,44 @@ std::string DigX::parse_ns_record(const std::string& raw_response) { } // Helper function to extract SOA record -std::string DigX::parse_soa_record(const std::string& raw_response) { +std::string parse_soa_record(const std::string& raw_response) { std::regex re("SOA\\s+([a-zA-Z0-9.-]+)\\s+([a-zA-Z0-9.-]+)"); std::smatch match; if (std::regex_search(raw_response, match, re)) { return "SOA Record: " + match[1].str() + " " + match[2].str() + "\n"; } return ""; +} + +std::string dig_x(const std::string& domain, int options) { + std::string raw_response = execute_dig(domain); + + std::string result; + if (options & DIG_A_RECORD) result += parse_a_record(raw_response); + if (options & DIG_MX_RECORD) result += parse_mx_record(raw_response); + if (options & DIG_CNAME_RECORD) result += parse_cname_record(raw_response); + if (options & DIG_NS_RECORD) result += parse_ns_record(raw_response); + if (options & DIG_SOA_RECORD) result += parse_soa_record(raw_response); + + return result.empty() ? "No matching records found\n" : result; +} + + +std::string Dig::run(const std::vector& args) { + if (args.size() < 2) { + return "Usage: dig_x [options]\nOptions: --a-record --mx-record --cname --ns-record --soa-record\n"; + } + + std::string target = args[1]; + int options = 0; + + for (size_t i = 2; i < args.size(); ++i) { + if (args[i] == "--a-record") options |= DIG_A_RECORD; + else if (args[i] == "--mx-record") options |= DIG_MX_RECORD; + else if (args[i] == "--cname") options |= DIG_CNAME_RECORD; + else if (args[i] == "--ns-record") options |= DIG_NS_RECORD; + else if (args[i] == "--soa-record") options |= DIG_SOA_RECORD; + } + + return dig_x(target, options); } \ No newline at end of file diff --git a/backend/utilities/src/nmap_x.cpp b/backend/utilities/src/nmap_x.cpp new file mode 100644 index 0000000..edeff01 --- /dev/null +++ b/backend/utilities/src/nmap_x.cpp @@ -0,0 +1,134 @@ +#include "nmap_x.hpp" +#include +#include +#include +#include +#include +#include + +using namespace tinyxml2; + +std::string run_nmap(const std::string& target, uint8_t options) { + std::ostringstream cmd_stream; + cmd_stream << "nmap -oX - "; + + if (options & NMAP_OPEN_PORT) cmd_stream << "-p- "; + if (options & NMAP_PUBLIC_IP) cmd_stream << "--unprivileged "; + if (options & NMAP_MAC_ADDRESS) cmd_stream << "--osscan-guess "; + if (options & NMAP_DOMAIN) cmd_stream << "--dns-servers "; + if (options & NMAP_OS) cmd_stream << "-O "; + + cmd_stream << target; + std::string cmd = cmd_stream.str(); + + FILE* pipe = popen(cmd.c_str(), "r"); + if (!pipe) throw std::runtime_error("Failed to run nmap command"); + + char buffer[128]; + std::string result; + while (fgets(buffer, sizeof(buffer), pipe) != nullptr) { + result += buffer; + } + pclose(pipe); + return result; +} + +std::vector parse_nmap_xml(const std::string& xml_data, uint8_t options) { + XMLDocument doc; + std::vector results; + if (doc.Parse(xml_data.c_str()) != XML_SUCCESS) { + throw std::runtime_error("Failed to parse XML data from nmap"); + } + + XMLElement* root = doc.RootElement(); + if (!root) { + throw std::runtime_error("Failed to find root element in nmap XML"); + } + + XMLElement* host = root->FirstChildElement("host"); + while (host) { + if (options & NMAP_OPEN_PORT) { + XMLElement* ports = host->FirstChildElement("ports"); + if (ports) { + for (XMLElement* port = ports->FirstChildElement("port"); port; port = port->NextSiblingElement("port")) { + const char* port_str = port->Attribute("portid"); + if (port_str) results.push_back("Open Port: " + std::string(port_str)); + } + } + } + if (options & NMAP_PUBLIC_IP) { + XMLElement* address = host->FirstChildElement("address"); + if (address) { + const char* ip = address->Attribute("addr"); + if (ip) results.push_back("Public IP: " + std::string(ip)); + } + } + if (options & NMAP_MAC_ADDRESS) { + XMLElement* mac = host->FirstChildElement("address"); + if (mac && mac->Attribute("addrtype", "mac")) { + results.push_back("MAC Address: " + std::string(mac->Attribute("addr"))); + } + } + if (options & NMAP_DOMAIN) { + XMLElement* hostnames = host->FirstChildElement("hostnames"); + if (hostnames) { + for (XMLElement* hostname = hostnames->FirstChildElement("hostname"); hostname; hostname = hostname->NextSiblingElement("hostname")) { + const char* domain = hostname->Attribute("name"); + if (domain) results.push_back("Domain: " + std::string(domain)); + } + } + } + if (options & NMAP_OS) { + XMLElement* os = host->FirstChildElement("os"); + if (os) { + XMLElement* osmatch = os->FirstChildElement("osmatch"); + if (osmatch) { + const char* os_name = osmatch->Attribute("name"); + if (os_name) results.push_back("OS: " + std::string(os_name)); + } + } + } + host = host->NextSiblingElement("host"); + } + return results; +} + +std::vector nmap_x(const std::string& target, uint8_t options) { + try { + std::string scan_result = run_nmap(target, options); + return parse_nmap_xml(scan_result, options); + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return {}; + } +} + +std::string Nmap::run(const std::vector& args) { + if (args.size() < 2) { + return "Usage: nmap_x [options]"; + } + + std::string target = args[1]; + uint8_t options = 0; + + std::unordered_map option_map = { + {"--open-ports", NMAP_OPEN_PORT}, + {"--public-ip", NMAP_PUBLIC_IP}, + {"--mac-address", NMAP_MAC_ADDRESS}, + {"--domain", NMAP_DOMAIN}, + {"--os", NMAP_OS} + }; + + for (size_t i = 2; i < args.size(); ++i) { + auto it = option_map.find(args[i]); + if (it != option_map.end()) { + options |= it->second; + } + } + + std::vector results = nmap_x(target, options); + for (const std::string& res : results) { + std::cout << res << std::endl; + } + return 0; +} diff --git a/backend/src/utilities/ping_x.cpp b/backend/utilities/src/ping_x.cpp similarity index 75% rename from backend/src/utilities/ping_x.cpp rename to backend/utilities/src/ping_x.cpp index 0ec8b78..99ff3f6 100644 --- a/backend/src/utilities/ping_x.cpp +++ b/backend/utilities/src/ping_x.cpp @@ -55,4 +55,22 @@ std::string ping_x(const std::string& ip, int options) { if (options & PING_IP) result += "Target IP: " + ip + "\n"; return result.empty() ? "No matching ping results\n" : result; -} \ No newline at end of file +} + +std::string Ping::run(const std::vector& args) { + if (args.size() < 2) { + return "Usage: ping_x [options]\nOptions: --latency --loss --ttl --ip\n"; + } + + std::string ip = args[1]; + int options = 0; + + for (size_t i = 2; i < args.size(); ++i) { + if (args[i] == "--latency") options |= PING_LATENCY; + else if (args[i] == "--loss") options |= PING_PACKET_LOSS; + else if (args[i] == "--ttl") options |= PING_TTL; + else if (args[i] == "--ip") options |= PING_IP; + } + + return ping_x(ip, options); +} diff --git a/backend/src/utilities/traceroute_x.cpp b/backend/utilities/src/traceroute_x.cpp similarity index 75% rename from backend/src/utilities/traceroute_x.cpp rename to backend/utilities/src/traceroute_x.cpp index 6105d4d..bf56e4c 100644 --- a/backend/src/utilities/traceroute_x.cpp +++ b/backend/utilities/src/traceroute_x.cpp @@ -48,4 +48,21 @@ std::string traceroute_x(const std::string& target, int options) { if (options & TRACE_IPS) result += parse_ips(response); return result.empty() ? "No matching traceroute results\n" : result; +} + +std::string Traceroute::run(const std::vector& args) { + if (args.size() < 2) { + return "Usage: traceroute_x [options]\nOptions: --hops --latency --ips\n"; + } + + std::string target = args[1]; + int options = 0; + + for (size_t i = 2; i < args.size(); ++i) { + if (args[i] == "--hops") options |= TRACE_HOPS; + else if (args[i] == "--latency") options |= TRACE_LATENCY; + else if (args[i] == "--ips") options |= TRACE_IPS; + } + + return traceroute_x(target, options); } \ No newline at end of file