iPXE
syslog.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 FILE_SECBOOT ( PERMITTED );
26 
27 /** @file
28  *
29  * Syslog protocol
30  *
31  */
32 
33 #include <stdint.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include <byteswap.h>
38 #include <ipxe/xfer.h>
39 #include <ipxe/open.h>
40 #include <ipxe/tcpip.h>
41 #include <ipxe/dhcp.h>
42 #include <ipxe/dhcpv6.h>
43 #include <ipxe/settings.h>
44 #include <ipxe/console.h>
45 #include <ipxe/lineconsole.h>
46 #include <ipxe/syslog.h>
47 #include <config/console.h>
48 
49 /* Set default console usage if applicable */
50 #if ! ( defined ( CONSOLE_SYSLOG ) && CONSOLE_EXPLICIT ( CONSOLE_SYSLOG ) )
51 #undef CONSOLE_SYSLOG
52 #define CONSOLE_SYSLOG ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_TUI )
53 #endif
54 
55 /** The syslog server */
56 static union {
57  struct sockaddr sa;
59  struct sockaddr_in sin;
61 } logserver = {
62  .st = {
63  .st_port = htons ( SYSLOG_PORT ),
64  },
65 };
66 
67 /** Syslog UDP interface operations */
69 
70 /** Syslog UDP interface descriptor */
73 
74 /** The syslog UDP interface */
76 
77 /******************************************************************************
78  *
79  * Console driver
80  *
81  ******************************************************************************
82  */
83 
84 /** Host name (for log messages) */
85 static char *syslog_hostname;
86 
87 /** Domain name (for log messages) */
88 static char *syslog_domain;
89 
90 /**
91  * Transmit formatted syslog message
92  *
93  * @v xfer Data transfer interface
94  * @v severity Severity
95  * @v message Message
96  * @v terminator Message terminator
97  * @ret rc Return status code
98  */
99 int syslog_send ( struct interface *xfer, unsigned int severity,
100  const char *message, const char *terminator ) {
101  const char *hostname = ( syslog_hostname ? syslog_hostname : "" );
102  const char *domain = ( ( hostname[0] && syslog_domain ) ?
103  syslog_domain : "" );
104 
105  return xfer_printf ( xfer, "<%d>%s%s%s%sipxe: %s%s",
107  severity ), hostname,
108  ( domain[0] ? "." : "" ), domain,
109  ( hostname[0] ? " " : "" ), message, terminator );
110 }
111 
112 /******************************************************************************
113  *
114  * Console driver
115  *
116  ******************************************************************************
117  */
118 
119 /** Syslog line buffer */
121 
122 /** Syslog severity */
124 
125 /**
126  * Handle ANSI set syslog priority (private sequence)
127  *
128  * @v ctx ANSI escape sequence context
129  * @v count Parameter count
130  * @v params List of graphic rendition aspects
131  */
133  unsigned int count __unused,
134  int params[] ) {
135  if ( params[0] >= 0 ) {
136  syslog_severity = params[0];
137  } else {
139  }
140 }
141 
142 /** Syslog ANSI escape sequence handlers */
143 static struct ansiesc_handler syslog_handlers[] = {
145  { 0, NULL }
146 };
147 
148 /** Syslog line console */
149 static struct line_console syslog_line = {
151  .len = sizeof ( syslog_buffer ),
152  .ctx = {
153  .handlers = syslog_handlers,
154  },
155 };
156 
157 /** Syslog recursion marker */
158 static int syslog_entered;
159 
160 /**
161  * Print a character to syslog console
162  *
163  * @v character Character to be printed
164  */
165 static void syslog_putchar ( int character ) {
166  int rc;
167 
168  /* Ignore if we are already mid-logging */
169  if ( syslog_entered )
170  return;
171 
172  /* Fill line buffer */
173  if ( line_putchar ( &syslog_line, character ) == 0 )
174  return;
175 
176  /* Guard against re-entry */
177  syslog_entered = 1;
178 
179  /* Send log message */
181  syslog_buffer, "" ) ) != 0 ) {
182  DBG ( "SYSLOG could not send log message: %s\n",
183  strerror ( rc ) );
184  }
185 
186  /* Clear re-entry flag */
187  syslog_entered = 0;
188 }
189 
190 /** Syslog console driver */
191 struct console_driver syslog_console __console_driver = {
193  .disabled = CONSOLE_DISABLED,
194  .usage = CONSOLE_SYSLOG,
195 };
196 
197 /******************************************************************************
198  *
199  * Settings
200  *
201  ******************************************************************************
202  */
203 
204 /** IPv4 syslog server setting */
205 const struct setting syslog_setting __setting ( SETTING_MISC, syslog ) = {
206  .name = "syslog",
207  .description = "Syslog server",
208  .tag = DHCP_LOG_SERVERS,
209  .type = &setting_type_ipv4,
210 };
211 
212 /** IPv6 syslog server setting */
213 const struct setting syslog6_setting __setting ( SETTING_MISC, syslog6 ) = {
214  .name = "syslog6",
215  .description = "Syslog server",
216  .tag = DHCPV6_LOG_SERVERS,
217  .type = &setting_type_ipv6,
218  .scope = &dhcpv6_scope,
219 };
220 
221 /**
222  * Strip invalid characters from host/domain name
223  *
224  * @v name Name to strip
225  */
226 static void syslog_fix_name ( char *name ) {
227  char *fixed = name;
228  int c;
229 
230  /* Do nothing if name does not exist */
231  if ( ! name )
232  return;
233 
234  /* Strip any non-printable or whitespace characters from the name */
235  do {
236  c = *(name++);
237  *fixed = c;
238  if ( isprint ( c ) && ! isspace ( c ) )
239  fixed++;
240  } while ( c );
241 }
242 
243 /**
244  * Apply syslog settings
245  *
246  * @ret rc Return status code
247  */
248 static int apply_syslog_settings ( void ) {
249  struct sockaddr old_logserver;
250  int rc;
251 
252  /* Fetch hostname and domain name */
253  free ( syslog_hostname );
254  fetch_string_setting_copy ( NULL, &hostname_setting, &syslog_hostname );
256  free ( syslog_domain );
257  fetch_string_setting_copy ( NULL, &domain_setting, &syslog_domain );
259 
260  /* Fetch log server */
261  syslog_console.disabled = CONSOLE_DISABLED;
262  memcpy ( &old_logserver, &logserver, sizeof ( old_logserver ) );
263  logserver.sa.sa_family = 0;
264  if ( fetch_ipv6_setting ( NULL, &syslog6_setting,
265  &logserver.sin6.sin6_addr ) >= 0 ) {
266  logserver.sin6.sin6_family = AF_INET6;
267  } else if ( fetch_ipv4_setting ( NULL, &syslog_setting,
268  &logserver.sin.sin_addr ) >= 0 ) {
269  logserver.sin.sin_family = AF_INET;
270  }
271  if ( logserver.sa.sa_family ) {
272  syslog_console.disabled = 0;
273  DBG ( "SYSLOG using log server %s\n",
274  sock_ntoa ( &logserver.sa ) );
275  }
276 
277  /* Do nothing unless log server has changed */
278  if ( memcmp ( &logserver, &old_logserver, sizeof ( logserver ) ) == 0 )
279  return 0;
280 
281  /* Reset syslog connection */
282  intf_restart ( &syslogger, 0 );
283 
284  /* Do nothing unless we have a log server */
285  if ( syslog_console.disabled ) {
286  DBG ( "SYSLOG has no log server\n" );
287  return 0;
288  }
289 
290  /* Connect to log server */
292  &logserver.sa, NULL ) ) != 0 ) {
293  DBG ( "SYSLOG cannot connect to log server: %s\n",
294  strerror ( rc ) );
295  return rc;
296  }
297 
298  return 0;
299 }
300 
301 /** Syslog settings applicator */
302 struct settings_applicator syslog_applicator __settings_applicator = {
304 };
An object interface operation.
Definition: interface.h:18
TCP/IP socket address.
Definition: tcpip.h:76
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
const char * name
Definition: ath9k_hw.c:1986
static struct interface_operation syslogger_operations[]
Syslog UDP interface operations.
Definition: syslog.c:68
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition: interface.c:344
#define SYSLOG_PRIORITY(facility, severity)
Syslog priority.
Definition: syslog.h:37
A handler for an escape sequence.
Definition: ansiesc.h:35
Dynamic Host Configuration Protocol.
#define AF_INET6
IPv6 Internet addresses.
Definition: socket.h:65
#define DHCP_LOG_SERVERS
Syslog servers.
Definition: dhcp.h:75
static char syslog_buffer[SYSLOG_BUFSIZE]
Syslog line buffer.
Definition: syslog.c:120
const struct settings_scope dhcpv6_scope
IPv6 settings scope.
Definition: settings.c:1793
static void syslog_handle_priority(struct ansiesc_context *ctx __unused, unsigned int count __unused, int params[])
Handle ANSI set syslog priority (private sequence)
Definition: syslog.c:132
int xfer_open_socket(struct interface *intf, int semantics, struct sockaddr *peer, struct sockaddr *local)
Open socket.
Definition: open.c:143
int fetch_ipv4_setting(struct settings *settings, const struct setting *setting, struct in_addr *inp)
Fetch value of IPv4 address setting.
Definition: settings.c:913
static union @6 logserver
The syslog server.
static unsigned int syslog_severity
Syslog severity.
Definition: syslog.c:123
#define INTF_INIT(descriptor)
Initialise a static object interface.
Definition: interface.h:218
#define SOCK_DGRAM
Definition: socket.h:30
#define CONSOLE_DISABLED
Console is disabled for all uses.
Definition: console.h:112
struct sockaddr_in6 sin6
Definition: syslog.c:60
FILE_SECBOOT(PERMITTED)
#define CONSOLE_SYSLOG
Definition: syslog.c:52
struct eltorito_descriptor_fixed fixed
Fixed portion.
Definition: eltorito.h:13
A settings applicator.
Definition: settings.h:252
#define SETTING_MISC
Miscellaneous settings.
Definition: settings.h:81
#define INTF_DESC_PURE(operations)
Define an object interface descriptor for a pure-interface object.
Definition: interface.h:116
#define DHCPV6_LOG_SERVERS
DHCPv6 syslog server option.
Definition: dhcpv6.h:187
IPv4 socket address.
Definition: in.h:85
static void syslog_fix_name(char *name)
Strip invalid characters from host/domain name.
Definition: syslog.c:226
A line-based console.
Definition: lineconsole.h:17
ANSI escape sequence context.
Definition: ansiesc.h:74
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
Character types.
Line-based console.
const struct setting syslog_setting __setting(SETTING_MISC, syslog)
IPv4 syslog server setting.
static void syslog_putchar(int character)
Print a character to syslog console.
Definition: syslog.c:165
size_t line_putchar(struct line_console *line, int character)
Print a character to a line-based console.
Definition: lineconsole.c:44
static int isprint(int character)
Check if character is printable.
Definition: ctype.h:98
Data transfer interfaces.
const char * name
Name.
Definition: settings.h:29
struct sockaddr_tcpip st
Definition: syslog.c:58
static char * syslog_domain
Domain name (for log messages)
Definition: syslog.c:88
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void(* putchar)(int character)
Write a character to the console.
Definition: console.h:69
An object interface.
Definition: interface.h:125
Syslog protocol.
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
struct sockaddr sa
Definition: syslog.c:57
Transport-network layer interface.
static unsigned int count
Number of entries.
Definition: dwmac.h:225
int fetch_string_setting_copy(struct settings *settings, const struct setting *setting, char **data)
Fetch value of string setting.
Definition: settings.c:874
User interaction.
Configuration settings.
Generalized socket address structure.
Definition: socket.h:97
An object interface descriptor.
Definition: interface.h:56
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:55
struct settings_applicator syslog_applicator __settings_applicator
Syslog settings applicator.
Definition: syslog.c:302
static int syslog_entered
Syslog recursion marker.
Definition: syslog.c:158
#define ANSIESC_LOG_PRIORITY
Explicit log message priority.
Definition: ansiesc.h:126
static int apply_syslog_settings(void)
Apply syslog settings.
Definition: syslog.c:248
int isspace(int character)
Check to see if character is a space.
Definition: ctype.c:42
static char * syslog_hostname
Host name (for log messages)
Definition: syslog.c:85
Data transfer interface opening.
Console configuration.
static struct ansiesc_handler syslog_handlers[]
Syslog ANSI escape sequence handlers.
Definition: syslog.c:143
A setting.
Definition: settings.h:24
#define SYSLOG_PORT
Syslog server port.
Definition: syslog.h:16
int xfer_printf(struct interface *intf, const char *format,...)
Deliver formatted string.
Definition: xfer.c:335
#define SYSLOG_DEFAULT_SEVERITY
Syslog default severity.
Definition: syslog.h:34
const char * sock_ntoa(struct sockaddr *sa)
Transcribe socket address.
Definition: socket.c:43
static struct line_console syslog_line
Syslog line console.
Definition: syslog.c:149
static struct interface_descriptor syslogger_desc
Syslog UDP interface descriptor.
Definition: syslog.c:71
struct console_driver syslog_console __console_driver
Syslog console driver.
Definition: syslog.c:191
#define syslog(priority, fmt,...)
Write message to system log.
Definition: syslog.h:94
int syslog_send(struct interface *xfer, unsigned int severity, const char *message, const char *terminator)
Transmit formatted syslog message.
Definition: syslog.c:99
IPv6 socket address.
Definition: in.h:118
int(* apply)(void)
Apply updated settings.
Definition: settings.h:257
char * buffer
Data buffer.
Definition: lineconsole.h:22
A console driver.
Definition: console.h:56
struct sockaddr_in sin
Definition: syslog.c:59
char message[VMCONSOLE_BUFSIZE]
Definition: vmconsole.c:54
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
#define SYSLOG_BUFSIZE
Syslog line buffer size.
Definition: syslog.h:22
#define SYSLOG_DEFAULT_FACILITY
Syslog default facility.
Definition: syslog.h:28
struct eth_slow_terminator_tlv terminator
Terminator.
Definition: eth_slow.h:21
int fetch_ipv6_setting(struct settings *settings, const struct setting *setting, struct in6_addr *inp)
Fetch value of IPv6 address setting.
Definition: settings.c:951
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:115
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
String functions.
#define htons(value)
Definition: byteswap.h:136
#define AF_INET
IPv4 Internet addresses.
Definition: socket.h:64
Dynamic Host Configuration Protocol for IPv6.
static struct interface syslogger
The syslog UDP interface.
Definition: syslog.c:75