From f2f94b70d4fc5099ae72494f30975dda69f29bcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexe=C3=AF=20KADIR?= Date: Fri, 23 Feb 2024 03:14:05 +0100 Subject: [PATCH] Added some signatures for XML generation and domain management --- src/domain.c | 8 -- src/domain.h | 22 +++++ src/pci.c | 42 ++++----- src/pci.h | 16 ++-- src/sandbox.c | 1 + src/sandbox.h | 2 +- src/xml.c | 246 -------------------------------------------------- src/xml.h | 57 +++++------- xml | 65 ------------- 9 files changed, 75 insertions(+), 384 deletions(-) delete mode 100644 src/domain.c delete mode 100644 src/xml.c delete mode 100644 xml diff --git a/src/domain.c b/src/domain.c deleted file mode 100644 index 253e4bf..0000000 --- a/src/domain.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "domain.h" - -#include "sandbox.h" -#include "container.h" -#include "pci.h" -#include "xml.h" - -#include diff --git a/src/domain.h b/src/domain.h index 5b8741a..a87892f 100644 --- a/src/domain.h +++ b/src/domain.h @@ -1,3 +1,25 @@ #pragma once #include "utils.h" + +/// @brief Converts a container identifier to a domain identifier. +/// @param _domain The string pointer to store the resulting domain identifier in. The caller is responsible for freeing the string. +/// @param container The container identifier to convert. +/// @return The result of the operation. +result_t container_to_domain_identifier(char** _domain, const char* container); + +/// @brief Converts a domain identifier to a container identifier. +/// @param _container The string pointer to store the resulting container identifier in. The caller is responsible for freeing the string. +/// @param domain The domain identifier to convert. +/// @return The result of the operation. +result_t domain_to_container_identifier(char** _container, const char* domain); + +/// @brief Checks whether the given string is a valid domain identifier. If the string is not a valid domain identifier, the call will return a failure result with an error message. +/// @param domain The string to check. +/// @return The result of the operation. +result_t check_domain_identifier(const char* domain); + +/// @brief Checks whether the given domain exists. If the domain does not exist, the call will return a failure result with an error message. +/// @param domain The domain to check. +/// @return The result of the operation. +result_t check_domain_exists(const char* domain); diff --git a/src/pci.c b/src/pci.c index 13d2855..f6c77d6 100644 --- a/src/pci.c +++ b/src/pci.c @@ -8,36 +8,36 @@ #include #include -result_t check_pci_address(const char* pci) { +result_t check_pci_address(const char* pci_address) { // Check the length of the string (should be 12 characters, eg. 0000:00:00.0) - if (strlen(pci) != 12) - return failure("Invalid PCI address '%s'. Valid PCI addresses are in the format '0000:00:00.0'.", pci); + if (strlen(pci_address) != 12) + return failure("Invalid PCI address '%s'. Valid PCI addresses are in the format '0000:00:00.0'.", pci_address); // Check the format of the string for (int i = 0; i < 12; i++) if (i == 4 || i == 7) { - if (pci[i] != ':') - return failure("Invalid PCI address '%s'. Missing colon at position %d. Valid PCI addresses are in the format '0000:00:00.0'.", pci, i); + if (pci_address[i] != ':') + return failure("Invalid PCI address '%s'. Missing colon at position %d. Valid PCI addresses are in the format '0000:00:00.0'.", pci_address, i); } else if (i == 10) { - if (pci[i] != '.') - return failure("Invalid PCI address '%s'. Missing dot at position %d. Valid PCI addresses are in the format '0000:00:00.0'.", pci, i); + if (pci_address[i] != '.') + return failure("Invalid PCI address '%s'. Missing dot at position %d. Valid PCI addresses are in the format '0000:00:00.0'.", pci_address, i); } else { - if (!isxdigit(pci[i])) - return failure("Invalid PCI address '%s'. Non-hexadecimal character '%c' at position %d. Valid PCI addresses are in the format '0000:00:00.0'.", pci, pci[i], i); + if (!isxdigit(pci_address[i])) + return failure("Invalid PCI address '%s'. Non-hexadecimal character '%c' at position %d. Valid PCI addresses are in the format '0000:00:00.0'.", pci_address, pci_address[i], i); } return success(); } -result_t check_pci_exists(const char* pci) { +result_t check_pci_exists(const char* pci_address) { // Check the PCI address format - result_t result = check_pci_address(pci); + result_t result = check_pci_address(pci_address); if (result != success()) return result; // Check if the PCI address exists by checking if the sysfs directory exists char* path; - result = format(&path, "/sys/bus/pci/devices/%s", pci); + result = format(&path, "/sys/bus/pci/devices/%s", pci_address); if (result != success()) return result; @@ -45,7 +45,7 @@ result_t check_pci_exists(const char* pci) { struct stat st; if (stat(path, &st) != 0 || !S_ISDIR(st.st_mode)) { free(path); - return failure("PCI address '%s' does not exist.", pci); + return failure("PCI address '%s' does not exist.", pci_address); } // Free the path @@ -54,18 +54,18 @@ result_t check_pci_exists(const char* pci) { return success(); } -result_t get_iommu_group(int* _group, const char* pci) { +result_t get_iommu_group(int* _group, const char* pci_address) { // Initialize the output parameter *_group = -1; // Check that the PCI address exists - result_t result = check_pci_exists(pci); + result_t result = check_pci_exists(pci_address); if (result != success()) return result; // Get the IOMMU group if the PCI device has one char* path; - result = format(&path, "/sys/bus/pci/devices/%s/iommu_group", pci); + result = format(&path, "/sys/bus/pci/devices/%s/iommu_group", pci_address); if (result != success()) return result; @@ -73,7 +73,7 @@ result_t get_iommu_group(int* _group, const char* pci) { struct stat st; if (lstat(path, &st) != 0 || !S_ISLNK(st.st_mode)) { free(path); - return failure("PCI address '%s' does not have an IOMMU group. Please ensure that the IOMMU is enabled in the kernel.", pci); + return failure("PCI address '%s' does not have an IOMMU group. Please ensure that the IOMMU is enabled in the kernel.", pci_address); } // Read the IOMMU group by getting the path of the symlink, and getting the basename of the path @@ -84,7 +84,7 @@ result_t get_iommu_group(int* _group, const char* pci) { // Check for errors during the readlink call if (len == -1) - return failure("Failed to read IOMMU group of PCI address '%s'.", pci); + return failure("Failed to read IOMMU group of PCI address '%s'.", pci_address); // Null-terminate the path iommu_group_path[len] = '\0'; @@ -95,14 +95,14 @@ result_t get_iommu_group(int* _group, const char* pci) { return success(); } -result_t get_iommu_groups(int** _groups, int* _count, const char** pcis) { +result_t get_iommu_groups(int** _groups, int* _count, const char** pci_addresses) { // Initialize the output parameters *_groups = NULL; *_count = 0; // Count the number of PCI devices int count = 0; - while (pcis[count] != NULL) + while (pci_addresses[count] != NULL) count++; // Allocate memory for the groups @@ -113,7 +113,7 @@ result_t get_iommu_groups(int** _groups, int* _count, const char** pcis) { // Get the IOMMU groups of the PCI devices for (int i = 0; i < count; i++) { // Get the IOMMU group of the PCI device - result_t result = get_iommu_group(&groups[i], pcis[i]); + result_t result = get_iommu_group(&groups[i], pci_addresses[i]); if (result != success()) { free(groups); return result; diff --git a/src/pci.h b/src/pci.h index 397ab7a..40db76f 100644 --- a/src/pci.h +++ b/src/pci.h @@ -3,27 +3,27 @@ #include "utils.h" /// @brief Checks whether the given string is a valid PCI address. If the string is not a valid PCI address, the call will return a failure result with an error message. -/// @param pci The string to check. +/// @param pci_address The string to check. /// @return The result of the operation. -result_t check_pci_address(const char* pci); +result_t check_pci_address(const char* pci_address); /// @brief Checks whether the given PCI address exists. If the PCI address does not exist, the call will return a failure result with an error message. -/// @param pci The PCI address to check. +/// @param pci_address The PCI address to check. /// @return The result of the operation. -result_t check_pci_exists(const char* pci); +result_t check_pci_exists(const char* pci_address); /// @brief Gets the IOMMU group of the given PCI address. /// @param _group The integer pointer to store the resulting IOMMU group in. -/// @param pci The PCI address to get the IOMMU group of. +/// @param pci_address The PCI address to get the IOMMU group of. /// @return The result of the operation. -result_t get_iommu_group(int* _group, const char* pci); +result_t get_iommu_group(int* _group, const char* pci_address); /// @brief Gets the IOMMU groups of the given PCI addresses. /// @param _groups The integer array pointer to store the resulting IOMMU groups in. The caller is responsible for freeing the array. /// @param _count The integer pointer to store the number of IOMMU groups in. -/// @param pcis The PCI addresses to get the IOMMU groups of. +/// @param pci_addresses The PCI addresses to get the IOMMU groups of. /// @return The result of the operation. -result_t get_iommu_groups(int** _groups, int* _count, const char** pcis); +result_t get_iommu_groups(int** _groups, int* _count, const char** pci_addresses); /// @brief Checks that the given file is a PCI device. This function is used as a filter for listing PCI devices. /// @param file The file to check. diff --git a/src/sandbox.c b/src/sandbox.c index a644c3c..e367e72 100755 --- a/src/sandbox.c +++ b/src/sandbox.c @@ -68,6 +68,7 @@ int main(int argc, char** argv) { } // TODO: Parse commands from the command line + return EXIT_SUCCESS; } int command_help(int argc, char* argv[]) { diff --git a/src/sandbox.h b/src/sandbox.h index 72a97b0..227913b 100755 --- a/src/sandbox.h +++ b/src/sandbox.h @@ -5,7 +5,7 @@ #define SANDBOX_VERSION "0.1.4" #define SANDBOX_USER "sandbox" -#define LIBVIRT_DOMAIN "sandbox" +#define DOMAIN_IDENTIFIER_PREFIX "sandbox-" #define LIBVIRT_DRIVER "qemu:///system" #define CONFIG_FILE "/etc/sandbox.d/sandbox.conf" diff --git a/src/xml.c b/src/xml.c deleted file mode 100644 index 88f391b..0000000 --- a/src/xml.c +++ /dev/null @@ -1,246 +0,0 @@ -#include "xml.h" - -#include "pci.h" -#include "container.h" -#include "sandbox.h" - -#include -#include - -result_t generate_container_xml(char** _xml, const char* container, int cpu, uint64_t memory, const char** pcis, const char** iso_paths, int vnc_port, const char* vnc_password) { - // Initialize the output parameters - *_xml = NULL; - - // Generate the PCI XML - char* pci_xml; - result_t result = generate_multi_pci_xml(&pci_xml, pcis); - if (result != success()) - return result; - - // Generate the ISO XML - char* iso_xml; - result = generate_multi_iso_xml(&iso_xml, iso_paths); - if (result != success()) { - free(pci_xml); - return result; - } - - // Generate the VNC XML - char* vnc_xml; - result = generate_vnc_xml(&vnc_xml, vnc_port, vnc_password); - if (result != success()) { - free(pci_xml); - free(iso_xml); - return result; - } - - // Get the container path - char* container_path; - result = get_container_path(&container_path, container); - if (result != success()) { - free(pci_xml); - free(iso_xml); - free(vnc_xml); - return result; - } - - // Generate the XML - result = format(_xml, "\n" - "" LIBVIRT_DOMAIN "\n" - "\n\n" - "%llu\n" - "%d\n" - "\n" - "\n\n" - "\n" - "hvm\n" - "\n" - "\n" - "\n\n" - "\n" - "\n" - "\n" - "\n" - "\n\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n\n" - "destroy\n" - "destroy\n" - "destroy\n" - "\n" - "\n" - "\n" - "\n" - "\n\n" - "\n" - "/usr/bin/qemu-system-x86_64\n" - "\n\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n\n" - "%s" - "\n\n" - "%s" - "\n\n" - "%s" - "\n\n" - "\n" - "\n" - "\n" - "\n", - memory, cpu, container_path, iso_xml, vnc_xml, pci_xml); - - // Free the PCI, ISO, and VNC XML - free(pci_xml); - free(iso_xml); - free(vnc_xml); - - return result; -} - -result_t generate_iso_xml(char** _xml, const char* iso_path, int index) { - // Initialize the output parameters - *_xml = NULL; - - if (index >= 26) - return failure("Too many ISO images"); - - // Generate the XML - return format(_xml, "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n", - iso_path, 'a' + index, index + 1); // sda is reserved for the hard drive -} - -result_t generate_multi_iso_xml(char** _xml, const char** iso_paths) { - // Initialize the output parameters - *_xml = NULL; - - char* xml = strdup(""); - if (xml == NULL) - return failure("Failed to allocate memory for XML"); - - if (iso_paths == NULL) { - *_xml = xml; - return success(); - } - - // For each ISO path, generate the XML and append it to the result - for (int i = 0; iso_paths[i] != NULL; i++) { - // Generate the XML for the ISO - char* iso_xml; - result_t result = generate_iso_xml(&iso_xml, iso_paths[i], i + 1); // +1 to skip the hard drive - if (result != success()) { - free(xml); - return result; - } - - // Append the ISO XML to the result - char* new_xml; - result = format(&new_xml, "%s%s", xml == NULL ? "" : xml, iso_xml); - - free(iso_xml); - - // Check that the append operation was successful - if (result != success()) { - free(xml); - return result; - } - - // Swap the XML strings - free(xml); - xml = new_xml; - } - - *_xml = xml; - return success(); -} - -result_t generate_pci_xml(char** _xml, const char* pci) { - // Initialize the output parameters - *_xml = NULL; - - // Check that the PCI address is valid - result_t result = check_pci_address(pci); - if (result != success()) - return result; - - // Split the PCI address into its components - unsigned int domain, bus, slot, function; - sscanf(pci, "%04x:%02x:%02x.%01x", &domain, &bus, &slot, &function); - - // Generate the XML - return format(_xml, "\n" - "\n" - "
\n" - "\n" - "\n", - domain, bus, slot, function); -} - -result_t generate_multi_pci_xml(char** _xml, const char** pcis) { - // Initialize the output parameters - *_xml = NULL; - - char* xml = strdup(""); - if (xml == NULL) - return failure("Failed to allocate memory for XML"); - - if (pcis == NULL) { - *_xml = xml; - return success(); - } - - // For each PCI address, generate the XML and append it to the result - for (int i = 0; pcis[i] != NULL; i++) { - // Generate the XML for the PCI address - char* pci_xml; - result_t result = generate_pci_xml(&pci_xml, pcis[i]); - if (result != success()) { - free(xml); - return result; - } - - // Append the PCI XML to the result - char* new_xml; - result = format(&new_xml, "%s%s", xml == NULL ? "" : xml, pci_xml); - - free(pci_xml); - - // Check that the append operation was successful - if (result != success()) { - free(xml); - return result; - } - - // Swap the XML strings - free(xml); - xml = new_xml; - } - - *_xml = xml; - return success(); -} - -result_t generate_vnc_xml(char** _xml, int vnc_port, const char* password) { - // Initialize the output parameters - *_xml = NULL; - - // Generate the XML - if (vnc_port != -1) - return format(_xml, "\n", vnc_port, password); - else - return format(_xml, ""); -} diff --git a/src/xml.h b/src/xml.h index 8062cc2..f89e930 100644 --- a/src/xml.h +++ b/src/xml.h @@ -2,46 +2,33 @@ #include "utils.h" -/// @brief Generate the libvirt XML used to start a container with the given parameters. -/// @param _xml The string pointer to store the resulting XML in. The caller is responsible for freeing the string. -/// @param container The container to generate the XML for. -/// @param cpu The number of CPUs to allocate to the container. -/// @param memory The amount of memory to allocate to the container, in bytes. -/// @param pcis A null-terminated array of PCI devices to pass through to the container. If NULL, no PCI devices will be passed through. -/// @param iso_paths A null-terminated array of ISO image paths to attach to the container. If NULL, no ISO images will be attached. -/// @param vnc_port The VNC port to use for the container. If -1, no VNC server will be started. -/// @param vnc_password The password to use for the VNC server. This parameter is ignored if VNC is not enabled. +/// @brief Generates the XML configuration for a sandbox domain, using the given parameters. +/// @param _xml The string pointer to store the resulting XML configuration in. The caller is responsible for freeing the string. +/// @param container The container to generate the XML configuration for. +/// @param memory The memory size of the domain, in bytes. +/// @param vcpus The number of virtual CPUs of the domain. +/// @param pci_addresses The PCI addresses of the devices to pass through to the domain. +/// @param iso_paths The paths to the ISO images to pass through to the domain. +/// @param vnc_port The VNC port to use for the domain, or 0 to disable VNC. +/// @param vnc_password The VNC password to use for the domain. If the VNC server is disabled, this parameter is ignored. /// @return The result of the operation. -result_t generate_container_xml(char** _xml, const char* container, int cpu, uint64_t memory, const char** pcis, const char** iso_paths, int vnc_port, const char* vnc_password); +result_t generate_domain_xml(char** _xml, const char* container, uint64_t memory, int vcpus, const char** pci_addresses, const char** iso_paths, int vnc_port, const char* vnc_password); -/// @brief Generate the libvirt XML used to attach an ISO image to a container. -/// @param _xml The string pointer to store the resulting XML in. -/// @param iso_path The path to the ISO image to attach. -/// @param index The index of the ISO image within the container. Must be positive, unique, and less than 26. +/// @brief Generates the XML configuration for passing through the given PCI devices. +/// @param _xml The string pointer to store the resulting XML configuration in. The caller is responsible for freeing the string. +/// @param pci_addresses The PCI addresses of the devices to pass through. /// @return The result of the operation. -result_t generate_iso_xml(char** _xml, const char* iso_path, int index); +result_t generate_pci_xml(char** _xml, const char** pci_addresses); -/// @brief Generate the libvirt XML used to attach multiple ISO images to a container. -/// @param _xml The string pointer to store the resulting XML in. +/// @brief Generates the XML configuration for attaching the given ISO images. +/// @param _xml The string pointer to store the resulting XML configuration in. The caller is responsible for freeing the string. /// @param iso_paths The paths to the ISO images to attach. /// @return The result of the operation. -result_t generate_multi_iso_xml(char** _xml, const char** iso_paths); +result_t generate_iso_xml(char** _xml, const char** iso_paths); -/// @brief Generate the libvirt XML used to pass through a PCI device to a container. -/// @param _xml The string pointer to store the resulting XML in. -/// @param pci The PCI device to generate the XML for. +/// @brief Generates the XML configuration for a VNC server. +/// @param _xml The string pointer to store the resulting XML configuration in. The caller is responsible for freeing the string. +/// @param vnc_port The VNC port to use. If 0, the VNC server will be disabled. +/// @param vnc_password The VNC password to use. If the VNC server is disabled, this parameter is ignored. /// @return The result of the operation. -result_t generate_pci_xml(char** _xml, const char* pci); - -/// @brief Generate the libvirt XML used to pass through multiple PCI devices to a container. -/// @param _xml The string pointer to store the resulting XML in. -/// @param pcis The PCI devices to generate the XML for. -/// @return The result of the operation. -result_t generate_multi_pci_xml(char** _xml, const char** pcis); - -/// @brief Generate the libvirt XML used to start a VNC server for a container. -/// @param _xml The string pointer to store the resulting XML in. -/// @param vnc_port The VNC port to use for the container. -/// @param password The password to use for the VNC server. This parameter is ignored if VNC is not enabled. -/// @return The result of the operation. -result_t generate_vnc_xml(char** _xml, int vnc_port, const char* password); +result_t generate_vnc_xml(char** _xml, int vnc_port, const char* vnc_password); diff --git a/xml b/xml deleted file mode 100644 index d1004f6..0000000 --- a/xml +++ /dev/null @@ -1,65 +0,0 @@ - -sandbox - - -1073741824 -1 - - - - -hvm - - - - - - - - - - - - - - - - - -destroy -destroy -destroy - - - - - - - -/usr/bin/qemu-system-x86_64 - - - - - - - - - - - - - - - - - -
- - - - - - - -