diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | src/boot.c | 119 | ||||
-rw-r--r-- | src/boot.h | 14 | ||||
-rw-r--r-- | src/rest.c | 59 |
4 files changed, 181 insertions, 12 deletions
diff --git a/Makefile.am b/Makefile.am index 159f85c..cf0c7b5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,6 +3,7 @@ sbin_PROGRAMS = ogserver AM_CFLAGS = ${LIBDBI_CFLAGS} ${LIBJANSSON_CFLAGS} ${LIBEVENT_CFLAGS} -g -Wall ogserver_SOURCES= src/ogAdmServer.c \ + src/boot.c \ src/cfg.c \ src/core.c \ src/dbi.c \ diff --git a/src/boot.c b/src/boot.c new file mode 100644 index 0000000..c58f332 --- /dev/null +++ b/src/boot.c @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2020-2024 Soleta Networks <info@soleta.eu> + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License as published by the + * Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <syslog.h> +#include <sys/stat.h> +#include <errno.h> +#include "boot.h" +#include "utils.h" + +#define OGRELIVE_TEMPLATE \ +"# Autogenerated by ogserver on %s - do not edit this file!\n" \ +"set ogserver=%s\n" \ +"set ogrepo=%s\n" \ +"set ogreliveversion=%s\n" \ +"set ogrelivedir=ogrelive/$ogreliveversion\n" \ +"set username=%s\n" \ +"set passwd=%s\n" \ +"\n" \ +"set timeout=0\n" \ +"set timeout_style=hidden\n" \ +"\n" \ +"echo \"checking for vmlinuz in cache...\"\n" \ +"set root=''\n" \ +"search --file --set root /boot/$ogreliveversion/vmlinuz\n" \ +"if [ \"$root\" == \"\" ]; then\n" \ +" echo \"no vmlinuz found in cache, booting from network\"\n" \ +" set default=1;\n" \ +"else\n" \ +" echo \"vmlinuz found, booting from cache\"\n" \ +" set default=0;\n" \ +"fi\n" \ +"\n" \ +"menuentry \"ogReLive HTTP boot\" {\n" \ +" insmod http\n" \ +" insmod net\n" \ +" net_bootp\n" \ +" linux (http,$ogrepo)/$ogrelivedir/vmlinuz ro boot=live quiet splash oglivedir=$ogrelivedir ip=$ogserver ogrepo=$ogrepo username=$username passwd=$passwd fetch=http://$ogrepo/$ogrelivedir/filesystem.squashfs\n" \ +" initrd (http,$ogrepo)/$ogrelivedir/initrd.img\n" \ +" boot\n" \ +"}\n" + +/* Same as OG_TFTP_BOOT_UEFI. */ +#define OG_BOOT_GRUB_DIR "/opt/opengnsys/tftpboot/grub" + +static void ogrelive_grub2_file_path(char *grub2_filename, + size_t grub2_filename_size, + const char *mac) +{ + snprintf(grub2_filename, grub2_filename_size, + OG_BOOT_GRUB_DIR"/01-%c%c:%c%c:%c%c:%c%c:%c%c:%c%c", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], + mac[6], mac[7], mac[8], mac[9], mac[10], mac[11]); + str_tolower(grub2_filename); +} + +int ogrelive_generate_grub2_file(const struct og_boot_cfg *cfg, const char *mac) +{ + char grub2_tmp_filename[] = "/tmp/grub_template_XXXXXX"; + char grub2_filename[FILENAME_MAX] = {}; + time_t now = time(NULL); + char *date; + FILE *fp; + int fd; + + date = asctime(localtime(&now)); + date[strlen(date) - 1] = '\0'; + + fd = mkstemp(grub2_tmp_filename); + if (fd < 0) { + syslog(LOG_ERR, "Cannot open %s to %s (%s:%u)\n", + grub2_tmp_filename, grub2_filename, __FILE__, __LINE__); + return -1; + } + + fp = fdopen(fd, "w+"); + if (!fp) { + close(fd); + syslog(LOG_ERR, "Cannot open %s to %s (%s:%u)\n", + grub2_tmp_filename, grub2_filename, __FILE__, __LINE__); + return -1; + } + + fprintf(fp, OGRELIVE_TEMPLATE, date, + cfg->ogserver, cfg->ogrepo, cfg->ogrelivedir, cfg->username, cfg->passwd); + + fclose(fp); + + if (unlink(grub2_filename) < 0) { + if (errno != ENOENT) { + syslog(LOG_ERR, "Failed to delete %s (%s:%u)\n", + grub2_filename, __FILE__, __LINE__); + return -1; + } + } + + ogrelive_grub2_file_path(grub2_filename, sizeof(grub2_filename), mac); + + if (rename(grub2_tmp_filename, grub2_filename) < 0) { + unlink(grub2_tmp_filename); + syslog(LOG_ERR, "Failed to rename %s to %s (%s:%u)\n", + grub2_tmp_filename, grub2_filename, __FILE__, __LINE__); + return -1; + } + + chmod(grub2_filename, 0644); + + return 0; +} diff --git a/src/boot.h b/src/boot.h new file mode 100644 index 0000000..4e3ff45 --- /dev/null +++ b/src/boot.h @@ -0,0 +1,14 @@ +#ifndef _OG_BOOT_H_ +#define _OG_BOOT_H_ + +struct og_boot_cfg { + const char *ogserver; + const char *ogrepo; + const char *ogrelivedir; + const char *username; + const char *passwd; +}; + +int ogrelive_generate_grub2_file(const struct og_boot_cfg *cfg, const char *mac); + +#endif /* _OG_BOOT_H_ */ @@ -16,6 +16,7 @@ #include "wol.h" #include "cfg.h" #include "repo.h" +#include "boot.h" #include <ev.h> #include <syslog.h> #include <sys/ioctl.h> @@ -1168,6 +1169,16 @@ static int og_get_boot_modes(struct list_head *boot_mode_list) } closedir(d); + /* ogrelive built-in grub2 template. */ + mode = calloc(1, sizeof(struct og_boot_mode)); + if (!mode) { + og_boot_mode_free(boot_mode_list); + return -1; + } + + snprintf(mode->name, FILENAME_MAX, "ogrelive"); + list_add_tail(&mode->list, boot_mode_list); + return 0; } @@ -1657,20 +1668,44 @@ static int og_set_client_mode(struct og_dbi *dbi, const char *client_ip, return -1; } - if (og_get_client_mode_params(dbi, mac, params, sizeof(params)) < 0) { - syslog(LOG_ERR, "failed to get boot parameters (%s:%d)\n", __FILE__, __LINE__); - return -1; - } + if (!strcmp(mode, "ogrelive")) { + struct og_boot_mode_params boot_params = {}; + struct og_boot_cfg boot_cfg = {}; - 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; - } + if (og_boot_params_find(dbi, &boot_params, mac) < 0) { + syslog(LOG_ERR, "failed to get boot parameters (%s:%d)\n", __FILE__, __LINE__); + return -1; + } - 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; + boot_cfg.ogserver = boot_params.server_ip; + boot_cfg.ogrepo = boot_params.repo_ip; + boot_cfg.ogrelivedir = boot_params.oglivedir; + boot_cfg.username = "opengnsys"; + boot_cfg.passwd = ogconfig.db.pass; + + if (ogrelive_generate_grub2_file(&boot_cfg, mac) < 0) { + syslog(LOG_ERR, "failed to create HTTP boot file (%s:%d)\n", __FILE__, __LINE__); + og_boot_params_free(&boot_params); + return -1; + } + + og_boot_params_free(&boot_params); + } else { + if (og_get_client_mode_params(dbi, mac, params, sizeof(params)) < 0) { + syslog(LOG_ERR, "failed to get boot parameters (%s:%d)\n", __FILE__, __LINE__); + return -1; + } + + 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; + } + + 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; + } } if (og_change_db_mode(dbi, mac, mode) < 0) { |