|
|
1.1 ! root 1: /* ! 2: * Copyright (C) 2011 Michael Brown <[email protected]>. ! 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., 675 Mass Ave, Cambridge, MA 02139, USA. ! 17: */ ! 18: ! 19: FILE_LICENCE ( GPL2_OR_LATER ); ! 20: ! 21: /** @file ! 22: * ! 23: * Syslog protocol ! 24: * ! 25: */ ! 26: ! 27: #include <stdint.h> ! 28: #include <byteswap.h> ! 29: #include <ipxe/xfer.h> ! 30: #include <ipxe/open.h> ! 31: #include <ipxe/tcpip.h> ! 32: #include <ipxe/dhcp.h> ! 33: #include <ipxe/settings.h> ! 34: #include <ipxe/console.h> ! 35: #include <ipxe/ansiesc.h> ! 36: #include <ipxe/syslog.h> ! 37: ! 38: /** The syslog server */ ! 39: static struct sockaddr_tcpip logserver = { ! 40: .st_port = htons ( SYSLOG_PORT ), ! 41: }; ! 42: ! 43: /** Syslog UDP interface operations */ ! 44: static struct interface_operation syslogger_operations[] = {}; ! 45: ! 46: /** Syslog UDP interface descriptor */ ! 47: static struct interface_descriptor syslogger_desc = ! 48: INTF_DESC_PURE ( syslogger_operations ); ! 49: ! 50: /** The syslog UDP interface */ ! 51: static struct interface syslogger = INTF_INIT ( syslogger_desc ); ! 52: ! 53: /****************************************************************************** ! 54: * ! 55: * Console driver ! 56: * ! 57: ****************************************************************************** ! 58: */ ! 59: ! 60: /** Syslog line buffer */ ! 61: static char syslog_buffer[SYSLOG_BUFSIZE]; ! 62: ! 63: /** Index into syslog line buffer */ ! 64: static unsigned int syslog_idx; ! 65: ! 66: /** Syslog recursion marker */ ! 67: static int syslog_entered; ! 68: ! 69: /** Syslog ANSI escape sequence handlers */ ! 70: static struct ansiesc_handler syslog_ansiesc_handlers[] = { ! 71: { 0, NULL } ! 72: }; ! 73: ! 74: /** Syslog ANSI escape sequence context */ ! 75: static struct ansiesc_context syslog_ansiesc_ctx = { ! 76: .handlers = syslog_ansiesc_handlers, ! 77: }; ! 78: ! 79: /** ! 80: * Print a character to syslog console ! 81: * ! 82: * @v character Character to be printed ! 83: */ ! 84: static void syslog_putchar ( int character ) { ! 85: int rc; ! 86: ! 87: /* Do nothing if we have no log server */ ! 88: if ( ! logserver.st_family ) ! 89: return; ! 90: ! 91: /* Ignore if we are already mid-logging */ ! 92: if ( syslog_entered ) ! 93: return; ! 94: ! 95: /* Strip ANSI escape sequences */ ! 96: character = ansiesc_process ( &syslog_ansiesc_ctx, character ); ! 97: if ( character < 0 ) ! 98: return; ! 99: ! 100: /* Ignore carriage return */ ! 101: if ( character == '\r' ) ! 102: return; ! 103: ! 104: /* Treat newline as a terminator */ ! 105: if ( character == '\n' ) ! 106: character = 0; ! 107: ! 108: /* Add character to buffer */ ! 109: syslog_buffer[syslog_idx++] = character; ! 110: ! 111: /* Do nothing more unless we reach end-of-line (or end-of-buffer) */ ! 112: if ( ( character != 0 ) && ! 113: ( syslog_idx < ( sizeof ( syslog_buffer ) - 1 /* NUL */ ) ) ) { ! 114: return; ! 115: } ! 116: ! 117: /* Reset to start of buffer */ ! 118: syslog_idx = 0; ! 119: ! 120: /* Guard against re-entry */ ! 121: syslog_entered = 1; ! 122: ! 123: /* Send log message */ ! 124: if ( ( rc = xfer_printf ( &syslogger, "<%d>ipxe: %s", ! 125: SYSLOG_PRIORITY ( SYSLOG_FACILITY, ! 126: SYSLOG_SEVERITY ), ! 127: syslog_buffer ) ) != 0 ) { ! 128: DBG ( "SYSLOG could not send log message: %s\n", ! 129: strerror ( rc ) ); ! 130: } ! 131: ! 132: /* Clear re-entry flag */ ! 133: syslog_entered = 0; ! 134: } ! 135: ! 136: /** Syslog console driver */ ! 137: struct console_driver syslog_console __console_driver = { ! 138: .putchar = syslog_putchar, ! 139: }; ! 140: ! 141: /****************************************************************************** ! 142: * ! 143: * Settings ! 144: * ! 145: ****************************************************************************** ! 146: */ ! 147: ! 148: /** Syslog server setting */ ! 149: struct setting syslog_setting __setting ( SETTING_MISC ) = { ! 150: .name = "syslog", ! 151: .description = "Syslog server", ! 152: .tag = DHCP_LOG_SERVERS, ! 153: .type = &setting_type_ipv4, ! 154: }; ! 155: ! 156: /** ! 157: * Apply syslog settings ! 158: * ! 159: * @ret rc Return status code ! 160: */ ! 161: static int apply_syslog_settings ( void ) { ! 162: struct sockaddr_in *sin_logserver = ! 163: ( struct sockaddr_in * ) &logserver; ! 164: struct in_addr old_addr; ! 165: int len; ! 166: int rc; ! 167: ! 168: /* Fetch log server */ ! 169: old_addr.s_addr = sin_logserver->sin_addr.s_addr; ! 170: logserver.st_family = 0; ! 171: if ( ( len = fetch_ipv4_setting ( NULL, &syslog_setting, ! 172: &sin_logserver->sin_addr ) ) >= 0 ) { ! 173: sin_logserver->sin_family = AF_INET; ! 174: } ! 175: ! 176: /* Do nothing unless log server has changed */ ! 177: if ( sin_logserver->sin_addr.s_addr == old_addr.s_addr ) ! 178: return 0; ! 179: ! 180: /* Reset syslog connection */ ! 181: intf_restart ( &syslogger, 0 ); ! 182: ! 183: /* Do nothing unless we have a log server */ ! 184: if ( ! logserver.st_family ) { ! 185: DBG ( "SYSLOG has no log server\n" ); ! 186: return 0; ! 187: } ! 188: ! 189: /* Connect to log server */ ! 190: if ( ( rc = xfer_open_socket ( &syslogger, SOCK_DGRAM, ! 191: ( ( struct sockaddr * ) &logserver ), ! 192: NULL ) ) != 0 ) { ! 193: DBG ( "SYSLOG cannot connect to log server: %s\n", ! 194: strerror ( rc ) ); ! 195: return rc; ! 196: } ! 197: DBG ( "SYSLOG using log server %s\n", ! 198: inet_ntoa ( sin_logserver->sin_addr ) ); ! 199: ! 200: return 0; ! 201: } ! 202: ! 203: /** Syslog settings applicator */ ! 204: struct settings_applicator syslog_applicator __settings_applicator = { ! 205: .apply = apply_syslog_settings, ! 206: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.