diff options
author | Alejandro Sirgo Rica <asirgo@soleta.eu> | 2024-07-15 16:38:07 +0200 |
---|---|---|
committer | Alejandro Sirgo Rica <asirgo@soleta.eu> | 2024-07-16 13:44:40 +0200 |
commit | e62a55ae37bfdb2aba86696dde5bc27555dd5cf8 (patch) | |
tree | 17e00961938d32d433429e072383684ace7c4cc8 /src | |
parent | df52acba04e85191b0fc7f10b7853fe17fb25260 (diff) |
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/
Diffstat (limited to 'src')
-rw-r--r-- | src/rest.c | 232 |
1 files changed, 196 insertions, 36 deletions
@@ -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; } |