diff options
Diffstat (limited to 'common/misc.c')
-rw-r--r-- | common/misc.c | 115 |
1 files changed, 98 insertions, 17 deletions
diff --git a/common/misc.c b/common/misc.c index e0e32f47c5..530f85f6e3 100644 --- a/common/misc.c +++ b/common/misc.c @@ -13,6 +13,8 @@ #include <led.h> #include <of.h> #include <restart.h> +#include <poweroff.h> +#include <string.h> #include <linux/stringify.h> int errno; @@ -105,16 +107,10 @@ const char *strerror(int errnum) } EXPORT_SYMBOL(strerror); -const char *errno_str(void) -{ - return strerror(errno); -} -EXPORT_SYMBOL(errno_str); - void perror(const char *s) { #ifdef CONFIG_ERRNO_MESSAGES - printf("%s: %s\n", s, errno_str()); + printf("%s: %m\n", s); #else printf("%s returned with %d\n", s, errno); #endif @@ -152,6 +148,67 @@ static char *hostname; static char *serial_number; static char *of_machine_compatible; +/* Note that HOST_NAME_MAX is 64 on Linux */ +#define BAREBOX_HOST_NAME_MAX 64 + +static bool barebox_valid_ldh_char(char c) +{ + /* "LDH" -> "Letters, digits, hyphens", as per RFC 5890, Section 2.3.1 */ + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || c == '-'; +} + +bool barebox_hostname_is_valid(const char *s) +{ + unsigned int n_dots = 0; + const char *p; + bool dot, hyphen; + + /* + * Check if s looks like a valid hostname or FQDN. This does not do full + * DNS validation, but only checks if the name is composed of allowed + * characters and the length is not above the maximum allowed by Linux. + * Doesn't accept empty hostnames, hostnames with leading dots, and + * hostnames with multiple dots in a sequence. Doesn't allow hyphens at + * the beginning or end of label. + */ + if (isempty(s)) + return false; + + for (p = s, dot = hyphen = true; *p; p++) { + if (*p == '.') { + if (dot || hyphen) + return false; + + dot = true; + hyphen = false; + n_dots++; + + } else if (*p == '-') { + if (dot) + return false; + + dot = false; + hyphen = true; + + } else { + if (!barebox_valid_ldh_char(*p)) + return false; + + dot = false; + hyphen = false; + } + } + + if (dot || hyphen) + return false; + + if (p - s > BAREBOX_HOST_NAME_MAX) + return false; + + return true; +} + /* * The hostname is supposed to be the shortname of a board. It should * contain only lowercase letters, numbers, '-', '_'. No whitespaces @@ -162,6 +219,10 @@ void barebox_set_hostname(const char *__hostname) globalvar_add_simple_string("hostname", &hostname); free(hostname); + + if (!barebox_hostname_is_valid(__hostname)) + pr_warn("Hostname is not valid, please fix it\n"); + hostname = xstrdup(__hostname); } @@ -222,23 +283,43 @@ device_initcall(of_kernel_init); BAREBOX_MAGICVAR(global.of.kernel.add_machine_compatible, "Additional machine/board compatible"); -void __noreturn panic(const char *fmt, ...) +static void __noreturn do_panic(bool stacktrace, const char *fmt, va_list ap) { - va_list args; - va_start(args, fmt); - vprintf(fmt, args); + vprintf(fmt, ap); putchar('\n'); - va_end(args); - dump_stack(); + if (stacktrace) + dump_stack(); led_trigger(LED_TRIGGER_PANIC, TRIGGER_ENABLE); - if (IS_ENABLED(CONFIG_PANIC_HANG)) { + if (IS_ENABLED(CONFIG_PANIC_HANG)) hang(); - } else { - udelay(100000); /* allow messages to go out */ + + udelay(100000); /* allow messages to go out */ + + if (IS_ENABLED(CONFIG_PANIC_POWEROFF)) + poweroff_machine(); + else restart_machine(); - } +} + +void __noreturn panic(const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + do_panic(true, fmt, args); + va_end(args); } EXPORT_SYMBOL(panic); + +void __noreturn panic_no_stacktrace(const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + do_panic(false, fmt, args); + va_end(args); +} +EXPORT_SYMBOL(panic_no_stacktrace); |