Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -66,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
Expand All @@ -93,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
Expand Down
55 changes: 38 additions & 17 deletions backend/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,40 +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}/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.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)
# 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
dns_lookup
network_scan
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()
12 changes: 12 additions & 0 deletions backend/include/commands.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef COMMANDS_HPP
#define COMMANDS_HPP

#include <string> // For std::string
#include <vector> // For std::vector
#include "dig_x.hpp"
#include "nmap_x.hpp"
#include "ping_x.hpp"
#include "traceroute_x.hpp"


#endif // COMMANDS_HPP
5 changes: 0 additions & 5 deletions backend/include/dns_lookup.hpp

This file was deleted.

5 changes: 0 additions & 5 deletions backend/include/network_scan.hpp

This file was deleted.

5 changes: 0 additions & 5 deletions backend/include/ping.hpp

This file was deleted.

28 changes: 28 additions & 0 deletions backend/include/plugin.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef PLUGIN_HPP
#define PLUGIN_HPP

#include <string>

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
5 changes: 0 additions & 5 deletions backend/include/traceroute.hpp

This file was deleted.

63 changes: 62 additions & 1 deletion backend/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,63 @@
#include "network_server.hpp"
#include "plugin.hpp"
#include <iostream>
#include <cstdlib> // For std::stoi
#include <cstdlib>
#include <dlfcn.h> // For dynamic loading on Linux/macOS
#include <dirent.h> // For reading directories
#include <vector>
#include <string>

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) {
Expand All @@ -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;
Expand Down
70 changes: 45 additions & 25 deletions backend/src/network_server.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
#include "network_server.hpp"
#include "commands.hpp" // Universal import for all command header files
#include <iostream>
#include <sstream>
#include <vector>
#include <asio.hpp>

// Function to parse command input into a vector of arguments
std::vector<std::string> parse_command(const std::string& input) {
std::vector<std::string> 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)) {}

Expand All @@ -16,13 +30,9 @@ 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;
asio::read_until(socket, buffer, "\n");
std::istream input(&buffer);

std::string client_type;
std::getline(input, client_type);

Expand Down Expand Up @@ -53,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<std::string> 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;
Expand All @@ -78,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;
Expand Down
11 changes: 0 additions & 11 deletions backend/src/utilities/dns_lookup.cpp

This file was deleted.

6 changes: 0 additions & 6 deletions backend/src/utilities/network_scan.cpp

This file was deleted.

Loading