diff options
author | Heinrich Schuchardt <xypron.glpk@gmx.de> | 2020-02-26 21:48:16 +0100 |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2020-04-16 08:07:58 -0600 |
commit | befadde0a24c3a726689745d5a00c8586adc9c84 (patch) | |
tree | 31642c5c60cc0dd358ed960f79aacc2dd43f4898 /common | |
parent | d1a02f53b3f24dfce488ba244ba4f8809bebe596 (diff) | |
download | u-boot-befadde0a24c3a726689745d5a00c8586adc9c84.zip u-boot-befadde0a24c3a726689745d5a00c8586adc9c84.tar.gz u-boot-befadde0a24c3a726689745d5a00c8586adc9c84.tar.bz2 |
log: syslog driver
Provide a log driver that broadcasts RFC 3164 messages to syslog servers.
rsyslog is one implementation of such a server.
The messages are sent to the local broadcast address 255.255.255.255 on
port 514.
The environment variable log_hostname can be used to provide the HOSTNAME
field for the messages. The optional TIMESTAMP field of RFC 3164 is not
provided.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'common')
-rw-r--r-- | common/Kconfig | 7 | ||||
-rw-r--r-- | common/Makefile | 1 | ||||
-rw-r--r-- | common/log_syslog.c | 117 |
3 files changed, 125 insertions, 0 deletions
diff --git a/common/Kconfig b/common/Kconfig index 40da8fa..ee4f748 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -775,6 +775,13 @@ config TPL_LOG_CONSOLE log message is shown - other details like level, category, file and line number are omitted. +config LOG_SYSLOG + bool "Log output to syslog server" + depends on LOG && NET + help + Enables a log driver which broadcasts log records via UDP port 514 + to syslog servers. + config LOG_TEST bool "Provide a test for logging" depends on LOG && UNIT_TEST diff --git a/common/Makefile b/common/Makefile index 702f239..d84e10b 100644 --- a/common/Makefile +++ b/common/Makefile @@ -132,6 +132,7 @@ obj-$(CONFIG_DFU_OVER_USB) += dfu.o obj-y += command.o obj-$(CONFIG_$(SPL_TPL_)LOG) += log.o obj-$(CONFIG_$(SPL_TPL_)LOG_CONSOLE) += log_console.o +obj-$(CONFIG_$(SPL_TPL_)LOG_SYSLOG) += log_syslog.o obj-y += s_record.o obj-$(CONFIG_CMD_LOADB) += xyzModem.o obj-$(CONFIG_$(SPL_TPL_)YMODEM_SUPPORT) += xyzModem.o diff --git a/common/log_syslog.c b/common/log_syslog.c new file mode 100644 index 0000000..5e3e20e --- /dev/null +++ b/common/log_syslog.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Log to syslog. + * + * Copyright (c) 2020, Heinrich Schuchardt <xypron.glpk@gmx.de> + */ + +#include <common.h> +#include <log.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define BUFFER_SIZE 480 + +static void append(char **buf, char *buf_end, const char *fmt, ...) +{ + va_list args; + size_t size = buf_end - *buf; + + va_start(args, fmt); + vsnprintf(*buf, size, fmt, args); + va_end(args); + *buf += strlen(*buf); +} + +static int log_syslog_emit(struct log_device *ldev, struct log_rec *rec) +{ + int ret; + int fmt = gd->log_fmt; + char msg[BUFFER_SIZE]; + char *msg_end = msg + BUFFER_SIZE; + char *ptr = msg; + char *iphdr; + char *log_msg; + int eth_hdr_size; + struct in_addr bcast_ip; + static int processing_msg; + unsigned int log_level; + char *log_hostname; + + /* Fend off messages from the network stack while writing a message */ + if (processing_msg) + return 0; + + processing_msg = 1; + + /* Setup packet buffers */ + net_init(); + /* Disable hardware and put it into the reset state */ + eth_halt(); + /* Set current device according to environment variables */ + eth_set_current(); + /* Get hardware ready for send and receive operations */ + ret = eth_init(); + if (ret < 0) { + eth_halt(); + goto out; + } + + memset(msg, 0, BUFFER_SIZE); + + /* Set ethernet header */ + eth_hdr_size = net_set_ether((uchar *)ptr, net_bcast_ethaddr, PROT_IP); + ptr += eth_hdr_size; + iphdr = ptr; + ptr += IP_UDP_HDR_SIZE; + log_msg = ptr; + + /* + * The syslog log levels defined in RFC 5424 match the U-Boot ones up to + * level 7 (debug). + */ + log_level = rec->level; + if (log_level > 7) + log_level = 7; + /* Leave high bits as 0 to write a 'kernel message' */ + + /* Write log message to buffer */ + append(&ptr, msg_end, "<%u>", log_level); + log_hostname = env_get("log_hostname"); + if (log_hostname) + append(&ptr, msg_end, "%s ", log_hostname); + append(&ptr, msg_end, "uboot: "); + if (fmt & (1 << LOGF_LEVEL)) + append(&ptr, msg_end, "%s.", + log_get_level_name(rec->level)); + if (fmt & (1 << LOGF_CAT)) + append(&ptr, msg_end, "%s,", + log_get_cat_name(rec->cat)); + if (fmt & (1 << LOGF_FILE)) + append(&ptr, msg_end, "%s:", rec->file); + if (fmt & (1 << LOGF_LINE)) + append(&ptr, msg_end, "%d-", rec->line); + if (fmt & (1 << LOGF_FUNC)) + append(&ptr, msg_end, "%s()", rec->func); + if (fmt & (1 << LOGF_MSG)) + append(&ptr, msg_end, "%s%s", + fmt != (1 << LOGF_MSG) ? " " : "", rec->msg); + /* Consider trailing 0x00 */ + ptr++; + + debug("log message: '%s'\n", log_msg); + + /* Broadcast message */ + bcast_ip.s_addr = 0xFFFFFFFFL; + net_set_udp_header((uchar *)iphdr, bcast_ip, 514, 514, ptr - log_msg); + net_send_packet((uchar *)msg, ptr - msg); + +out: + processing_msg = 0; + return ret; +} + +LOG_DRIVER(syslog) = { + .name = "syslog", + .emit = log_syslog_emit, +}; |