diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ChangeLog | 69 | ||||
-rw-r--r-- | lib/command.c | 636 | ||||
-rw-r--r-- | lib/command.h | 29 | ||||
-rw-r--r-- | lib/log.c | 167 | ||||
-rw-r--r-- | lib/log.h | 82 | ||||
-rw-r--r-- | lib/vty.c | 36 | ||||
-rw-r--r-- | lib/vty.h | 6 |
7 files changed, 672 insertions, 353 deletions
diff --git a/lib/ChangeLog b/lib/ChangeLog index 79062cae..986c67aa 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,3 +1,72 @@ +2004-12-07 Andrew J. Schorr <ajschorr@alumni.princeton.edu> + + * log.h: Replace struct zlog flags and maskpri fields with maxlvl + array to support individual logging levels for each destination. + Remove the 2nd argument to openzlog since the default logging config + should be standardized inside the library. Replaced the + zlog_set_flag and zlog_reset_flag functions with zlog_set_level. + And zlog_set_file now requires an additional log_level argument. + Declare zlog_proto_names for use inside command.c in the + "show logging" command. Added defines useful for command + construction. + * log.c: (vzlog) Decide where to send the message based on the + individual logging levels configured for each destination. + Remove support for ZLOG_STDERR since it was never actually used. + Support record-priority for terminal monitors. + (zlog_signal,zlog_backtrace_sigsafe) Support destination-specific + logging levels. Remove stderr support (was never used). Added + support for terminal monitor logging. + (_zlog_assert_failed) Increase message severity to LOG_EMERG. + (openzlog) Remove 2nd argument since default config should be + standardized in library. By default, terminal monitoring + is set to debug, and all other logging is disabled. + (zlog_set_flag,zlog_reset_flag) Removed. + (zlog_set_level) New function to replace zlog_set_flag and + zlog_reset_flag. Supports destination-specific logging levels. + (zlog_set_file,zlog_reset_file) Support file-specific logging level. + (zlog_rotate) Log an error message if fopen fails, and support + new file-specific logging level. + * command.h: Change DEFUN_CMD_FUNC_DECL and DEFUN_CMD_FUNC_TEXT so that + command functions will be static instead of global. Remove + declarations for config_exit and config_help. Define new macros + DEFUNSH_ATTR, DEFUNSH_HIDDEN, and DEFUNSH_DEPRECATED so we can + have deprecated commands in vtysh. Similarly, for completeness, + define macros ALIAS_SH, ALIAS_SH_HIDDEN, and ALIAS_SH_DEPRECATED. + Also, fix bug in ALIAS_ATTR macro (didn't matter because it + was never used). + * command.c: Make many functions static instead of global. + (facility_name,facility_match,level_match) New functions + to support enhanced destination-specific logging levels. + (config_write_host) Support new destination-specific logging levels. + (config_logmsg) Added new "logmsg" command to help test logging + system. + (show_logging) Added "show logging" command to show the current + configuration of the logging system. + (config_log_stdout_level) Support explicit stdout logging level. + (no_config_log_stdout) Now takes optional LEVEL arg. + (config_log_monitor,config_log_monitor_level,no_config_log_monitor) + New commands creating new "log monitor" commands to set terminal + monitoring log level. + (config_log_file_level) Support explicit file logging level. + (config_log_syslog_level) Support explicit syslog logging level. + (config_log_facility,no_config_log_facility) Implement new + "log facility" command. + (cmd_init) Add hooks for new commands: "show logging", "logmsg", + "log stdout <level>", "log monitor", "log monitor <level>", + "no log monitor", "log file <filename> <level>", + "no log file <filename> <level>", "log syslog <level>", + "log facility", and "no log facility". + * vty.h: Added a "level" argument to vty_log so it can support + "log record-priority". Declare new function vty_log_fixed for + use in signal handlers. + * vty.c: (vty_log,vty_log_out) Added a "level" argument to support + "log record-priority" for vty terminal monitors. + (vty_down_level) Use config_exit_cmd.func instead of calling + config_exit directly (since command functions will now be static + instead of global). + (vty_log_fixed) New function to send terminal monitor messages + from inside a signal handler. + 2004-12-03 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * log.h: Document appropriate use of syslog logging priorities diff --git a/lib/command.c b/lib/command.c index 99036d17..18829672 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,4 +1,7 @@ -/* Command interpreter routine for virtual terminal [aka TeletYpe] +/* + $Id: command.c,v 1.28 2004/12/07 15:39:32 ajs Exp $ + + Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro This file is part of GNU Zebra. @@ -75,6 +78,70 @@ Hello, this is " QUAGGA_PROGNAME " (version " QUAGGA_VERSION ").\r\n\ " QUAGGA_COPYRIGHT "\r\n\ \r\n"; + +static struct facility_map { + int facility; + const char *name; + size_t match; +} syslog_facilities[] = + { + { LOG_KERN, "kern", 1 }, + { LOG_USER, "user", 2 }, + { LOG_MAIL, "mail", 1 }, + { LOG_DAEMON, "daemon", 1 }, + { LOG_AUTH, "auth", 1 }, + { LOG_SYSLOG, "syslog", 1 }, + { LOG_LPR, "lpr", 2 }, + { LOG_NEWS, "news", 1 }, + { LOG_UUCP, "uucp", 2 }, + { LOG_CRON, "cron", 1 }, +#ifdef LOG_FTP + { LOG_FTP, "ftp", 1 }, +#endif + { LOG_LOCAL0, "local0", 6 }, + { LOG_LOCAL1, "local1", 6 }, + { LOG_LOCAL2, "local2", 6 }, + { LOG_LOCAL3, "local3", 6 }, + { LOG_LOCAL4, "local4", 6 }, + { LOG_LOCAL5, "local5", 6 }, + { LOG_LOCAL6, "local6", 6 }, + { LOG_LOCAL7, "local7", 6 }, + { 0, NULL, 0 }, + }; + +static const char * +facility_name(int facility) +{ + struct facility_map *fm; + + for (fm = syslog_facilities; fm->name; fm++) + if (fm->facility == facility) + return fm->name; + return ""; +} + +static int +facility_match(const char *str) +{ + struct facility_map *fm; + + for (fm = syslog_facilities; fm->name; fm++) + if (!strncmp(str,fm->name,fm->match)) + return fm->facility; + return -1; +} + +static int +level_match(const char *s) +{ + int level ; + + for ( level = 0 ; zlog_priority [level] != NULL ; level ++ ) + if (!strncmp (s, zlog_priority[level], 2)) + return level; + return ZLOG_DISABLED; +} + void print_version (const char *progname) { @@ -128,7 +195,7 @@ install_node (struct cmd_node *node, } /* Compare two command's string. Used in sort_node (). */ -int +static int cmp_node (const void *p, const void *q) { struct cmd_element *a = *(struct cmd_element **)p; @@ -137,7 +204,7 @@ cmp_node (const void *p, const void *q) return strcmp (a->string, b->string); } -int +static int cmp_desc (const void *p, const void *q) { struct desc *a = *(struct desc **)p; @@ -241,7 +308,7 @@ cmd_free_strvec (vector v) } /* Fetch next description. Used in cmd_make_descvec(). */ -char * +static char * cmd_desc_str (const char **string) { const char *cp, *start; @@ -277,7 +344,7 @@ cmd_desc_str (const char **string) } /* New string vector. */ -vector +static vector cmd_make_descvec (const char *string, const char *descstr) { int multiple = 0; @@ -370,7 +437,7 @@ cmd_make_descvec (const char *string, const char *descstr) /* Count mandantory string vector size. This is to determine inputed command has enough command length. */ -int +static int cmd_cmdsize (vector strvec) { unsigned int i; @@ -430,7 +497,7 @@ install_element (enum node_type ntype, struct cmd_element *cmd) static unsigned char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; -void +static void to64(char *s, long v, int n) { while (--n >= 0) @@ -440,7 +507,8 @@ to64(char *s, long v, int n) } } -char *zencrypt (const char *passwd) +static char * +zencrypt (const char *passwd) { char salt[6]; struct timeval tv; @@ -455,73 +523,8 @@ char *zencrypt (const char *passwd) return crypt (passwd, salt); } -const char * -syslog_facility_print (int facility) -{ - switch (facility) - { - case LOG_KERN: - return "kern"; - break; - case LOG_USER: - return "user"; - break; - case LOG_MAIL: - return "mail"; - break; - case LOG_DAEMON: - return "daemon"; - break; - case LOG_AUTH: - return "auth"; - break; - case LOG_SYSLOG: - return "syslog"; - break; - case LOG_LPR: - return "lpr"; - break; - case LOG_NEWS: - return "news"; - break; - case LOG_UUCP: - return "uucp"; - break; - case LOG_CRON: - return "cron"; - break; - case LOG_LOCAL0: - return "local0"; - break; - case LOG_LOCAL1: - return "local1"; - break; - case LOG_LOCAL2: - return "local2"; - break; - case LOG_LOCAL3: - return "local3"; - break; - case LOG_LOCAL4: - return "local4"; - break; - case LOG_LOCAL5: - return "local5"; - break; - case LOG_LOCAL6: - return "local6"; - break; - case LOG_LOCAL7: - return "local7"; - break; - default: - break; - } - return ""; -} - /* This function write configuration of this host. */ -int +static int config_write_host (struct vty *vty) { if (host.name) @@ -542,21 +545,46 @@ config_write_host (struct vty *vty) vty_out (vty, "enable password %s%s", host.enable, VTY_NEWLINE); } - if (host.logfile) - vty_out (vty, "log file %s%s", host.logfile, VTY_NEWLINE); + if (zlog_default->default_lvl != LOG_DEBUG) + vty_out (vty, "log trap %s%s", + zlog_priority[zlog_default->default_lvl], VTY_NEWLINE); + + if (host.logfile && (zlog_default->maxlvl[ZLOG_DEST_FILE] != ZLOG_DISABLED)) + { + vty_out (vty, "log file %s", host.logfile); + if (zlog_default->maxlvl[ZLOG_DEST_FILE] != zlog_default->default_lvl) + vty_out (vty, " %s", + zlog_priority[zlog_default->maxlvl[ZLOG_DEST_FILE]]); + vty_out (vty, "%s", VTY_NEWLINE); + } + + if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != ZLOG_DISABLED) + { + vty_out (vty, "log stdout"); + if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != zlog_default->default_lvl) + vty_out (vty, " %s", + zlog_priority[zlog_default->maxlvl[ZLOG_DEST_STDOUT]]); + vty_out (vty, "%s", VTY_NEWLINE); + } - if (zlog_default->flags & ZLOG_STDOUT) - vty_out (vty, "log stdout%s", VTY_NEWLINE); + if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED) + vty_out(vty,"no log monitor%s",VTY_NEWLINE); + else if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] != zlog_default->default_lvl) + vty_out(vty,"log monitor %s%s", + zlog_priority[zlog_default->maxlvl[ZLOG_DEST_MONITOR]],VTY_NEWLINE); - if (zlog_default->flags & ZLOG_SYSLOG) + if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED) { vty_out (vty, "log syslog"); - if (zlog_default->facility != LOG_DAEMON) - vty_out (vty, " facility %s", syslog_facility_print (zlog_default->facility)); + if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != zlog_default->default_lvl) + vty_out (vty, " %s", + zlog_priority[zlog_default->maxlvl[ZLOG_DEST_SYSLOG]]); vty_out (vty, "%s", VTY_NEWLINE); } - if (zlog_default->maskpri != LOG_DEBUG) - vty_out (vty, "log trap %s%s", zlog_priority[zlog_default->maskpri], VTY_NEWLINE); + + if (zlog_default->facility != LOG_DAEMON) + vty_out (vty, "log facility %s%s", + facility_name(zlog_default->facility), VTY_NEWLINE); if (zlog_default->record_priority == 1) vty_out (vty, "log record-priority%s", VTY_NEWLINE); @@ -578,15 +606,17 @@ config_write_host (struct vty *vty) } /* Utility function for getting command vector. */ -vector +static vector cmd_node_vector (vector v, enum node_type ntype) { struct cmd_node *cnode = vector_slot (v, ntype); return cnode->cmd_vector; } -/* Filter command vector by symbol */ -int +#if 0 +/* Filter command vector by symbol. This function is not actually used; + * should it be deleted? */ +static int cmd_filter_by_symbol (char *command, char *symbol) { int i, lim; @@ -629,6 +659,7 @@ cmd_filter_by_symbol (char *command, char *symbol) } return 0; } +#endif /* Completion match types. */ enum match_type @@ -645,7 +676,7 @@ enum match_type exact_match }; -enum match_type +static enum match_type cmd_ipv4_match (const char *str) { const char *sp; @@ -702,7 +733,7 @@ cmd_ipv4_match (const char *str) return exact_match; } -enum match_type +static enum match_type cmd_ipv4_prefix_match (const char *str) { const char *sp; @@ -793,7 +824,7 @@ cmd_ipv4_prefix_match (const char *str) #ifdef HAVE_IPV6 -enum match_type +static enum match_type cmd_ipv6_match (const char *str) { int state = STATE_START; @@ -899,7 +930,7 @@ cmd_ipv6_match (const char *str) return exact_match; } -enum match_type +static enum match_type cmd_ipv6_prefix_match (const char *str) { int state = STATE_START; @@ -1034,7 +1065,7 @@ cmd_ipv6_prefix_match (const char *str) #define DECIMAL_STRLEN_MAX 10 -int +static int cmd_range_match (const char *range, const char *str) { char *p; @@ -1080,7 +1111,7 @@ cmd_range_match (const char *range, const char *str) } /* Make completion match and return match type flag. */ -enum match_type +static enum match_type cmd_filter_by_completion (char *command, vector v, unsigned int index) { unsigned int i; @@ -1195,7 +1226,7 @@ cmd_filter_by_completion (char *command, vector v, unsigned int index) } /* Filter vector by command character with index. */ -enum match_type +static enum match_type cmd_filter_by_string (char *command, vector v, unsigned int index) { unsigned int i; @@ -1303,7 +1334,7 @@ cmd_filter_by_string (char *command, vector v, unsigned int index) } /* Check ambiguous match */ -int +static int is_cmd_ambiguous (char *command, vector v, int index, enum match_type type) { unsigned int i; @@ -1400,7 +1431,7 @@ is_cmd_ambiguous (char *command, vector v, int index, enum match_type type) } /* If src matches dst return dst string, otherwise return NULL */ -const char * +static const char * cmd_entry_function (const char *src, const char *dst) { /* Skip variable arguments. */ @@ -1422,7 +1453,7 @@ cmd_entry_function (const char *src, const char *dst) /* If src matches dst return dst string, otherwise return NULL */ /* This version will return the dst string always if it is CMD_VARIABLE for '?' key processing */ -const char * +static const char * cmd_entry_function_desc (const char *src, const char *dst) { if (CMD_VARARG (dst)) @@ -1486,7 +1517,7 @@ cmd_entry_function_desc (const char *src, const char *dst) /* Check same string element existence. If it isn't there return 1. */ -int +static int cmd_unique_string (vector v, const char *str) { unsigned int i; @@ -1501,7 +1532,7 @@ cmd_unique_string (vector v, const char *str) /* Compare string to description vector. If there is same string return 1 else return 0. */ -int +static int desc_unique_string (vector v, const char *str) { unsigned int i; @@ -1514,7 +1545,7 @@ desc_unique_string (vector v, const char *str) return 0; } -int +static int cmd_try_do_shortcut (enum node_type node, char* first_word) { if ( first_word != NULL && node != AUTH_NODE && @@ -1527,7 +1558,7 @@ cmd_try_do_shortcut (enum node_type node, char* first_word) { } /* '?' describe command support. */ -vector +static vector cmd_describe_command_real (vector vline, struct vty *vty, int *status) { unsigned int i; @@ -1690,7 +1721,7 @@ cmd_describe_command (vector vline, struct vty *vty, int *status) /* Check LCD of matched command. */ -int +static int cmd_lcd (char **matched) { int i; @@ -1723,7 +1754,7 @@ cmd_lcd (char **matched) } /* Command line completion support. */ -char ** +static char ** cmd_complete_command_real (vector vline, struct vty *vty, int *status) { unsigned int i; @@ -1905,7 +1936,8 @@ cmd_complete_command (vector vline, struct vty *vty, int *status) /* return parent node */ /* MUST eventually converge on CONFIG_NODE */ -enum node_type node_parent ( enum node_type node ) +static enum node_type +node_parent ( enum node_type node ) { enum node_type ret; @@ -1930,7 +1962,7 @@ enum node_type node_parent ( enum node_type node ) } /* Execute command by argument vline vector. */ -int +static int cmd_execute_command_real (vector vline, struct vty *vty, struct cmd_element **cmd) { unsigned int i; @@ -2959,40 +2991,158 @@ DEFUN (no_service_terminal_length, no_service_terminal_length_cmd, return CMD_SUCCESS; } +DEFUN (config_logmsg, + config_logmsg_cmd, + "logmsg "LOG_LEVELS" .MESSAGE", + "Send a message to enabled logging destinations\n" + LOG_LEVEL_DESC + "The message to send\n") +{ + int level; + char *message; + + if ((level = level_match(argv[0])) == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; + + zlog(NULL, level, (message = argv_concat(argv, argc, 1))); + XFREE(MTYPE_TMP, message); + return CMD_SUCCESS; +} + +DEFUN (show_logging, + show_logging_cmd, + "show logging", + SHOW_STR + "Show current logging configuration\n") +{ + struct zlog *zl = zlog_default; + + vty_out (vty, "Syslog logging: "); + if (zl->maxlvl[ZLOG_DEST_SYSLOG] == ZLOG_DISABLED) + vty_out (vty, "disabled"); + else + vty_out (vty, "level %s, facility %s, ident %s", + zlog_priority[zl->maxlvl[ZLOG_DEST_SYSLOG]], + facility_name(zl->facility), zl->ident); + vty_out (vty, "%s", VTY_NEWLINE); + + vty_out (vty, "Stdout logging: "); + if (zl->maxlvl[ZLOG_DEST_STDOUT] == ZLOG_DISABLED) + vty_out (vty, "disabled"); + else + vty_out (vty, "level %s", + zlog_priority[zl->maxlvl[ZLOG_DEST_STDOUT]]); + vty_out (vty, "%s", VTY_NEWLINE); + + vty_out (vty, "Monitor logging: "); + if (zl->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED) + vty_out (vty, "disabled"); + else + vty_out (vty, "level %s", + zlog_priority[zl->maxlvl[ZLOG_DEST_MONITOR]]); + vty_out (vty, "%s", VTY_NEWLINE); + + vty_out (vty, "File logging: "); + if ((zl->maxlvl[ZLOG_DEST_FILE] == ZLOG_DISABLED) || + !zl->fp) + vty_out (vty, "disabled"); + else + vty_out (vty, "level %s, filename %s", + zlog_priority[zl->maxlvl[ZLOG_DEST_FILE]], + zl->filename); + vty_out (vty, "%s", VTY_NEWLINE); + + vty_out (vty, "Protocol name: %s%s", + zlog_proto_names[zl->protocol], VTY_NEWLINE); + vty_out (vty, "Record priority: %s%s", + (zl->record_priority ? "enabled" : "disabled"), VTY_NEWLINE); + + return CMD_SUCCESS; +} + DEFUN (config_log_stdout, config_log_stdout_cmd, "log stdout", "Logging control\n" - "Logging goes to stdout\n") + "Set stdout logging level\n") { - zlog_set_flag (NULL, ZLOG_STDOUT); + zlog_set_level (NULL, ZLOG_DEST_STDOUT, zlog_default->default_lvl); + return CMD_SUCCESS; +} + +DEFUN (config_log_stdout_level, + config_log_stdout_level_cmd, + "log stdout "LOG_LEVELS, + "Logging control\n" + "Set stdout logging level\n" + LOG_LEVEL_DESC) +{ + int level; + + if ((level = level_match(argv[0])) == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; + zlog_set_level (NULL, ZLOG_DEST_STDOUT, level); return CMD_SUCCESS; } DEFUN (no_config_log_stdout, no_config_log_stdout_cmd, - "no log stdout", + "no log stdout [LEVEL]", NO_STR "Logging control\n" - "Cancel logging to stdout\n") + "Cancel logging to stdout\n" + "Logging level\n") { - zlog_reset_flag (NULL, ZLOG_STDOUT); + zlog_set_level (NULL, ZLOG_DEST_STDOUT, ZLOG_DISABLED); return CMD_SUCCESS; } -DEFUN (config_log_file, - config_log_file_cmd, - "log file FILENAME", +DEFUN (config_log_monitor, + config_log_monitor_cmd, + "log monitor", "Logging control\n" - "Logging to file\n" - "Logging filename\n") + "Set terminal line (monitor) logging level\n") +{ + zlog_set_level (NULL, ZLOG_DEST_MONITOR, zlog_default->default_lvl); + return CMD_SUCCESS; +} + +DEFUN (config_log_monitor_level, + config_log_monitor_level_cmd, + "log monitor "LOG_LEVELS, + "Logging control\n" + "Set terminal line (monitor) logging level\n" + LOG_LEVEL_DESC) +{ + int level; + + if ((level = level_match(argv[0])) == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; + zlog_set_level (NULL, ZLOG_DEST_MONITOR, level); + return CMD_SUCCESS; +} + +DEFUN (no_config_log_monitor, + no_config_log_monitor_cmd, + "no log monitor [LEVEL]", + NO_STR + "Logging control\n" + "Disable terminal line (monitor) logging\n" + "Logging level\n") +{ + zlog_set_level (NULL, ZLOG_DEST_MONITOR, ZLOG_DISABLED); + return CMD_SUCCESS; +} + +static int +set_log_file(struct vty *vty, const char *fname, int loglevel) { int ret; char *p = NULL; const char *fullpath; /* Path detection. */ - if (! IS_DIRECTORY_SEP (*argv[0])) + if (! IS_DIRECTORY_SEP (*fname)) { char cwd[MAXPATHLEN+1]; cwd[MAXPATHLEN] = '\0'; @@ -3003,37 +3153,62 @@ DEFUN (config_log_file, return CMD_WARNING; } - if ( (p = XMALLOC (MTYPE_TMP, strlen (cwd) + strlen (argv[0]) + 2)) + if ( (p = XMALLOC (MTYPE_TMP, strlen (cwd) + strlen (fname) + 2)) == NULL) { zlog_err ("config_log_file: Unable to alloc mem!"); return CMD_WARNING; } - sprintf (p, "%s/%s", cwd, argv[0]); + sprintf (p, "%s/%s", cwd, fname); fullpath = p; } else - fullpath = argv[0]; + fullpath = fname; - ret = zlog_set_file (NULL, fullpath); + ret = zlog_set_file (NULL, fullpath, loglevel); if (p) XFREE (MTYPE_TMP, p); if (!ret) { - vty_out (vty, "can't open logfile %s\n", argv[0]); + vty_out (vty, "can't open logfile %s\n", fname); return CMD_WARNING; } if (host.logfile) XFREE (MTYPE_TMP, host.logfile); - host.logfile = XSTRDUP (MTYPE_TMP, argv[0]); + host.logfile = XSTRDUP (MTYPE_TMP, fname); return CMD_SUCCESS; } +DEFUN (config_log_file, + config_log_file_cmd, + "log file FILENAME", + "Logging control\n" + "Logging to file\n" + "Logging filename\n") +{ + return set_log_file(vty, argv[0], zlog_default->default_lvl); +} + +DEFUN (config_log_file_level, + config_log_file_level_cmd, + "log file FILENAME "LOG_LEVELS, + "Logging control\n" + "Logging to file\n" + "Logging filename\n" + LOG_LEVEL_DESC) +{ + int level; + + if ((level = level_match(argv[1])) == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; + return set_log_file(vty, argv[0], level); +} + DEFUN (no_config_log_file, no_config_log_file_cmd, "no log file [FILENAME]", @@ -3052,154 +3227,135 @@ DEFUN (no_config_log_file, return CMD_SUCCESS; } +ALIAS (no_config_log_file, + no_config_log_file_level_cmd, + "no log file FILENAME LEVEL", + NO_STR + "Logging control\n" + "Cancel logging to file\n" + "Logging file name\n" + "Logging level\n") + DEFUN (config_log_syslog, config_log_syslog_cmd, "log syslog", "Logging control\n" - "Logging goes to syslog\n") + "Set syslog logging level\n") { - zlog_set_flag (NULL, ZLOG_SYSLOG); - zlog_default->facility = LOG_DAEMON; + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl); return CMD_SUCCESS; } -DEFUN (config_log_syslog_facility, - config_log_syslog_facility_cmd, - "log syslog facility (kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7)", +DEFUN (config_log_syslog_level, + config_log_syslog_level_cmd, + "log syslog "LOG_LEVELS, "Logging control\n" - "Logging goes to syslog\n" - "Facility parameter for syslog messages\n" - "Kernel\n" - "User process\n" - "Mail system\n" - "System daemons\n" - "Authorization system\n" - "Syslog itself\n" - "Line printer system\n" - "USENET news\n" - "Unix-to-Unix copy system\n" - "Cron/at facility\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n") -{ - int facility = LOG_DAEMON; - - zlog_set_flag (NULL, ZLOG_SYSLOG); - - if (strncmp (argv[0], "kern", 1) == 0) - facility = LOG_KERN; - else if (strncmp (argv[0], "user", 2) == 0) - facility = LOG_USER; - else if (strncmp (argv[0], "mail", 1) == 0) - facility = LOG_MAIL; - else if (strncmp (argv[0], "daemon", 1) == 0) - facility = LOG_DAEMON; - else if (strncmp (argv[0], "auth", 1) == 0) - facility = LOG_AUTH; - else if (strncmp (argv[0], "syslog", 1) == 0) - facility = LOG_SYSLOG; - else if (strncmp (argv[0], "lpr", 2) == 0) - facility = LOG_LPR; - else if (strncmp (argv[0], "news", 1) == 0) - facility = LOG_NEWS; - else if (strncmp (argv[0], "uucp", 2) == 0) - facility = LOG_UUCP; - else if (strncmp (argv[0], "cron", 1) == 0) - facility = LOG_CRON; - else if (strncmp (argv[0], "local0", 6) == 0) - facility = LOG_LOCAL0; - else if (strncmp (argv[0], "local1", 6) == 0) - facility = LOG_LOCAL1; - else if (strncmp (argv[0], "local2", 6) == 0) - facility = LOG_LOCAL2; - else if (strncmp (argv[0], "local3", 6) == 0) - facility = LOG_LOCAL3; - else if (strncmp (argv[0], "local4", 6) == 0) - facility = LOG_LOCAL4; - else if (strncmp (argv[0], "local5", 6) == 0) - facility = LOG_LOCAL5; - else if (strncmp (argv[0], "local6", 6) == 0) - facility = LOG_LOCAL6; - else if (strncmp (argv[0], "local7", 6) == 0) - facility = LOG_LOCAL7; + "Set syslog logging level\n" + LOG_LEVEL_DESC) +{ + int level; - zlog_default->facility = facility; + if ((level = level_match(argv[0])) == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, level); + return CMD_SUCCESS; +} + +DEFUN_DEPRECATED (config_log_syslog_facility, + config_log_syslog_facility_cmd, + "log syslog facility "LOG_FACILITIES, + "Logging control\n" + "Logging goes to syslog\n" + "(Deprecated) Facility parameter for syslog messages\n" + LOG_FACILITY_DESC) +{ + int facility; + + if ((facility = facility_match(argv[0])) < 0) + return CMD_ERR_NO_MATCH; + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl); + zlog_default->facility = facility; return CMD_SUCCESS; } DEFUN (no_config_log_syslog, no_config_log_syslog_cmd, - "no log syslog", + "no log syslog [LEVEL]", NO_STR "Logging control\n" - "Cancel logging to syslog\n") + "Cancel logging to syslog\n" + "Logging level\n") { - zlog_reset_flag (NULL, ZLOG_SYSLOG); - zlog_default->facility = LOG_DAEMON; + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, ZLOG_DISABLED); return CMD_SUCCESS; } ALIAS (no_config_log_syslog, no_config_log_syslog_facility_cmd, - "no log syslog facility (kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7)", + "no log syslog facility "LOG_FACILITIES, NO_STR "Logging control\n" "Logging goes to syslog\n" "Facility parameter for syslog messages\n" - "Kernel\n" - "User process\n" - "Mail system\n" - "System daemons\n" - "Authorization system\n" - "Syslog itself\n" - "Line printer system\n" - "USENET news\n" - "Unix-to-Unix copy system\n" - "Cron/at facility\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n") - -DEFUN (config_log_trap, - config_log_trap_cmd, - "log trap (emergencies|alerts|critical|errors|warnings|notifications|informational|debugging)", + LOG_FACILITY_DESC) + +DEFUN (config_log_facility, + config_log_facility_cmd, + "log facility "LOG_FACILITIES, "Logging control\n" - "Limit logging to specifed level\n") + "Facility parameter for syslog messages\n" + LOG_FACILITY_DESC) { - int new_level ; - - for ( new_level = 0 ; zlog_priority [new_level] != NULL ; new_level ++ ) - { - if ( strcmp ( argv[0], zlog_priority [new_level] ) == 0 ) - /* found new logging level */ - { - zlog_default->maskpri = new_level; - return CMD_SUCCESS; - } - } - return CMD_ERR_NO_MATCH; + int facility; + + if ((facility = facility_match(argv[0])) < 0) + return CMD_ERR_NO_MATCH; + zlog_default->facility = facility; + return CMD_SUCCESS; } -DEFUN (no_config_log_trap, - no_config_log_trap_cmd, - "no log trap", +DEFUN (no_config_log_facility, + no_config_log_facility_cmd, + "no log facility [FACILITY]", NO_STR "Logging control\n" - "Permit all logging information\n") + "Reset syslog facility to default (daemon)\n" + "Syslog facility\n") +{ + zlog_default->facility = LOG_DAEMON; + return CMD_SUCCESS; +} + +DEFUN_DEPRECATED (config_log_trap, + config_log_trap_cmd, + "log trap "LOG_LEVELS, + "Logging control\n" + "(Deprecated) Set logging level and default for all destinations\n" + LOG_LEVEL_DESC) +{ + int new_level ; + int i; + + if ((new_level = level_match(argv[0])) == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; + + zlog_default->default_lvl = new_level; + for (i = 0; i < ZLOG_NUM_DESTS; i++) + if (zlog_default->maxlvl[i] != ZLOG_DISABLED) + zlog_default->maxlvl[i] = new_level; + return CMD_SUCCESS; +} + +DEFUN_DEPRECATED (no_config_log_trap, + no_config_log_trap_cmd, + "no log trap [LEVEL]", + NO_STR + "Logging control\n" + "Permit all logging information\n" + "Logging level\n") { - zlog_default->maskpri = LOG_DEBUG; + zlog_default->default_lvl = LOG_DEBUG; return CMD_SUCCESS; } @@ -3304,6 +3460,7 @@ cmd_init (int terminal) install_element (VIEW_NODE, &config_enable_cmd); install_element (VIEW_NODE, &config_terminal_length_cmd); install_element (VIEW_NODE, &config_terminal_no_length_cmd); + install_element (VIEW_NODE, &show_logging_cmd); } if (terminal) @@ -3320,6 +3477,8 @@ cmd_init (int terminal) { install_element (ENABLE_NODE, &config_terminal_length_cmd); install_element (ENABLE_NODE, &config_terminal_no_length_cmd); + install_element (ENABLE_NODE, &show_logging_cmd); + install_element (ENABLE_NODE, &config_logmsg_cmd); install_default (CONFIG_NODE); } @@ -3336,13 +3495,22 @@ cmd_init (int terminal) install_element (CONFIG_NODE, &no_enable_password_cmd); install_element (CONFIG_NODE, &config_log_stdout_cmd); + install_element (CONFIG_NODE, &config_log_stdout_level_cmd); install_element (CONFIG_NODE, &no_config_log_stdout_cmd); + install_element (CONFIG_NODE, &config_log_monitor_cmd); + install_element (CONFIG_NODE, &config_log_monitor_level_cmd); + install_element (CONFIG_NODE, &no_config_log_monitor_cmd); install_element (CONFIG_NODE, &config_log_file_cmd); + install_element (CONFIG_NODE, &config_log_file_level_cmd); install_element (CONFIG_NODE, &no_config_log_file_cmd); + install_element (CONFIG_NODE, &no_config_log_file_level_cmd); install_element (CONFIG_NODE, &config_log_syslog_cmd); + install_element (CONFIG_NODE, &config_log_syslog_level_cmd); install_element (CONFIG_NODE, &config_log_syslog_facility_cmd); install_element (CONFIG_NODE, &no_config_log_syslog_cmd); install_element (CONFIG_NODE, &no_config_log_syslog_facility_cmd); + install_element (CONFIG_NODE, &config_log_facility_cmd); + install_element (CONFIG_NODE, &no_config_log_facility_cmd); install_element (CONFIG_NODE, &config_log_trap_cmd); install_element (CONFIG_NODE, &no_config_log_trap_cmd); install_element (CONFIG_NODE, &config_log_record_priority_cmd); diff --git a/lib/command.h b/lib/command.h index 52cfded9..c8699e10 100644 --- a/lib/command.h +++ b/lib/command.h @@ -177,10 +177,10 @@ struct desc }; #define DEFUN_CMD_FUNC_DECL(funcname) \ - int funcname (struct cmd_element *, struct vty *, int, const char *[]); \ + static int funcname (struct cmd_element *, struct vty *, int, const char *[]); \ #define DEFUN_CMD_FUNC_TEXT(funcname) \ - int funcname \ + static int funcname \ (struct cmd_element *self, struct vty *vty, int argc, const char *argv[]) /* DEFUN for vty command interafce. Little bit hacky ;-). */ @@ -214,12 +214,24 @@ struct desc DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, daemon) \ DEFUN_CMD_FUNC_TEXT(funcname) +/* DEFUN + DEFSH with attributes */ +#define DEFUNSH_ATTR(daemon, funcname, cmdname, cmdstr, helpstr, attr) \ + DEFUN_CMD_FUNC_DECL(funcname) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, daemon) \ + DEFUN_CMD_FUNC_TEXT(funcname) + +#define DEFUNSH_HIDDEN(daemon, funcname, cmdname, cmdstr, helpstr) \ + DEFUNSH_ATTR (daemon, funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN) + +#define DEFUNSH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \ + DEFUNSH_ATTR (daemon, funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED) + /* ALIAS macro which define existing command's alias. */ #define ALIAS(funcname, cmdname, cmdstr, helpstr) \ DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) #define ALIAS_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \ - DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, daemon) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0) #define ALIAS_HIDDEN(funcname, cmdname, cmdstr, helpstr) \ DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, 0) @@ -227,6 +239,15 @@ struct desc #define ALIAS_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \ DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED, 0) +#define ALIAS_SH(daemon, funcname, cmdname, cmdstr, helpstr) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, daemon) + +#define ALIAS_SH_HIDDEN(daemon, funcname, cmdname, cmdstr, helpstr) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, daemon) + +#define ALIAS_SH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED, daemon) + #endif /* VTYSH_EXTRACT_PL */ /* Some macroes */ @@ -319,8 +340,6 @@ extern struct cmd_element config_exit_cmd; extern struct cmd_element config_quit_cmd; extern struct cmd_element config_help_cmd; extern struct cmd_element config_list_cmd; -int config_exit (struct cmd_element *, struct vty *, int, const char *[]); -int config_help (struct cmd_element *, struct vty *, int, const char *[]); char *host_config_file (); void host_config_set (char *); @@ -1,4 +1,7 @@ -/* Logging of zebra +/* + * $Id: log.c,v 1.17 2004/12/07 15:39:32 ajs Exp $ + * + * Logging of zebra * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro * * This file is part of GNU Zebra. @@ -104,12 +107,8 @@ vzlog (struct zlog *zl, int priority, const char *format, va_list args) return; } - /* only log this information if it has not been masked out */ - if ( priority > zl->maskpri ) - return ; - /* Syslog output */ - if (zl->flags & ZLOG_SYSLOG) + if (priority <= zl->maxlvl[ZLOG_DEST_SYSLOG]) { va_list ac; va_copy(ac, args); @@ -118,7 +117,7 @@ vzlog (struct zlog *zl, int priority, const char *format, va_list args) } /* File output. */ - if (zl->flags & ZLOG_FILE) + if ((priority <= zl->maxlvl[ZLOG_DEST_FILE]) && zl->fp) { va_list ac; time_print (zl->fp); @@ -133,7 +132,7 @@ vzlog (struct zlog *zl, int priority, const char *format, va_list args) } /* stdout output. */ - if (zl->flags & ZLOG_STDOUT) + if (priority <= zl->maxlvl[ZLOG_DEST_STDOUT]) { va_list ac; time_print (stdout); @@ -147,23 +146,10 @@ vzlog (struct zlog *zl, int priority, const char *format, va_list args) fflush (stdout); } - /* stderr output. */ - if (zl->flags & ZLOG_STDERR) - { - va_list ac; - time_print (stderr); - if (zl->record_priority) - fprintf (stderr, "%s: ", zlog_priority[priority]); - fprintf (stderr, "%s: ", zlog_proto_names[zl->protocol]); - va_copy(ac, args); - vfprintf (stderr, format, ac); - va_end(ac); - fprintf (stderr, "\n"); - fflush (stderr); - } - /* Terminal monitor. */ - vty_log (zlog_proto_names[zl->protocol], format, args); + if (priority <= zl->maxlvl[ZLOG_DEST_MONITOR]) + vty_log ((zl->record_priority ? zlog_priority[priority] : NULL), + zlog_proto_names[zl->protocol], format, args); } static char * @@ -297,26 +283,29 @@ zlog_signal(int signo, const char *action) if (s < buf+sizeof(buf)) *s++ = '\n'; + /* N.B. implicit priority is most severe */ +#define PRI LOG_EMERG + #define DUMP(FP) write(fileno(FP),buf,s-buf); if (!zlog_default) DUMP(stderr) else { - if ((zlog_default->flags & ZLOG_FILE) && zlog_default->fp) + if ((PRI <= zlog_default->maxlvl[ZLOG_DEST_FILE]) && zlog_default->fp) DUMP(zlog_default->fp) - if (zlog_default->flags & ZLOG_STDOUT) + if (PRI <= zlog_default->maxlvl[ZLOG_DEST_STDOUT]) DUMP(stdout) - if (zlog_default->flags & ZLOG_STDERR) - DUMP(stderr) - if (zlog_default->flags & ZLOG_SYSLOG) - { - *--s = '\0'; - syslog_sigsafe(LOG_ERR|zlog_default->facility,msgstart,s-msgstart); - } + /* Remove trailing '\n' for monitor and syslog */ + *--s = '\0'; + if (PRI <= zlog_default->maxlvl[ZLOG_DEST_MONITOR]) + vty_log_fixed(buf,s-buf); + if (PRI <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG]) + syslog_sigsafe(PRI|zlog_default->facility,msgstart,s-msgstart); } #undef DUMP - zlog_backtrace_sigsafe(LOG_ERR); + zlog_backtrace_sigsafe(PRI); +#undef PRI #undef LOC } @@ -332,10 +321,6 @@ zlog_backtrace_sigsafe(int priority) char *s; #define LOC s,buf+sizeof(buf)-s - /* only log this information if it has not been masked out */ - if (zlog_default && (priority > zlog_default->maskpri)) - return; - if (((size = backtrace(array,sizeof(array)/sizeof(array[0]))) <= 0) || ((size_t)size > sizeof(array)/sizeof(array[0]))) return; @@ -353,29 +338,34 @@ zlog_backtrace_sigsafe(int priority) DUMP(stderr) else { - if ((zlog_default->flags & ZLOG_FILE) && zlog_default->fp) + if ((priority <= zlog_default->maxlvl[ZLOG_DEST_FILE]) && + zlog_default->fp) DUMP(zlog_default->fp) - if (zlog_default->flags & ZLOG_STDOUT) + if (priority <= zlog_default->maxlvl[ZLOG_DEST_STDOUT]) DUMP(stdout) - if (zlog_default->flags & ZLOG_STDERR) - DUMP(stderr) - if (zlog_default->flags & ZLOG_SYSLOG) - { - int i; - *--s = '\0'; - syslog_sigsafe(priority|zlog_default->facility,buf,s-buf); - /* Just print the function addresses. */ - for (i = 0; i < size; i++) - { - s = buf; - s = str_append(LOC,"[bt "); - s = num_append(LOC,i); - s = str_append(LOC,"] 0x"); - s = hex_append(LOC,(u_long)(array[i])); - *s = '\0'; + /* Remove trailing '\n' for monitor and syslog */ + *--s = '\0'; + if (priority <= zlog_default->maxlvl[ZLOG_DEST_MONITOR]) + vty_log_fixed(buf,s-buf); + if (priority <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG]) + syslog_sigsafe(priority|zlog_default->facility,buf,s-buf); + { + int i; + /* Just print the function addresses. */ + for (i = 0; i < size; i++) + { + s = buf; + s = str_append(LOC,"[bt "); + s = num_append(LOC,i); + s = str_append(LOC,"] 0x"); + s = hex_append(LOC,(u_long)(array[i])); + *s = '\0'; + if (priority <= zlog_default->maxlvl[ZLOG_DEST_MONITOR]) + vty_log_fixed(buf,s-buf); + if (priority <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG]) syslog_sigsafe(priority|zlog_default->facility,buf,s-buf); - } - } + } + } } #undef DUMP #undef LOC @@ -476,29 +466,32 @@ _zlog_assert_failed (const char *assertion, const char *file, { zlog_err("Assertion `%s' failed in file %s, line %u, function %s", assertion,file,line,(function ? function : "?")); - zlog_backtrace(LOG_ERR); + zlog_backtrace(LOG_EMERG); abort(); } /* Open log stream */ struct zlog * -openzlog (const char *progname, int flags, zlog_proto_t protocol, +openzlog (const char *progname, zlog_proto_t protocol, int syslog_flags, int syslog_facility) { struct zlog *zl; + u_int i; - zl = XMALLOC(MTYPE_ZLOG, sizeof (struct zlog)); - memset (zl, 0, sizeof (struct zlog)); + zl = XCALLOC(MTYPE_ZLOG, sizeof (struct zlog)); zl->ident = progname; - zl->flags = flags; zl->protocol = protocol; zl->facility = syslog_facility; - zl->maskpri = LOG_DEBUG; - zl->record_priority = 0; zl->syslog_options = syslog_flags; + /* Set default logging levels. */ + for (i = 0; i < sizeof(zl->maxlvl)/sizeof(zl->maxlvl[0]); i++) + zl->maxlvl[i] = ZLOG_DISABLED; + zl->maxlvl[ZLOG_DEST_MONITOR] = LOG_DEBUG; + zl->default_lvl = LOG_DEBUG; + openlog (progname, syslog_flags, zl->facility); return zl; @@ -515,25 +508,16 @@ closezlog (struct zlog *zl) /* Called from command.c. */ void -zlog_set_flag (struct zlog *zl, int flags) +zlog_set_level (struct zlog *zl, zlog_dest_t dest, int log_level) { if (zl == NULL) zl = zlog_default; - zl->flags |= flags; -} - -void -zlog_reset_flag (struct zlog *zl, int flags) -{ - if (zl == NULL) - zl = zlog_default; - - zl->flags &= ~flags; + zl->maxlvl[dest] = log_level; } int -zlog_set_file (struct zlog *zl, const char *filename) +zlog_set_file (struct zlog *zl, const char *filename, int log_level) { FILE *fp; mode_t oldumask; @@ -548,16 +532,13 @@ zlog_set_file (struct zlog *zl, const char *filename) /* Open file. */ oldumask = umask (0777 & ~LOGFILE_MASK); fp = fopen (filename, "a"); - if (fp == NULL) - { - umask(oldumask); - return 0; - } umask(oldumask); + if (fp == NULL) + return 0; /* Set flags. */ zl->filename = strdup (filename); - zl->flags |= ZLOG_FILE; + zl->maxlvl[ZLOG_DEST_FILE] = log_level; zl->fp = fp; return 1; @@ -570,11 +551,10 @@ zlog_reset_file (struct zlog *zl) if (zl == NULL) zl = zlog_default; - zl->flags &= ~ZLOG_FILE; - if (zl->fp) fclose (zl->fp); zl->fp = NULL; + zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED; if (zl->filename) free (zl->filename); @@ -587,7 +567,7 @@ zlog_reset_file (struct zlog *zl) int zlog_rotate (struct zlog *zl) { - FILE *fp; + int level; if (zl == NULL) zl = zlog_default; @@ -595,20 +575,25 @@ zlog_rotate (struct zlog *zl) if (zl->fp) fclose (zl->fp); zl->fp = NULL; + level = zl->maxlvl[ZLOG_DEST_FILE]; + zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED; if (zl->filename) { mode_t oldumask; + int save_errno; oldumask = umask (0777 & ~LOGFILE_MASK); - fp = fopen (zl->filename, "a"); - if (fp == NULL) + zl->fp = fopen (zl->filename, "a"); + save_errno = errno; + umask(oldumask); + if (zl->fp == NULL) { - umask(oldumask); + zlog_err("Log rotate failed: cannot open file %s for append: %s", + zl->filename, safe_strerror(save_errno)); return -1; } - umask(oldumask); - zl->fp = fp; + zl->maxlvl[ZLOG_DEST_FILE] = level; } return 1; @@ -1,4 +1,7 @@ -/* Zebra logging funcions. +/* + * $Id: log.h,v 1.14 2004/12/07 15:39:32 ajs Exp $ + * + * Zebra logging funcions. * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro * * This file is part of GNU Zebra. @@ -40,12 +43,6 @@ * please use LOG_ERR instead. */ -#define ZLOG_NOLOG 0x00 -#define ZLOG_FILE 0x01 -#define ZLOG_SYSLOG 0x02 -#define ZLOG_STDOUT 0x04 -#define ZLOG_STDERR 0x08 - typedef enum { ZLOG_NONE, @@ -60,14 +57,28 @@ typedef enum ZLOG_MASC } zlog_proto_t; +/* If maxlvl is set to ZLOG_DISABLED, then no messages will be sent + to that logging destination. */ +#define ZLOG_DISABLED (LOG_EMERG-1) + +typedef enum +{ + ZLOG_DEST_SYSLOG = 0, + ZLOG_DEST_STDOUT, + ZLOG_DEST_MONITOR, + ZLOG_DEST_FILE +} zlog_dest_t; +#define ZLOG_NUM_DESTS (ZLOG_DEST_FILE+1) + struct zlog { const char *ident; /* daemon name (first arg to openlog) */ zlog_proto_t protocol; - int flags; /* mask indicating which destinations to log to */ + int maxlvl[ZLOG_NUM_DESTS]; /* maximum priority to send to associated + logging destination */ + int default_lvl; /* maxlvl to use if none is specified */ FILE *fp; char *filename; - int maskpri; /* discard messages with priority > maskpri */ int facility; /* as per syslog facility */ int record_priority; /* should messages logged through stdio include the priority of the message? */ @@ -85,7 +96,8 @@ struct message extern struct zlog *zlog_default; /* Open zlog function */ -struct zlog *openzlog (const char *, int, zlog_proto_t, int, int); +struct zlog *openzlog (const char *progname, zlog_proto_t protocol, + int syslog_options, int syslog_facility); /* Close zlog function. */ void closezlog (struct zlog *zl); @@ -114,12 +126,15 @@ void plog_info (struct zlog *, const char *format, ...); void plog_notice (struct zlog *, const char *format, ...); void plog_debug (struct zlog *, const char *format, ...); -/* Set zlog flags. */ -void zlog_set_flag (struct zlog *zl, int flags); -void zlog_reset_flag (struct zlog *zl, int flags); +/* Set logging level for the given destination. If the log_level + argument is ZLOG_DISABLED, then the destination is disabled. + This function should not be used for file logging (use zlog_set_file + or zlog_reset_file instead). */ +void zlog_set_level (struct zlog *zl, zlog_dest_t, int log_level); -/* Set zlog filename. */ -int zlog_set_file (struct zlog *zl, const char *filename); +/* Set logging to the given filename at the specified level. */ +int zlog_set_file (struct zlog *zl, const char *filename, int log_level); +/* Disable file logging. */ int zlog_reset_file (struct zlog *zl); /* Rotate log. */ @@ -132,6 +147,7 @@ const char *lookup (struct message *, int); const char *mes_lookup (struct message *meslist, int max, int index); extern const char *zlog_priority[]; +extern const char *zlog_proto_names[]; /* Safe version of strerror -- never returns NULL. */ extern const char *safe_strerror(int errnum); @@ -147,4 +163,40 @@ extern void zlog_backtrace(int priority); up the state of zlog file pointers. */ extern void zlog_backtrace_sigsafe(int priority); +/* Defines for use in command construction: */ + +#define LOG_LEVELS "(emergencies|alerts|critical|errors|warnings|notifications|informational|debugging)" + +#define LOG_LEVEL_DESC \ + "System is unusable\n" \ + "Immediate action needed\n" \ + "Critical conditions\n" \ + "Error conditions\n" \ + "Warning conditions\n" \ + "Normal but significant conditions\n" \ + "Informational messages\n" \ + "Debugging messages\n" + +#define LOG_FACILITIES "(kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7)" + +#define LOG_FACILITY_DESC \ + "Kernel\n" \ + "User process\n" \ + "Mail system\n" \ + "System daemons\n" \ + "Authorization system\n" \ + "Syslog itself\n" \ + "Line printer system\n" \ + "USENET news\n" \ + "Unix-to-Unix copy system\n" \ + "Cron/at facility\n" \ + "Local use\n" \ + "Local use\n" \ + "Local use\n" \ + "Local use\n" \ + "Local use\n" \ + "Local use\n" \ + "Local use\n" \ + "Local use\n" + #endif /* _ZEBRA_LOG_H */ @@ -148,14 +148,17 @@ vty_out (struct vty *vty, const char *format, ...) } static int -vty_log_out (struct vty *vty, const char *proto_str, const char *format, - va_list va) +vty_log_out (struct vty *vty, const char *level, const char *proto_str, + const char *format, va_list va) { int len; char buf[1024]; - snprintf (buf, sizeof buf, "%s: ", proto_str); - write (vty->fd, buf, strlen (proto_str) + 2); + if (level) + snprintf (buf, sizeof buf, "%s: %s: ", level, proto_str); + else + snprintf (buf, sizeof buf, "%s: ", proto_str); + write (vty->fd, buf, strlen (buf)); len = vsnprintf (buf, sizeof buf, format, va); if (len < 0) @@ -602,7 +605,7 @@ static void vty_down_level (struct vty *vty) { vty_out (vty, "%s", VTY_NEWLINE); - config_exit (NULL, vty, 0, NULL); + (*config_exit_cmd.func)(NULL, vty, 0, NULL); vty_prompt (vty); vty->cp = 0; } @@ -2273,7 +2276,8 @@ vty_read_config (char *config_file, /* Small utility function which output log to the VTY. */ void -vty_log (const char *proto_str, const char *format, va_list va) +vty_log (const char *level, const char *proto_str, + const char *format, va_list va) { unsigned int i; struct vty *vty; @@ -2284,11 +2288,29 @@ vty_log (const char *proto_str, const char *format, va_list va) { va_list ac; va_copy(ac, va); - vty_log_out (vty, proto_str, format, ac); + vty_log_out (vty, level, proto_str, format, ac); va_end(ac); } } +/* Async-signal-safe version of vty_log for fixed strings. */ +void +vty_log_fixed (const char *buf, size_t len) +{ + unsigned int i; + + for (i = 0; i < vector_max (vtyvec); i++) + { + struct vty *vty; + if ((vty = vector_slot (vtyvec, i)) != NULL) + if (vty->monitor) + { + write(vty->fd, buf, len); + write(vty->fd, "\r\n", 2); + } + } +} + int vty_config_lock (struct vty *vty) { @@ -180,11 +180,15 @@ void vty_time_print (struct vty *, int); void vty_serv_sock (const char *, unsigned short, const char *); void vty_close (struct vty *); char *vty_get_cwd (void); -void vty_log (const char *, const char *, va_list); +void vty_log (const char *level, const char *proto, const char *fmt, va_list); int vty_config_lock (struct vty *); int vty_config_unlock (struct vty *); int vty_shell (struct vty *); int vty_shell_serv (struct vty *); void vty_hello (struct vty *); +/* Send a fixed-size message to all vty terminal monitors; this should be + an async-signal-safe function. */ +extern void vty_log_fixed (const char *buf, size_t len); + #endif /* _ZEBRA_VTY_H */ |