From: Heinrich Schuchardt Date: Wed, 26 Feb 2020 20:48:16 +0000 (+0100) Subject: log: syslog driver X-Git-Url: http://git.dujemihanovic.xyz/img/static/git-logo.png?a=commitdiff_plain;h=befadde0a24c3a726689745d5a00c8586adc9c84;p=u-boot.git 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 Reviewed-by: Simon Glass --- diff --git a/MAINTAINERS b/MAINTAINERS index d8d420f84f..0bafe5cabc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -654,7 +654,7 @@ LOGGING M: Simon Glass S: Maintained T: git https://gitlab.denx.de/u-boot/u-boot.git -F: common/log.c +F: common/log* F: cmd/log.c F: test/log/log_test.c F: test/py/tests/test_log.py diff --git a/common/Kconfig b/common/Kconfig index 40da8fa7a3..ee4f748c32 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 702f2396cf..d84e10ba99 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 0000000000..5e3e20e8a4 --- /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 + */ + +#include +#include + +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, +}; diff --git a/doc/README.log b/doc/README.log index 19856d43da..1057981f45 100644 --- a/doc/README.log +++ b/doc/README.log @@ -147,7 +147,10 @@ several possible determinations for logging information, all of which can be enabled or disabled independently: console - goes to stdout + syslog - broadcast RFC 3164 messages to syslog servers on UDP port 514 +The syslog driver sends the value of environmental variable 'log_hostname' as +HOSTNAME if available. Log format ----------