summaryrefslogtreecommitdiffstats
path: root/common/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/misc.c')
-rw-r--r--common/misc.c115
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);