From e62a55ae37bfdb2aba86696dde5bc27555dd5cf8 Mon Sep 17 00:00:00 2001 From: Alejandro Sirgo Rica Date: Mon, 15 Jul 2024 16:38:07 +0200 Subject: src: port setclientmode code to C Implement most of the code from the script setclientmode into ogServer to improve error handling and logs. Use a reduced version legacy script to replace the contents of the base PXE template. This file is now called updategrubprofile. Add updategrubprofile to the new extras/ folder. Create BIOS and UEFI files for PXE boot configuration. Each file is located in a different directory and requires a different name pattern. -BIOS- File format: /opt/opengnsys/tftpboot/menu.lst/01-XX-XX-XX-XX-XX-XX Template dir: /opt/opengnsys/tftpboot/menu.lst/templates/ -UEFI- File format: /opt/opengnsys/tftpboot/grub/01-xx:xx:xx:xx:xx:xx Template dir: /opt/opengnsys/tftpboot/grub/templates/ --- extras/updategrubprofile | 14 +++ src/rest.c | 232 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 210 insertions(+), 36 deletions(-) create mode 100644 extras/updategrubprofile diff --git a/extras/updategrubprofile b/extras/updategrubprofile new file mode 100644 index 0000000..f2c83e2 --- /dev/null +++ b/extras/updategrubprofile @@ -0,0 +1,14 @@ +#!/bin/bash + +[ $# -gt 1 ] && exit 1 +source "$1" || exit 1 + +# Obtener directorio ogLive a partir de los datos. +OGLIVEDIR=$(echo "$DATA" | awk -F= 'BEGIN {RS=" "} $1=="oglivedir" {print $2}') + +# Elimina "oglivedir" de los parametros si ya esta en la plantilla. +if grep -q "oglivedir=" ${TEMPLATE_PATH} 2>/dev/null; then + DATA="${DATA/oglivedir=$OGLIVEDIR/}" +fi + +sed -e "s,vga=[0-9]*,,g; s,INFOHOST,${DATA//,/\\,},g; s,set ISODIR=.*,set ISODIR=$OGLIVEDIR,g" ${TEMPLATE_PATH} >${PXEFILE_PATH} diff --git a/src/rest.c b/src/rest.c index c0e158e..32cf757 100644 --- a/src/rest.c +++ b/src/rest.c @@ -1286,18 +1286,204 @@ static bool og_boot_mode_is_valid(const char *name) return found; } +enum { + OG_TFTP_BOOT_BIOS, + OG_TFTP_BOOT_UEFI, + PXE_BOOT_TYPE_MAX, +}; + +const char *pxe_boot_type_to_dir[] = { + [OG_TFTP_BOOT_BIOS] = "/opt/opengnsys/tftpboot/menu.lst", + [OG_TFTP_BOOT_UEFI] = "/opt/opengnsys/tftpboot/grub" +}; + +static const char *pxe_boot_type(const int boot_type) +{ + if (boot_type < 0 || boot_type >= PXE_BOOT_TYPE_MAX) + return NULL; + + return pxe_boot_type_to_dir[boot_type]; +} + +static int get_grub_filename(unsigned int boot_type, const char *mac, + char *pxe_filename, size_t pxe_filename_size) +{ + const char *fmt; + + switch (boot_type) { + case OG_TFTP_BOOT_BIOS: + fmt = "01-%c%c-%c%c-%c%c-%c%c-%c%c-%c%c"; + break; + case OG_TFTP_BOOT_UEFI: + fmt = "01-%c%c:%c%c:%c%c:%c%c:%c%c:%c%c"; + break; + default: + syslog(LOG_ERR, "unknown boot type %d", boot_type); + return -1; + } + + snprintf(pxe_filename, pxe_filename_size, fmt, + mac[0], mac[1], + mac[2], mac[3], + mac[4], mac[5], + mac[6], mac[7], + mac[8], mac[9], + mac[10], mac[11]); + + switch (boot_type) { + case OG_TFTP_BOOT_BIOS: + str_toupper(pxe_filename); + break; + case OG_TFTP_BOOT_UEFI: + str_tolower(pxe_filename); + break; + default: + syslog(LOG_ERR, "unknown boot type %d", boot_type); + return -1; + } + + return 0; +} + +static int get_grub_file_path(unsigned int boot_type, const char *mac, + char *pxe_path, size_t pxe_path_size) +{ + char pxe_filename[PATH_MAX + 1]; + const char *pxe_dir; + int ret; + + pxe_dir = pxe_boot_type(boot_type); + if (!pxe_dir) { + syslog(LOG_ERR, "Invalid boot type parameter (%s:%d)\n", + __func__, __LINE__); + return -1; + } + + ret = get_grub_filename(boot_type, mac, pxe_filename, sizeof(pxe_filename)); + + if (ret < 0) + return -1; + + ret = snprintf(pxe_path, pxe_path_size, + "%s/%s", pxe_dir, pxe_filename); + + if (ret >= pxe_path_size) { + syslog(LOG_ERR, "failed to generate pxe file path (%s:%d)\n", + __func__, __LINE__); + return -1; + } + return 0; +} + +static int og_remove_tftpboot_file(unsigned int boot_type, const char *mac) +{ + char pxe_file_path[PATH_MAX + 1]; + int ret; + + ret = get_grub_file_path(boot_type, mac, pxe_file_path, sizeof(pxe_file_path)); + if (ret < 0) + return -1; + + if (unlink(pxe_file_path) < 0) { + syslog(LOG_ERR, "failed to delete file (%s:%d) %s\n", + __func__, __LINE__, pxe_file_path); + return -1; + } + return 0; +} + +static int og_create_boot_file(unsigned int boot_type, const char *mac, + const char *mode, char *params) +{ + char tmp_filename[] = "/tmp/mode_params_XXXXXX"; + char pxe_template_path[PATH_MAX + 1]; + char pxe_file_path[PATH_MAX + 1]; + char cmd_params[16384] = {}; + const char *pxe_dir; + int status; + pid_t pid; + int ret; + int fd; + + pxe_dir = pxe_boot_type(boot_type); + if (!pxe_dir) { + syslog(LOG_ERR, "Invalid boot type parameter (%s:%d)\n", + __func__, __LINE__); + return -1; + } + + snprintf(pxe_template_path, sizeof(pxe_template_path), + "%s/templates/%s", pxe_dir, mode); + + ret = get_grub_file_path(boot_type, mac, pxe_file_path, sizeof(pxe_file_path)); + if (ret < 0) + return -1; + + if (unlink(pxe_file_path) < 0) + syslog(LOG_INFO, "failed to delete file %s (%s:%d)\n", + pxe_file_path, __func__, __LINE__); + + snprintf(cmd_params, sizeof(cmd_params), + "DATA='%s'\nTEMPLATE_PATH='%s'\nPXEFILE_PATH='%s'", + params, pxe_template_path, pxe_file_path); + + fd = mkstemp(tmp_filename); + if (fd < 0) { + syslog(LOG_ERR, "cannot generate temp file %s: %s (%s:%d)\n", + tmp_filename, strerror(errno), __func__, __LINE__); + return -1; + } + + ret = write(fd, cmd_params, strlen(cmd_params) + 1); + close(fd); + + if (ret < 0) { + syslog(LOG_ERR, "cannot write file %s: %s (%s:%d)\n", + tmp_filename, strerror(errno), __func__, __LINE__); + unlink(tmp_filename); + return -1; + } + + pid = fork(); + if (pid < 0) { + syslog(LOG_ERR, "fork failed (%s:%d) %s\n", + __func__, __LINE__, strerror(errno)); + unlink(tmp_filename); + return -1; + } + + if (pid == 0) { + execlp("/bin/bash", "/bin/bash", + "/opt/opengnsys/bin/updategrubprofile", tmp_filename, NULL); + syslog(LOG_ERR, "failed script execution (%s:%d) %s\n", + __func__, __LINE__, strerror(errno)); + _exit(-1); + } else if (waitpid(pid, &status, 0) < 0) { + syslog(LOG_ERR, "waitpid failed (%s:%d) %s\n", + __func__, __LINE__, strerror(errno)); + unlink(tmp_filename); + return -1; + } + + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + syslog(LOG_ERR, "failed script execution %s (%s:%d)\n", + strerror(errno), __func__, __LINE__); + unlink(tmp_filename); + return -1; + } + + unlink(tmp_filename); + + return 0; +} + static int og_set_client_mode(struct og_dbi *dbi, const char *mac, const char *mode) { - char filename[PATH_MAX + 1] = "/tmp/mode_params_XXXXXX"; - char cmd_params[16384] = {}; char params[4096] = "\0"; const char *msglog; dbi_result result; unsigned int i; - int numbytes; - int status; - int fd; if (!og_boot_mode_is_valid(mode)) { syslog(LOG_ERR, "invalid boot mode in client (%s:%d)\n", @@ -1360,40 +1546,14 @@ static int og_set_client_mode(struct og_dbi *dbi, const char *mac, dbi_result_free(result); - snprintf(cmd_params, sizeof(cmd_params), - "MODE_FILE='%s'\nMAC='%s'\nDATA='%s'\nMODE='PERM'", - mode, mac, params); - - fd = mkstemp(filename); - if (fd < 0) { - syslog(LOG_ERR, "cannot generate temp file (%s:%d)\n", - __func__, __LINE__); - return -1; - } - - numbytes = write(fd, cmd_params, strlen(cmd_params) + 1); - close(fd); - - if (numbytes < 0) { - syslog(LOG_ERR, "cannot write file\n"); - unlink(filename); - return -1; - } - - if (fork() == 0) { - execlp("/bin/bash", "/bin/bash", - "/opt/opengnsys/bin/setclientmode", filename, NULL); - syslog(LOG_ERR, "failed script execution (%s:%d)\n", - __func__, __LINE__); + if (og_create_boot_file(OG_TFTP_BOOT_BIOS, mac, mode, params) < 0) { + syslog(LOG_ERR, "failed to create BIOS boot file (%s:%d)\n", __FILE__, __LINE__); return -1; - } else { - wait(&status); } - unlink(filename); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - syslog(LOG_ERR, "failed script execution (%s:%d)\n", - __func__, __LINE__); + if (og_create_boot_file(OG_TFTP_BOOT_UEFI, mac, mode, params) < 0) { + og_remove_tftpboot_file(OG_TFTP_BOOT_BIOS, mac); + syslog(LOG_ERR, "failed to create UEFI boot file (%s:%d)\n", __FILE__, __LINE__); return -1; } -- cgit v1.2.3-18-g5258