diff options
author | Chris Hall (GMCH) <chris.hall@highwayman.com> | 2009-12-02 17:11:35 +0000 |
---|---|---|
committer | Chris Hall (GMCH) <chris.hall@highwayman.com> | 2009-12-02 17:11:35 +0000 |
commit | 8364e12dd2737cf77a4e3ead7c3d7bb9cc684010 (patch) | |
tree | bbcf4243478504ad6d5c6c9183ba7a81a8118b7a | |
parent | db597018b8c47208e4139b75fdcd798505695ea8 (diff) | |
parent | 1e2ad204c4c72cb3ffa73864154c96047da8cad4 (diff) | |
download | quagga-8364e12dd2737cf77a4e3ead7c3d7bb9cc684010.tar.bz2 quagga-8364e12dd2737cf77a4e3ead7c3d7bb9cc684010.tar.xz |
Merge branch 'pthreads' of /git/quagga.euro-ix into pthreads
-rw-r--r-- | lib/command.c | 109 | ||||
-rw-r--r-- | lib/filter.c | 2 | ||||
-rw-r--r-- | lib/log.c | 553 | ||||
-rw-r--r-- | lib/log.h | 16 | ||||
-rw-r--r-- | lib/log_r.h | 32 | ||||
-rw-r--r-- | lib/plist.c | 2 | ||||
-rw-r--r-- | lib/privs.c | 201 | ||||
-rw-r--r-- | lib/routemap.c | 2 | ||||
-rw-r--r-- | lib/vty.c | 5 | ||||
-rw-r--r-- | tests/test-privs.c | 28 |
10 files changed, 710 insertions, 240 deletions
diff --git a/lib/command.c b/lib/command.c index 60880f49..efce3fa0 100644 --- a/lib/command.c +++ b/lib/command.c @@ -548,57 +548,57 @@ config_write_host (struct vty *vty) vty_out (vty, "enable password %s%s", host.enable, VTY_NEWLINE); } - if (zlog_default->default_lvl != LOG_DEBUG) + if (zlog_get_default_lvl(NULL) != LOG_DEBUG) { vty_out (vty, "! N.B. The 'log trap' command is deprecated.%s", VTY_NEWLINE); vty_out (vty, "log trap %s%s", - zlog_priority[zlog_default->default_lvl], VTY_NEWLINE); + zlog_priority[zlog_get_default_lvl(NULL)], VTY_NEWLINE); } - if (host.logfile && (zlog_default->maxlvl[ZLOG_DEST_FILE] != ZLOG_DISABLED)) + if (host.logfile && (zlog_get_maxlvl(NULL, ZLOG_DEST_FILE) != ZLOG_DISABLED)) { vty_out (vty, "log file %s", host.logfile); - if (zlog_default->maxlvl[ZLOG_DEST_FILE] != zlog_default->default_lvl) + if (zlog_get_maxlvl(NULL, ZLOG_DEST_FILE) != zlog_get_default_lvl(NULL)) vty_out (vty, " %s", - zlog_priority[zlog_default->maxlvl[ZLOG_DEST_FILE]]); + zlog_priority[zlog_get_maxlvl(NULL, ZLOG_DEST_FILE)]); vty_out (vty, "%s", VTY_NEWLINE); } - if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != ZLOG_DISABLED) + if (zlog_get_maxlvl(NULL, ZLOG_DEST_STDOUT) != ZLOG_DISABLED) { vty_out (vty, "log stdout"); - if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != zlog_default->default_lvl) + if (zlog_get_maxlvl(NULL, ZLOG_DEST_STDOUT) != zlog_get_default_lvl(NULL)) vty_out (vty, " %s", - zlog_priority[zlog_default->maxlvl[ZLOG_DEST_STDOUT]]); + zlog_priority[zlog_get_maxlvl(NULL, ZLOG_DEST_STDOUT)]); vty_out (vty, "%s", VTY_NEWLINE); } - if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED) + if (zlog_get_maxlvl(NULL, 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) + else if (zlog_get_maxlvl(NULL, ZLOG_DEST_MONITOR) != zlog_get_default_lvl(NULL)) vty_out(vty,"log monitor %s%s", - zlog_priority[zlog_default->maxlvl[ZLOG_DEST_MONITOR]],VTY_NEWLINE); + zlog_priority[zlog_get_maxlvl(NULL, ZLOG_DEST_MONITOR)],VTY_NEWLINE); - if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED) + if (zlog_get_maxlvl(NULL, ZLOG_DEST_SYSLOG) != ZLOG_DISABLED) { vty_out (vty, "log syslog"); - if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != zlog_default->default_lvl) + if (zlog_get_maxlvl(NULL, ZLOG_DEST_SYSLOG) != zlog_get_default_lvl(NULL)) vty_out (vty, " %s", - zlog_priority[zlog_default->maxlvl[ZLOG_DEST_SYSLOG]]); + zlog_priority[zlog_get_maxlvl(NULL, ZLOG_DEST_SYSLOG)]); vty_out (vty, "%s", VTY_NEWLINE); } - if (zlog_default->facility != LOG_DAEMON) + if (zlog_get_facility(NULL) != LOG_DAEMON) vty_out (vty, "log facility %s%s", - facility_name(zlog_default->facility), VTY_NEWLINE); + facility_name(zlog_get_facility(NULL)), VTY_NEWLINE); - if (zlog_default->record_priority == 1) + if (zlog_get_record_priority(NULL) == 1) vty_out (vty, "log record-priority%s", VTY_NEWLINE); - if (zlog_default->timestamp_precision > 0) + if (zlog_get_timestamp_precision(NULL) > 0) vty_out (vty, "log timestamp precision %d%s", - zlog_default->timestamp_precision, VTY_NEWLINE); + zlog_get_timestamp_precision(NULL), VTY_NEWLINE); if (host.advanced) vty_out (vty, "service advanced-vty%s", VTY_NEWLINE); @@ -3060,49 +3060,51 @@ DEFUN (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) + if (zlog_get_maxlvl(NULL, 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); + zlog_priority[zlog_get_maxlvl(NULL, ZLOG_DEST_SYSLOG)], + facility_name(zlog_get_facility(NULL)), zlog_get_ident(NULL)); vty_out (vty, "%s", VTY_NEWLINE); vty_out (vty, "Stdout logging: "); - if (zl->maxlvl[ZLOG_DEST_STDOUT] == ZLOG_DISABLED) + if (zlog_get_maxlvl(NULL, ZLOG_DEST_STDOUT) == ZLOG_DISABLED) vty_out (vty, "disabled"); else vty_out (vty, "level %s", - zlog_priority[zl->maxlvl[ZLOG_DEST_STDOUT]]); + zlog_priority[zlog_get_maxlvl(NULL, ZLOG_DEST_STDOUT)]); vty_out (vty, "%s", VTY_NEWLINE); vty_out (vty, "Monitor logging: "); - if (zl->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED) + if (zlog_get_maxlvl(NULL, ZLOG_DEST_MONITOR) == ZLOG_DISABLED) vty_out (vty, "disabled"); else vty_out (vty, "level %s", - zlog_priority[zl->maxlvl[ZLOG_DEST_MONITOR]]); + zlog_priority[zlog_get_maxlvl(NULL, ZLOG_DEST_MONITOR)]); vty_out (vty, "%s", VTY_NEWLINE); vty_out (vty, "File logging: "); - if ((zl->maxlvl[ZLOG_DEST_FILE] == ZLOG_DISABLED) || - !zl->fp) + if ((zlog_get_maxlvl(NULL, ZLOG_DEST_FILE) == ZLOG_DISABLED) || + !zlog_is_file(NULL)) vty_out (vty, "disabled"); else - vty_out (vty, "level %s, filename %s", - zlog_priority[zl->maxlvl[ZLOG_DEST_FILE]], - zl->filename); + { + char * filename = zlog_get_filename(NULL); + vty_out (vty, "level %s, filename %s", + zlog_priority[zlog_get_maxlvl(NULL, ZLOG_DEST_FILE)], + filename); + free(filename); + } vty_out (vty, "%s", VTY_NEWLINE); vty_out (vty, "Protocol name: %s%s", - zlog_proto_names[zl->protocol], VTY_NEWLINE); + zlog_get_proto_name(NULL), VTY_NEWLINE); vty_out (vty, "Record priority: %s%s", - (zl->record_priority ? "enabled" : "disabled"), VTY_NEWLINE); + (zlog_get_record_priority(NULL) ? "enabled" : "disabled"), VTY_NEWLINE); vty_out (vty, "Timestamp precision: %d%s", - zl->timestamp_precision, VTY_NEWLINE); + zlog_get_timestamp_precision(NULL), VTY_NEWLINE); return CMD_SUCCESS; } @@ -3113,7 +3115,7 @@ DEFUN (config_log_stdout, "Logging control\n" "Set stdout logging level\n") { - zlog_set_level (NULL, ZLOG_DEST_STDOUT, zlog_default->default_lvl); + zlog_set_level (NULL, ZLOG_DEST_STDOUT, zlog_get_default_lvl(NULL)); return CMD_SUCCESS; } @@ -3150,7 +3152,7 @@ DEFUN (config_log_monitor, "Logging control\n" "Set terminal line (monitor) logging level\n") { - zlog_set_level (NULL, ZLOG_DEST_MONITOR, zlog_default->default_lvl); + zlog_set_level (NULL, ZLOG_DEST_MONITOR, zlog_get_default_lvl(NULL)); return CMD_SUCCESS; } @@ -3238,7 +3240,7 @@ DEFUN (config_log_file, "Logging to file\n" "Logging filename\n") { - return set_log_file(vty, argv[0], zlog_default->default_lvl); + return set_log_file(vty, argv[0], zlog_get_default_lvl(NULL)); } DEFUN (config_log_file_level, @@ -3289,7 +3291,7 @@ DEFUN (config_log_syslog, "Logging control\n" "Set syslog logging level\n") { - zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl); + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_get_default_lvl(NULL)); return CMD_SUCCESS; } @@ -3321,8 +3323,8 @@ DEFUN_DEPRECATED (config_log_syslog_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; + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_get_default_lvl(NULL)); + zlog_set_facility(NULL, facility); return CMD_SUCCESS; } @@ -3358,7 +3360,7 @@ DEFUN (config_log_facility, if ((facility = facility_match(argv[0])) < 0) return CMD_ERR_NO_MATCH; - zlog_default->facility = facility; + zlog_set_facility(NULL, facility); return CMD_SUCCESS; } @@ -3370,7 +3372,7 @@ DEFUN (no_config_log_facility, "Reset syslog facility to default (daemon)\n" "Syslog facility\n") { - zlog_default->facility = LOG_DAEMON; + zlog_set_facility(NULL, LOG_DAEMON); return CMD_SUCCESS; } @@ -3387,10 +3389,7 @@ DEFUN_DEPRECATED (config_log_trap, 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; + zlog_set_default_lvl_dest (NULL, new_level); return CMD_SUCCESS; } @@ -3402,7 +3401,7 @@ DEFUN_DEPRECATED (no_config_log_trap, "Permit all logging information\n" "Logging level\n") { - zlog_default->default_lvl = LOG_DEBUG; + zlog_set_default_lvl(NULL, LOG_DEBUG); return CMD_SUCCESS; } @@ -3412,7 +3411,7 @@ DEFUN (config_log_record_priority, "Logging control\n" "Log the priority of the message within the message\n") { - zlog_default->record_priority = 1 ; + zlog_set_record_priority(NULL, 1) ; return CMD_SUCCESS; } @@ -3423,7 +3422,7 @@ DEFUN (no_config_log_record_priority, "Logging control\n" "Do not log the priority of the message within the message\n") { - zlog_default->record_priority = 0 ; + zlog_set_record_priority(NULL, 0) ; return CMD_SUCCESS; } @@ -3435,6 +3434,8 @@ DEFUN (config_log_timestamp_precision, "Set the timestamp precision\n" "Number of subsecond digits\n") { + int timestamp_precision; + if (argc != 1) { vty_out (vty, "Insufficient arguments%s", VTY_NEWLINE); @@ -3442,7 +3443,9 @@ DEFUN (config_log_timestamp_precision, } VTY_GET_INTEGER_RANGE("Timestamp Precision", - zlog_default->timestamp_precision, argv[0], 0, 6); + timestamp_precision, argv[0], 0, 6); + zlog_set_timestamp_precision(NULL, timestamp_precision); + return CMD_SUCCESS; } @@ -3454,7 +3457,7 @@ DEFUN (no_config_log_timestamp_precision, "Timestamp configuration\n" "Reset the timestamp precision to the default value of 0\n") { - zlog_default->timestamp_precision = 0 ; + zlog_set_timestamp_precision(NULL, 0); return CMD_SUCCESS; } diff --git a/lib/filter.c b/lib/filter.c index af8d587f..57109854 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -1584,7 +1584,7 @@ filter_show (struct vty *vty, const char *name, afi_t afi) /* Print the name of the protocol */ if (zlog_default) vty_out (vty, "%s:%s", - zlog_proto_names[zlog_default->protocol], VTY_NEWLINE); + zlog_get_proto_name(NULL), VTY_NEWLINE); for (access = master->num.head; access; access = access->next) { @@ -34,6 +34,26 @@ #ifdef HAVE_UCONTEXT_H #include <ucontext.h> #endif +#include <pthread.h> +#include <assert.h> + +/* logging needs to be pthread safe */ +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +#if 0 +static int lock_count = 0; +#define LOCK if(lock_count++ != 0){printf("Lock count: %d\n", lock_count);assert(0);} +#define UNLOCK if(--lock_count != 0){printf("Unlock count: %d\n", lock_count);assert(0);} +#elif defined(NDEBUG) +#define LOCK pthread_mutex_lock(&mutex); +#define UNLOCK pthread_mutex_unlock(&mutex); +#else +#define LOCK if(pthread_mutex_lock(&mutex)!= 0){assert(0);}; +#define UNLOCK if(pthread_mutex_unlock(&mutex)!= 0){assert(0);}; +#endif + +/* prototypes */ +static int do_reset_file (struct zlog *zl); +static size_t do_timestamp(int timestamp_precision, char *buf, size_t buflen); static int logfile_fd = -1; /* Used in signal handler. */ @@ -74,6 +94,16 @@ const char *zlog_priority[] = size_t quagga_timestamp(int timestamp_precision, char *buf, size_t buflen) { + size_t result; + LOCK + result = do_timestamp(timestamp_precision, buf, buflen); + UNLOCK + return result; +} + +static size_t +do_timestamp(int timestamp_precision, char *buf, size_t buflen) +{ static struct { time_t last; size_t len; @@ -81,6 +111,8 @@ quagga_timestamp(int timestamp_precision, char *buf, size_t buflen) } cache; struct timeval clock; + size_t result = 0; + /* would it be sufficient to use global 'recent_time' here? I fear not... */ gettimeofday(&clock, NULL); @@ -122,14 +154,19 @@ quagga_timestamp(int timestamp_precision, char *buf, size_t buflen) } while (--prec > 0); *p = '.'; - return cache.len+1+timestamp_precision; + result = cache.len+1+timestamp_precision; } - buf[cache.len] = '\0'; - return cache.len; + else + { + buf[cache.len] = '\0'; + result = cache.len; + } + } else { + if (buflen > 0) + buf[0] = '\0'; } - if (buflen > 0) - buf[0] = '\0'; - return 0; + + return result; } /* Utility routine for current time printing. */ @@ -138,7 +175,7 @@ time_print(FILE *fp, struct timestamp_control *ctl) { if (!ctl->already_rendered) { - ctl->len = quagga_timestamp(ctl->precision, ctl->buf, sizeof(ctl->buf)); + ctl->len = do_timestamp(ctl->precision, ctl->buf, sizeof(ctl->buf)); ctl->already_rendered = 1; } fprintf(fp, "%s ", ctl->buf); @@ -152,6 +189,8 @@ vzlog (struct zlog *zl, int priority, const char *format, va_list args) struct timestamp_control tsctl; tsctl.already_rendered = 0; + LOCK + /* If zlog is not specified, use default one. */ if (zl == NULL) zl = zlog_default; @@ -165,55 +204,65 @@ vzlog (struct zlog *zl, int priority, const char *format, va_list args) vfprintf (stderr, format, args); fprintf (stderr, "\n"); fflush (stderr); - - /* In this case we return at here. */ - return; } - tsctl.precision = zl->timestamp_precision; - - /* Syslog output */ - if (priority <= zl->maxlvl[ZLOG_DEST_SYSLOG]) + else { - va_list ac; - va_copy(ac, args); - vsyslog (priority|zlog_default->facility, format, ac); - va_end(ac); - } + tsctl.precision = zl->timestamp_precision; - /* File output. */ - if ((priority <= zl->maxlvl[ZLOG_DEST_FILE]) && zl->fp) - { - va_list ac; - time_print (zl->fp, &tsctl); - if (zl->record_priority) - fprintf (zl->fp, "%s: ", zlog_priority[priority]); - fprintf (zl->fp, "%s: ", zlog_proto_names[zl->protocol]); - va_copy(ac, args); - vfprintf (zl->fp, format, ac); - va_end(ac); - fprintf (zl->fp, "\n"); - fflush (zl->fp); - } + /* Syslog output */ + if (priority <= zl->maxlvl[ZLOG_DEST_SYSLOG]) + { + va_list ac; + va_copy(ac, args); + vsyslog (priority|zlog_default->facility, format, ac); + va_end(ac); + } - /* stdout output. */ - if (priority <= zl->maxlvl[ZLOG_DEST_STDOUT]) - { - va_list ac; - time_print (stdout, &tsctl); - if (zl->record_priority) - fprintf (stdout, "%s: ", zlog_priority[priority]); - fprintf (stdout, "%s: ", zlog_proto_names[zl->protocol]); - va_copy(ac, args); - vfprintf (stdout, format, ac); - va_end(ac); - fprintf (stdout, "\n"); - fflush (stdout); - } + /* File output. */ + if ((priority <= zl->maxlvl[ZLOG_DEST_FILE]) && zl->fp) + { + va_list ac; + time_print (zl->fp, &tsctl); + if (zl->record_priority) + fprintf (zl->fp, "%s: ", zlog_priority[priority]); + fprintf (zl->fp, "%s: ", zlog_proto_names[zl->protocol]); + va_copy(ac, args); + vfprintf (zl->fp, format, ac); + va_end(ac); + fprintf (zl->fp, "\n"); + fflush (zl->fp); + } - /* Terminal monitor. */ - if (priority <= zl->maxlvl[ZLOG_DEST_MONITOR]) - vty_log ((zl->record_priority ? zlog_priority[priority] : NULL), - zlog_proto_names[zl->protocol], format, &tsctl, args); + /* stdout output. */ + if (priority <= zl->maxlvl[ZLOG_DEST_STDOUT]) + { + va_list ac; + time_print (stdout, &tsctl); + if (zl->record_priority) + fprintf (stdout, "%s: ", zlog_priority[priority]); + fprintf (stdout, "%s: ", zlog_proto_names[zl->protocol]); + va_copy(ac, args); + vfprintf (stdout, format, ac); + va_end(ac); + fprintf (stdout, "\n"); + fflush (stdout); + } + + /* Terminal monitor. */ + if (priority <= zl->maxlvl[ZLOG_DEST_MONITOR]) + { + /* must be unlocked as vty handles it's own pthread stuff + * extract what we need from the zlog first + */ + const char *priority_name = (zl->record_priority ? zlog_priority[priority] : NULL); + const char *proto_name = zlog_proto_names[zl->protocol]; + + UNLOCK + vty_log (priority_name, proto_name, format, &tsctl, args); + return; + } + } + UNLOCK } static char * @@ -608,12 +657,16 @@ _zlog_assert_failed (const char *assertion, const char *file, unsigned int line, const char *function) { /* Force fallback file logging? */ + LOCK if (zlog_default && !zlog_default->fp && ((logfile_fd = open_crashlog()) >= 0) && ((zlog_default->fp = fdopen(logfile_fd, "w")) != NULL)) zlog_default->maxlvl[ZLOG_DEST_FILE] = LOG_ERR; + UNLOCK + zlog(NULL, LOG_CRIT, "Assertion `%s' failed in file %s, line %u, function %s", assertion,file,line,(function ? function : "?")); + zlog_backtrace(LOG_CRIT); abort(); } @@ -648,22 +701,33 @@ openzlog (const char *progname, zlog_proto_t protocol, void closezlog (struct zlog *zl) { + LOCK + closelog(); if (zl->fp != NULL) fclose (zl->fp); XFREE (MTYPE_ZLOG, zl); + + UNLOCK } /* Called from command.c. */ void zlog_set_level (struct zlog *zl, zlog_dest_t dest, int log_level) { + LOCK + if (zl == NULL) zl = zlog_default; - zl->maxlvl[dest] = log_level; + if (zl != NULL) + { + zl->maxlvl[dest] = log_level; + } + + UNLOCK } int @@ -671,46 +735,68 @@ zlog_set_file (struct zlog *zl, const char *filename, int log_level) { FILE *fp; mode_t oldumask; + int result = 1; + + LOCK /* There is opend file. */ - zlog_reset_file (zl); + do_reset_file (zl); /* Set default zl. */ if (zl == NULL) zl = zlog_default; - /* Open file. */ - oldumask = umask (0777 & ~LOGFILE_MASK); - fp = fopen (filename, "a"); - umask(oldumask); - if (fp == NULL) - return 0; - - /* Set flags. */ - zl->filename = strdup (filename); - zl->maxlvl[ZLOG_DEST_FILE] = log_level; - zl->fp = fp; - logfile_fd = fileno(fp); + if (zl != NULL) + { + /* Open file. */ + oldumask = umask (0777 & ~LOGFILE_MASK); + fp = fopen (filename, "a"); + umask(oldumask); + if (fp == NULL) + result = 0; + else + { + /* Set flags. */ + zl->filename = strdup (filename); + zl->maxlvl[ZLOG_DEST_FILE] = log_level; + zl->fp = fp; + logfile_fd = fileno(fp); + } + } - return 1; + UNLOCK + return result; } /* Reset opend file. */ int zlog_reset_file (struct zlog *zl) { + int result; + LOCK + result = do_reset_file(zl); + UNLOCK + return result; +} + +static int +do_reset_file (struct zlog *zl) + { if (zl == NULL) zl = zlog_default; - if (zl->fp) - fclose (zl->fp); - zl->fp = NULL; - logfile_fd = -1; - zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED; - - if (zl->filename) - free (zl->filename); - zl->filename = NULL; + if (zl != NULL) + { + if (zl->fp) + fclose (zl->fp); + zl->fp = NULL; + logfile_fd = -1; + zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED; + + if (zl->filename) + free (zl->filename); + zl->filename = NULL; + } return 1; } @@ -721,38 +807,309 @@ zlog_rotate (struct zlog *zl) { int level; + LOCK + if (zl == NULL) zl = zlog_default; - if (zl->fp) - fclose (zl->fp); - zl->fp = NULL; - logfile_fd = -1; - level = zl->maxlvl[ZLOG_DEST_FILE]; - zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED; + if (zl != NULL) + { + if (zl->fp) + fclose (zl->fp); + zl->fp = NULL; + logfile_fd = -1; + 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); + zl->fp = fopen (zl->filename, "a"); + save_errno = errno; + umask(oldumask); + if (zl->fp == NULL) + { + /* can't call logging while locked */ + char *fname = strdup(zl->filename); + UNLOCK + zlog_err("Log rotate failed: cannot open file %s for append: %s", + fname, safe_strerror(save_errno)); + free(fname); + return -1; + } + else + { + logfile_fd = fileno(zl->fp); + zl->maxlvl[ZLOG_DEST_FILE] = level; + } + } + } + UNLOCK + return 1; +} + +int +zlog_get_default_lvl (struct zlog *zl) +{ + int result = LOG_DEBUG; - if (zl->filename) + LOCK + + if (zl == NULL) + zl = zlog_default; + + if (zl != NULL) { - mode_t oldumask; - int save_errno; + result = zl->default_lvl; + } - oldumask = umask (0777 & ~LOGFILE_MASK); - zl->fp = fopen (zl->filename, "a"); - save_errno = errno; - umask(oldumask); - if (zl->fp == NULL) - { - zlog_err("Log rotate failed: cannot open file %s for append: %s", - zl->filename, safe_strerror(save_errno)); - return -1; - } - logfile_fd = fileno(zl->fp); - zl->maxlvl[ZLOG_DEST_FILE] = level; + UNLOCK + return result; +} + +void +zlog_set_default_lvl (struct zlog *zl, int level) +{ + LOCK + + if (zl == NULL) + zl = zlog_default; + + if (zl != NULL) + { + zl->default_lvl = level; } - return 1; + UNLOCK } - + +/* Set logging level and default for all destinations */ +void +zlog_set_default_lvl_dest (struct zlog *zl, int level) +{ + int i; + + LOCK + + if (zl == NULL) + zl = zlog_default; + + if (zl != NULL) + { + zl->default_lvl = level; + + for (i = 0; i < ZLOG_NUM_DESTS; i++) + if (zl->maxlvl[i] != ZLOG_DISABLED) + zl->maxlvl[i] = level; + } + + UNLOCK +} + +int +zlog_get_maxlvl (struct zlog *zl, zlog_dest_t dest) +{ + int result = ZLOG_DISABLED; + + LOCK + + if (zl == NULL) + zl = zlog_default; + + if (zl != NULL) + { + result = zl->maxlvl[dest]; + } + + UNLOCK + return result; +} + +int +zlog_get_facility (struct zlog *zl) +{ + int result = LOG_DAEMON; + + LOCK + + if (zl == NULL) + zl = zlog_default; + + if (zl != NULL) + { + result = zl->facility; + } + + UNLOCK + return result; +} + +void +zlog_set_facility (struct zlog *zl, int facility) +{ + LOCK + + if (zl == NULL) + zl = zlog_default; + + if (zl != NULL) + { + zl->facility = facility; + } + + UNLOCK +} + +int +zlog_get_record_priority (struct zlog *zl) +{ + int result = 0; + + LOCK + + if (zl == NULL) + zl = zlog_default; + + if (zl != NULL) + { + result = zl->record_priority; + } + + UNLOCK + return result; +} + +void +zlog_set_record_priority (struct zlog *zl, int record_priority) +{ + LOCK + + if (zl == NULL) + zl = zlog_default; + + if (zl != NULL) + { + zl->record_priority = record_priority; + } + UNLOCK +} + +int +zlog_get_timestamp_precision (struct zlog *zl) +{ + int result = 0; + + LOCK + + if (zl == NULL) + zl = zlog_default; + + if (zl != NULL) + { + result = zl->timestamp_precision; + } + UNLOCK + return result; +} + +void +zlog_set_timestamp_precision (struct zlog *zl, int timestamp_precision) +{ + LOCK + + if (zl == NULL) + zl = zlog_default; + + if (zl != NULL) + { + zl->timestamp_precision = timestamp_precision; + } + + UNLOCK +} + +/* returns name of ZLOG_NONE if no zlog given and no default set */ +const char * +zlog_get_proto_name (struct zlog *zl) +{ + zlog_proto_t protocol = ZLOG_NONE; + + LOCK + + if (zl == NULL) + zl = zlog_default; + + if (zl != NULL) + { + protocol = zl->protocol; + } + + UNLOCK + return zlog_proto_names[protocol]; +} + +/* caller must free result */ +char * +zlog_get_filename (struct zlog *zl) +{ + char * result = NULL; + + LOCK + + if (zl == NULL) + zl = zlog_default; + + if (zl != NULL && zl->filename != NULL) + { + result = strdup(zl->filename); + } + + UNLOCK + return result; +} + +const char * +zlog_get_ident (struct zlog *zl) +{ + const char * result = NULL; + + LOCK + + if (zl == NULL) + zl = zlog_default; + + if (zl != NULL) + { + result = zl->ident; + } + + UNLOCK + return result; +} + +/* logging to a file? */ +int +zlog_is_file (struct zlog *zl) +{ + int result = 0; + + LOCK + + if (zl == NULL) + zl = zlog_default; + + if (zl != NULL) + { + result = (zl->fp != NULL); + } + + UNLOCK + return result; +} + /* Message lookup function. */ const char * lookup (const struct message *mes, int key) @@ -147,6 +147,22 @@ extern int zlog_reset_file (struct zlog *zl); /* Rotate log. */ extern int zlog_rotate (struct zlog *); +/* getters & setters */ +extern int zlog_get_default_lvl (struct zlog *zl); +extern void zlog_set_default_lvl (struct zlog *zl, int level); +extern void zlog_set_default_lvl_dest (struct zlog *zl, int level); +extern int zlog_get_maxlvl (struct zlog *zl, zlog_dest_t dest); +extern int zlog_get_facility (struct zlog *zl); +extern void zlog_set_facility (struct zlog *zl, int facility); +extern int zlog_get_record_priority (struct zlog *zl); +extern void zlog_set_record_priority (struct zlog *zl, int record_priority); +extern int zlog_get_timestamp_precision (struct zlog *zl); +extern void zlog_set_timestamp_precision (struct zlog *zl, int timestamp_precision); +extern const char * zlog_get_ident (struct zlog *zl); +extern char * zlog_get_filename (struct zlog *zl); +extern int zlog_is_file (struct zlog *zl); +extern const char * zlog_get_proto_name (struct zlog *zl); + /* For hackey massage lookup and check */ #define LOOKUP(x, y) mes_lookup(x, x ## _max, y, "(no item found)") diff --git a/lib/log_r.h b/lib/log_r.h deleted file mode 100644 index eafae3c7..00000000 --- a/lib/log_r.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * $Id$ - * - * Zebra logging functions for pthreads - * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro - * - * This file is part of GNU Zebra. - * - * GNU Zebra is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * GNU Zebra is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef _ZEBRA_LOG_R_H -#define _ZEBRA_LOG_R_H - -#include <log.h> - - - -#endif /* _ZEBRA_LOG_R_H */ diff --git a/lib/plist.c b/lib/plist.c index 10d5e31c..b01c48f6 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -1378,7 +1378,7 @@ vty_show_prefix_entry (struct vty *vty, struct prefix_list *plist, { /* Print the name of the protocol */ if (zlog_default) - vty_out (vty, "%s: ", zlog_proto_names[zlog_default->protocol]); + vty_out (vty, "%s: ", zlog_get_proto_name(NULL)); if (dtype == normal_display) { diff --git a/lib/privs.c b/lib/privs.c index 69606f57..a6592bea 100644 --- a/lib/privs.c +++ b/lib/privs.c @@ -25,6 +25,21 @@ #include "log.h" #include "privs.h" #include "memory.h" +#include <pthread.h> + +/* needs to be pthread safe */ +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +#if 0 +static int lock_count = 0; +#define LOCK if(lock_count++ != 0){printf("Lock count: %d\n", lock_count);assert(0);} +#define UNLOCK if(--lock_count != 0){printf("Unlock count: %d\n", lock_count);assert(0);} +#elif defined(NDEBUG) +#define LOCK pthread_mutex_lock(&mutex); +#define UNLOCK pthread_mutex_unlock(&mutex); +#else +#define LOCK if(pthread_mutex_lock(&mutex)!= 0){assert(0);}; +#define UNLOCK if(pthread_mutex_unlock(&mutex)!= 0){assert(0);}; +#endif #ifdef HAVE_CAPABILITIES /* sort out some generic internal types for: @@ -61,6 +76,7 @@ typedef priv_set_t *pstorage_t; * zprivs_terminate is called and the NULL handler is installed. */ static zebra_privs_current_t zprivs_null_state = ZPRIVS_RAISED; +static int raise_count = 0; /* keep raised until all pthreads have lowered */ /* internal privileges state */ static struct _zprivs_t @@ -187,25 +203,42 @@ int zprivs_change_caps (zebra_privs_ops_t op) { cap_flag_value_t cflag; - + int result = 0; + int change = 0; + + LOCK + /* should be no possibility of being called without valid caps */ assert (zprivs_state.syscaps_p && zprivs_state.caps); if (! (zprivs_state.syscaps_p && zprivs_state.caps)) - exit (1); - + { + UNLOCK + exit (1); + } + if (op == ZPRIVS_RAISE) - cflag = CAP_SET; + { + cflag = CAP_SET; + change = (raise_count++ == 0); + } else if (op == ZPRIVS_LOWER) - cflag = CAP_CLEAR; + { + cflag = CAP_CLEAR; + change = (--raise_count == 0); + } else - return -1; + { + result = -1; + } - if ( !cap_set_flag (zprivs_state.caps, CAP_EFFECTIVE, + if ( change && !cap_set_flag (zprivs_state.caps, CAP_EFFECTIVE, zprivs_state.syscaps_p->num, zprivs_state.syscaps_p->caps, cflag)) - return cap_set_proc (zprivs_state.caps); - return -1; + result = cap_set_proc (zprivs_state.caps); + + UNLOCK + return result; } zebra_privs_current_t @@ -213,11 +246,17 @@ zprivs_state_caps (void) { int i; cap_flag_value_t val; + zebra_privs_current_t result = ZPRIVS_LOWERED; + + LOCK /* should be no possibility of being called without valid caps */ assert (zprivs_state.syscaps_p && zprivs_state.caps); if (! (zprivs_state.syscaps_p && zprivs_state.caps)) - exit (1); + { + UNLOCK + exit (1); + } for (i=0; i < zprivs_state.syscaps_p->num; i++) { @@ -226,12 +265,18 @@ zprivs_state_caps (void) { zlog_warn ("zprivs_state_caps: could not cap_get_flag, %s", safe_strerror (errno) ); - return ZPRIVS_UNKNOWN; + result = ZPRIVS_UNKNOWN; + break; } if (val == CAP_SET) - return ZPRIVS_RAISED; + { + result = ZPRIVS_RAISED; + break; + } } - return ZPRIVS_LOWERED; + + UNLOCK + return result; } static void @@ -376,12 +421,16 @@ zcaps2sys (zebra_capabilities_t *zcaps, int num) int zprivs_change_caps (zebra_privs_ops_t op) { + int result = 0; + LOCK + /* should be no possibility of being called without valid caps */ assert (zprivs_state.syscaps_p); if (!zprivs_state.syscaps_p) { fprintf (stderr, "%s: Eek, missing caps!", __func__); + UNLOCK exit (1); } @@ -389,49 +438,66 @@ zprivs_change_caps (zebra_privs_ops_t op) * to lower: just clear the working effective set */ if (op == ZPRIVS_RAISE) - priv_copyset (zprivs_state.syscaps_p, zprivs_state.caps); + { + if (raise_count++ == 0) + { + priv_copyset (zprivs_state.syscaps_p, zprivs_state.caps); + if (setppriv (PRIV_SET, PRIV_EFFECTIVE, zprivs_state.caps) != 0) + result = -1; + } + } else if (op == ZPRIVS_LOWER) - priv_emptyset (zprivs_state.caps); + { + if (--raise_count == 0) + { + priv_emptyset (zprivs_state.caps); + if (setppriv (PRIV_SET, PRIV_EFFECTIVE, zprivs_state.caps) != 0) + result = -1; + } + } else - return -1; + result = -1; - if (setppriv (PRIV_SET, PRIV_EFFECTIVE, zprivs_state.caps) != 0) - return -1; + UNLOCK - return 0; + return result; } /* Retrieve current privilege state, is it RAISED or LOWERED? */ zebra_privs_current_t zprivs_state_caps (void) { - zebra_privs_current_t result; + zebra_privs_current_t result = ZPRIVS_UNKNOWN; pset_t *effective; + LOCK + if ( (effective = priv_allocset()) == NULL) { fprintf (stderr, "%s: failed to get priv_allocset! %s\n", __func__, safe_strerror (errno)); - return ZPRIVS_UNKNOWN; - } - - if (getppriv (PRIV_EFFECTIVE, effective)) - { - fprintf (stderr, "%s: failed to get state! %s\n", __func__, - safe_strerror (errno)); - result = ZPRIVS_UNKNOWN; } else { - if (priv_isemptyset (effective) == B_TRUE) - result = ZPRIVS_LOWERED; + + if (getppriv (PRIV_EFFECTIVE, effective)) + { + fprintf (stderr, "%s: failed to get state! %s\n", __func__, + safe_strerror (errno)); + } else - result = ZPRIVS_RAISED; + { + if (priv_isemptyset (effective) == B_TRUE) + result = ZPRIVS_LOWERED; + else + result = ZPRIVS_RAISED; + } + + if (effective) + priv_freeset (effective); } - if (effective) - priv_freeset (effective); - + UNLOCK return result; } @@ -560,19 +626,42 @@ zprivs_caps_terminate (void) int zprivs_change_uid (zebra_privs_ops_t op) { + int result = 0; + + LOCK if (op == ZPRIVS_RAISE) - return seteuid (zprivs_state.zsuid); + { + if (raise_count++ == 0) + { + result = seteuid (zprivs_state.zsuid); + } + } else if (op == ZPRIVS_LOWER) - return seteuid (zprivs_state.zuid); + { + if (--raise_count == 0) + { + result = seteuid (zprivs_state.zuid); + } + } else - return -1; + { + result = -1; + } + + UNLOCK + return result; } zebra_privs_current_t zprivs_state_uid (void) { - return ( (zprivs_state.zuid == geteuid()) ? ZPRIVS_LOWERED : ZPRIVS_RAISED); + zebra_privs_current_t result; + + LOCK + result = ( (zprivs_state.zuid == geteuid()) ? ZPRIVS_LOWERED : ZPRIVS_RAISED); + UNLOCK + return result; } int @@ -584,7 +673,12 @@ zprivs_change_null (zebra_privs_ops_t op) zebra_privs_current_t zprivs_state_null (void) { - return zprivs_null_state; + int result; + + LOCK + result = zprivs_null_state; + UNLOCK + return result; } void @@ -599,12 +693,15 @@ zprivs_init(struct zebra_privs_t *zprivs) exit (1); } + LOCK + /* NULL privs */ if (! (zprivs->user || zprivs->group || zprivs->cap_num_p || zprivs->cap_num_i) ) { zprivs->change = zprivs_change_null; zprivs->current_state = zprivs_state_null; + UNLOCK return; } @@ -619,6 +716,7 @@ zprivs_init(struct zebra_privs_t *zprivs) /* cant use log.h here as it depends on vty */ fprintf (stderr, "privs_init: could not lookup user %s\n", zprivs->user); + UNLOCK exit (1); } } @@ -635,6 +733,7 @@ zprivs_init(struct zebra_privs_t *zprivs) { fprintf (stderr, "privs_init: could not setgroups, %s\n", safe_strerror (errno) ); + UNLOCK exit (1); } } @@ -642,6 +741,7 @@ zprivs_init(struct zebra_privs_t *zprivs) { fprintf (stderr, "privs_init: could not lookup vty group %s\n", zprivs->vty_group); + UNLOCK exit (1); } } @@ -656,6 +756,7 @@ zprivs_init(struct zebra_privs_t *zprivs) { fprintf (stderr, "privs_init: could not lookup group %s\n", zprivs->group); + UNLOCK exit (1); } /* change group now, forever. uid we do later */ @@ -663,6 +764,7 @@ zprivs_init(struct zebra_privs_t *zprivs) { fprintf (stderr, "zprivs_init: could not setregid, %s\n", safe_strerror (errno) ); + UNLOCK exit (1); } } @@ -671,7 +773,7 @@ zprivs_init(struct zebra_privs_t *zprivs) zprivs_caps_init (zprivs); #else /* !HAVE_CAPABILITIES */ /* we dont have caps. we'll need to maintain rid and saved uid - * and change euid back to saved uid (who we presume has all neccessary + * and change euid back to saved uid (who we presume has all necessary * privileges) whenever we are asked to raise our privileges. * * This is not worth that much security wise, but all we can do. @@ -683,6 +785,7 @@ zprivs_init(struct zebra_privs_t *zprivs) { fprintf (stderr, "privs_init (uid): could not setreuid, %s\n", safe_strerror (errno)); + UNLOCK exit (1); } } @@ -690,6 +793,8 @@ zprivs_init(struct zebra_privs_t *zprivs) zprivs->change = zprivs_change_uid; zprivs->current_state = zprivs_state_uid; #endif /* HAVE_CAPABILITIES */ + + UNLOCK } void @@ -701,6 +806,8 @@ zprivs_terminate (struct zebra_privs_t *zprivs) exit (0); } + LOCK + #ifdef HAVE_CAPABILITIES zprivs_caps_terminate(); #else /* !HAVE_CAPABILITIES */ @@ -710,6 +817,7 @@ zprivs_terminate (struct zebra_privs_t *zprivs) { fprintf (stderr, "privs_terminate: could not setreuid, %s", safe_strerror (errno) ); + UNLOCK exit (1); } } @@ -718,20 +826,25 @@ zprivs_terminate (struct zebra_privs_t *zprivs) zprivs->change = zprivs_change_null; zprivs->current_state = zprivs_state_null; zprivs_null_state = ZPRIVS_LOWERED; + raise_count = 0; + + UNLOCK return; } void zprivs_get_ids(struct zprivs_ids_t *ids) { + LOCK - ids->uid_priv = getuid(); - (zprivs_state.zuid) ? (ids->uid_normal = zprivs_state.zuid) + ids->uid_priv = getuid(); + (zprivs_state.zuid) ? (ids->uid_normal = zprivs_state.zuid) : (ids->uid_normal = -1); - (zprivs_state.zgid) ? (ids->gid_normal = zprivs_state.zgid) + (zprivs_state.zgid) ? (ids->gid_normal = zprivs_state.zgid) : (ids->gid_normal = -1); - (zprivs_state.vtygrp) ? (ids->gid_vty = zprivs_state.vtygrp) + (zprivs_state.vtygrp) ? (ids->gid_vty = zprivs_state.vtygrp) : (ids->gid_vty = -1); + UNLOCK return; } diff --git a/lib/routemap.c b/lib/routemap.c index 4f4e6d62..2dfa5a46 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -207,7 +207,7 @@ vty_show_route_map_entry (struct vty *vty, struct route_map *map) /* Print the name of the protocol */ if (zlog_default) - vty_out (vty, "%s:%s", zlog_proto_names[zlog_default->protocol], + vty_out (vty, "%s:%s", zlog_get_proto_name(NULL), VTY_NEWLINE); for (index = map->head; index; index = index->next) @@ -440,10 +440,7 @@ vty_command (struct vty *vty, char *buf) ret = cmd_execute_command (vline, vty, NULL, 0); /* Get the name of the protocol if any */ - if (zlog_default) - protocolname = zlog_proto_names[zlog_default->protocol]; - else - protocolname = zlog_proto_names[ZLOG_NONE]; + protocolname = zlog_get_proto_name(NULL); #ifdef CONSUMED_TIME_CHECK GETRUSAGE(&after); diff --git a/tests/test-privs.c b/tests/test-privs.c index a888ea0f..568fe79a 100644 --- a/tests/test-privs.c +++ b/tests/test-privs.c @@ -125,26 +125,42 @@ main (int argc, char **argv) #define PRIV_STATE() \ ((test_privs.current_state() == ZPRIVS_RAISED) ? "Raised" : "Lowered") - printf ("%s\n", PRIV_STATE()); + printf ("Initial state: %s\n", PRIV_STATE()); + + test_privs.change(ZPRIVS_RAISE); + printf ("Change raise: state: %s\n", PRIV_STATE()); + test_privs.change(ZPRIVS_RAISE); + printf ("Change raise: state: %s\n", PRIV_STATE()); - printf ("%s\n", PRIV_STATE()); test_privs.change(ZPRIVS_LOWER); + printf ("Change lower: state: %s\n", PRIV_STATE()); + + test_privs.change(ZPRIVS_LOWER); + printf ("Change lower: state: %s\n", PRIV_STATE()); - printf ("%s\n", PRIV_STATE()); + printf ("Get ids %s\n", PRIV_STATE()); zprivs_get_ids (&ids); /* terminate privileges */ zprivs_terminate(&test_privs); /* but these should continue to work... */ - printf ("%s\n", PRIV_STATE()); + printf ("Terminated state: %s\n", PRIV_STATE()); + + test_privs.change(ZPRIVS_RAISE); + printf ("Change raise: state: %s\n", PRIV_STATE()); + test_privs.change(ZPRIVS_RAISE); + printf ("Change raise: state: %s\n", PRIV_STATE()); - printf ("%s\n", PRIV_STATE()); test_privs.change(ZPRIVS_LOWER); + printf ("Change lower: state: %s\n", PRIV_STATE()); + + test_privs.change(ZPRIVS_LOWER); + printf ("Change lower: state: %s\n", PRIV_STATE()); - printf ("%s\n", PRIV_STATE()); + printf ("Get ids %s\n", PRIV_STATE()); zprivs_get_ids (&ids); printf ("terminating\n"); |