From b34b3e2817950c6cccbc9cf2fce8cc137f433a88 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 18 May 2012 03:08:40 +0200 Subject: New logging facilities --- src/config.c | 87 +++++++++++++++++--- src/config.l | 3 + src/config.y | 68 ++++++++++++---- src/fastd.c | 41 +++++++++- src/fastd.h | 121 ++++++++++++++++++++-------- src/printf.c | 259 ++++++++++++++++++++--------------------------------------- src/types.h | 12 +-- 7 files changed, 349 insertions(+), 242 deletions(-) diff --git a/src/config.c b/src/config.c index d9397cc..a77c258 100644 --- a/src/config.c +++ b/src/config.c @@ -51,7 +51,10 @@ extern const fastd_method fastd_method_xsalsa20_poly1305; static void default_config(fastd_config *conf) { - conf->loglevel = LOG_INFO; + conf->log_stderr_level = -1; + conf->log_syslog_level = -1; + conf->log_syslog_ident = strdup("fastd"); + conf->log_files = NULL; conf->keepalive_interval = 60; conf->peer_stale_time = 300; @@ -135,6 +138,43 @@ bool fastd_config_method(fastd_context *ctx, fastd_config *conf, const char *nam return true; } +bool fastd_config_add_log_file(fastd_context *ctx, fastd_config *conf, const char *name, int level) { + char *name2 = strdup(name); + char *name3 = strdup(name); + + char *dir = dirname(name2); + char *base = basename(name3); + + char *oldcwd = get_current_dir_name(); + + if (!chdir(dir)) { + char *logdir = get_current_dir_name(); + + fastd_log_file *file = malloc(sizeof(fastd_log_file)); + file->filename = malloc(strlen(logdir) + 1 + strlen(base) + 1); + + strcpy(file->filename, logdir); + strcat(file->filename, "/"); + strcat(file->filename, base); + + file->level = level; + + file->next = conf->log_files; + conf->log_files = file; + + if(chdir(oldcwd)) + pr_error(ctx, "can't chdir to `%s': %s", oldcwd, strerror(errno)); + } + else { + pr_error(ctx, "change from directory `%s' to `%s' failed: %s", oldcwd, dir, strerror(errno)); + } + + + free(name2); + free(name3); + return true; +} + static void read_peer_dir(fastd_context *ctx, fastd_config *conf, const char *dir) { DIR *dirh = opendir("."); @@ -334,7 +374,9 @@ static void count_peers(fastd_context *ctx, fastd_config *conf) { OPTION(usage, "--help" OR "-h", "Shows this help text") \ OPTION(version, "--version" OR "-v", "Shows the fastd version") \ OPTION(option_daemon, "--daemon" OR "-d", "Runs fastd in the background") \ - OPTION_ARG(option_log_level, "--log-level", "error|warn|info|verbose|debug", "Sets the log level; default is info") \ + OPTION_ARG(option_log_level, "--log-level", "error|warn|info|verbose|debug", "Sets the stderr log level; default is info, if no alternative log destination ist configured") \ + OPTION_ARG(option_syslog_level, "--syslog-level", "error|warn|info|verbose|debug", "Sets the log level for syslog output; default is not to use syslog") \ + OPTION_ARG(option_syslog_ident, "--syslog-ident", "", "Sets the syslog identification; default is 'fastd'") \ OPTION_ARG(option_config, "--config" OR "-c", "", "Loads a config file") \ OPTION_ARG(option_config_peer, "--config-peer", "", "Loads a config file for a single peer") \ OPTION_ARG(option_config_peer_dir, "--config-peer-dir", "", "Loads all files from a directory as peer configs") \ @@ -390,24 +432,38 @@ static void version(fastd_context *ctx, fastd_config *conf) { exit(0); } - -static void option_log_level(fastd_context *ctx, fastd_config *conf, const char *arg) { +static int parse_log_level(fastd_context *ctx, const char *arg) { if (!strcmp(arg, "fatal")) - conf->loglevel = LOG_FATAL; + return LOG_CRIT; else if (!strcmp(arg, "error")) - conf->loglevel = LOG_ERROR; + return LOG_ERR; else if (!strcmp(arg, "warn")) - conf->loglevel = LOG_WARN; + return LOG_WARNING; else if (!strcmp(arg, "info")) - conf->loglevel = LOG_INFO; + return LOG_NOTICE; else if (!strcmp(arg, "verbose")) - conf->loglevel = LOG_VERBOSE; + return LOG_INFO; else if (!strcmp(arg, "debug")) - conf->loglevel = LOG_DEBUG; + return LOG_DEBUG; else exit_error(ctx, "invalid log level `%s'", arg); } + + +static void option_log_level(fastd_context *ctx, fastd_config *conf, const char *arg) { + conf->log_stderr_level = parse_log_level(ctx, arg); +} + +static void option_syslog_level(fastd_context *ctx, fastd_config *conf, const char *arg) { + conf->log_syslog_level = parse_log_level(ctx, arg); +} + +static void option_syslog_ident(fastd_context *ctx, fastd_config *conf, const char *arg) { + free(conf->log_syslog_ident); + conf->log_syslog_ident = strdup(arg); +} + static void option_config(fastd_context *ctx, fastd_config *conf, const char *arg) { if (!strcmp(arg, "-")) arg = NULL; @@ -599,6 +655,9 @@ void fastd_configure(fastd_context *ctx, fastd_config *conf, int argc, char *con exit_error(ctx, "config error: unknown option `%s'; see --help for usage", argv[i]); } + if (conf->log_stderr_level < 0 && conf->log_syslog_level < 0 && !conf->log_files) + conf->log_stderr_level = FASTD_DEFAULT_LOG_LEVEL; + if (conf->generate_key || conf->show_key) return; @@ -725,6 +784,13 @@ void fastd_config_release(fastd_context *ctx, fastd_config *conf) { fastd_string_stack_free(conf->peer_dirs); + while (conf->log_files) { + fastd_log_file *next = conf->log_files->next; + free(conf->log_files->filename); + free(conf->log_files); + conf->log_files = next; + } + free(conf->ifname); free(conf->secret); free(conf->on_up); @@ -736,4 +802,5 @@ void fastd_config_release(fastd_context *ctx, fastd_config *conf) { free(conf->on_disestablish); free(conf->on_disestablish_dir); free(conf->protocol_config); + free(conf->log_syslog_ident); } diff --git a/src/config.l b/src/config.l index 963a05b..4f7dd7f 100644 --- a/src/config.l +++ b/src/config.l @@ -80,6 +80,9 @@ peers { UPDATE_LOCATION; return TOK_PEERS; } from { UPDATE_LOCATION; return TOK_FROM; } log { UPDATE_LOCATION; return TOK_LOG; } level { UPDATE_LOCATION; return TOK_LEVEL; } +syslog { UPDATE_LOCATION; return TOK_SYSLOG; } +stderr { UPDATE_LOCATION; return TOK_STDERR; } +to { UPDATE_LOCATION; return TOK_TO; } fatal { UPDATE_LOCATION; return TOK_FATAL; } error { UPDATE_LOCATION; return TOK_ERROR; } warn { UPDATE_LOCATION; return TOK_WARN; } diff --git a/src/config.y b/src/config.y index e283630..ec2aabe 100644 --- a/src/config.y +++ b/src/config.y @@ -81,6 +81,9 @@ %token TOK_FROM %token TOK_LOG %token TOK_LEVEL +%token TOK_SYSLOG +%token TOK_STDERR +%token TOK_TO %token TOK_FATAL %token TOK_ERROR %token TOK_WARN @@ -107,6 +110,8 @@ } +%type maybe_log_level +%type log_level %type port %type boolean %type maybe_port @@ -139,15 +144,40 @@ statement: TOK_LOG log ';' | TOK_INCLUDE include ';' ; -log: TOK_LEVEL log_level +log: TOK_LEVEL log_level { + conf->log_stderr_level = $2; + } + | TOK_TO TOK_STDERR maybe_log_level { + conf->log_stderr_level = $3; + } + | TOK_TO TOK_SYSLOG maybe_log_level { + conf->log_syslog_level = $3; + } + | TOK_TO TOK_SYSLOG TOK_AS TOK_STRING maybe_log_level { + free(conf->log_syslog_ident); + conf->log_syslog_ident = strdup($4->str); + + conf->log_syslog_level = $5; + } + | TOK_TO TOK_STRING maybe_log_level { + if (!fastd_config_add_log_file(ctx, conf, $2->str, $3)) { + fastd_config_error(&@$, ctx, conf, filename, depth, "unable to set log file"); + YYERROR; + } + } ; -log_level: TOK_FATAL { conf->loglevel = LOG_FATAL; } - | TOK_ERROR { conf->loglevel = LOG_ERROR; } - | TOK_WARN { conf->loglevel = LOG_WARN; } - | TOK_INFO { conf->loglevel = LOG_INFO; } - | TOK_VERBOSE { conf->loglevel = LOG_VERBOSE; } - | TOK_DEBUG { conf->loglevel = LOG_DEBUG; } +maybe_log_level: + TOK_LEVEL log_level { $$ = $2; } + | { $$ = FASTD_DEFAULT_LOG_LEVEL; } + ; + +log_level: TOK_FATAL { $$ = LOG_CRIT; } + | TOK_ERROR { $$ = LOG_ERR; } + | TOK_WARN { $$ = LOG_WARNING; } + | TOK_INFO { $$ = LOG_NOTICE; } + | TOK_VERBOSE { $$ = LOG_INFO; } + | TOK_DEBUG { $$ = LOG_DEBUG; } ; interface: TOK_STRING { free(conf->ifname); conf->ifname = strdup($1->str); } @@ -197,7 +227,7 @@ method: TOK_STRING { secret: TOK_STRING { free(conf->secret); conf->secret = strdup($1->str); } ; -on_up: TOK_STRING { +on_up: TOK_STRING { free(conf->on_up); free(conf->on_up_dir); @@ -206,7 +236,7 @@ on_up: TOK_STRING { } ; -on_down: TOK_STRING { +on_down: TOK_STRING { free(conf->on_down); free(conf->on_down_dir); @@ -215,7 +245,7 @@ on_down: TOK_STRING { } ; -on_establish: TOK_STRING { +on_establish: TOK_STRING { free(conf->on_establish); free(conf->on_establish_dir); @@ -224,7 +254,7 @@ on_establish: TOK_STRING { } ; -on_disestablish: TOK_STRING { +on_disestablish: TOK_STRING { free(conf->on_disestablish); free(conf->on_disestablish_dir); @@ -273,13 +303,15 @@ peer_remote: TOK_ADDR port { } ; -peer_key: TOK_STRING { free(conf->peers->key); conf->peers->key = strdup($1->str); } +peer_key: TOK_STRING { + free(conf->peers->key); conf->peers->key = strdup($1->str); + } ; -peer_include: TOK_STRING { - if (!fastd_read_config(ctx, conf, $1->str, true, depth)) - YYERROR; - } +peer_include: TOK_STRING { + if (!fastd_read_config(ctx, conf, $1->str, true, depth)) + YYERROR; + } ; @@ -308,7 +340,9 @@ maybe_port: port { $$ = $1; } | { $$ = 0; } ; -maybe_as: TOK_AS TOK_STRING { $$ = $2; } +maybe_as: TOK_AS TOK_STRING { + $$ = $2; + } | { $$ = NULL; } ; diff --git a/src/fastd.c b/src/fastd.c index e270a26..a73c73d 100644 --- a/src/fastd.c +++ b/src/fastd.c @@ -85,6 +85,35 @@ static void init_pipes(fastd_context *ctx) { ctx->resolvewfd = pipefd[1]; } +static void init_log(fastd_context *ctx) { + if (ctx->conf->log_syslog_level >= 0) + openlog(ctx->conf->log_syslog_ident, LOG_PID, LOG_DAEMON); + + fastd_log_file *config; + for (config = ctx->conf->log_files; config; config = config->next) { + fastd_log_fd *file = malloc(sizeof(fastd_log_fd)); + + file->config = config; + file->fd = open(config->filename, O_WRONLY|O_APPEND|O_CREAT, 0600); + + file->next = ctx->log_files; + ctx->log_files = file; + } +} + +static void close_log(fastd_context *ctx) { + while (ctx->log_files) { + fastd_log_fd *next = ctx->log_files->next; + + close(ctx->log_files->fd); + free(ctx->log_files); + + ctx->log_files = next; + } + + closelog(); +} + static void init_sockets(fastd_context *ctx) { struct sockaddr_in addr_in = ctx->conf->bind_addr_in; struct sockaddr_in6 addr_in6 = ctx->conf->bind_addr_in6; @@ -586,7 +615,7 @@ static void handle_input(fastd_context *ctx) { update_time(ctx); if (fds[0].revents & POLLIN) - handle_tun(ctx); + handle_tun(ctx); if (fds[1].revents & POLLIN) handle_socket(ctx, ctx->sockfd); if (fds[2].revents & POLLIN) @@ -652,6 +681,8 @@ int main(int argc, char *argv[]) { fastd_configure(&ctx, &conf, argc, argv); ctx.conf = &conf; + init_log(&ctx); + if (conf.generate_key) { conf.protocol->generate_key(&ctx); exit(0); @@ -672,7 +703,7 @@ int main(int argc, char *argv[]) { init_peers(&ctx); if (conf.daemon) { - if (daemon(0, 1) < 0) + if (daemon(1, 1) < 0) exit_errno(&ctx, "daemon"); } @@ -690,7 +721,12 @@ int main(int argc, char *argv[]) { if (sighup) { sighup = false; + + close_log(&ctx); + init_log(&ctx); + fastd_reconfigure(&ctx, &conf); + } pthread_sigmask(SIG_SETMASK, &oldset, NULL); @@ -706,6 +742,7 @@ int main(int argc, char *argv[]) { free(ctx.protocol_state); free(ctx.eth_addr); + close_log(&ctx); fastd_config_release(&ctx, &conf); return 0; diff --git a/src/fastd.h b/src/fastd.h index 564b9c5..80f012b 100644 --- a/src/fastd.h +++ b/src/fastd.h @@ -33,12 +33,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -107,8 +109,25 @@ struct _fastd_resolve_return { fastd_peer_address addr; }; +struct _fastd_log_file { + fastd_log_file *next; + + int level; + char *filename; +}; + +struct _fastd_log_fd { + fastd_log_fd *next; + + fastd_log_file *config; + int fd; +}; + struct _fastd_config { - fastd_loglevel loglevel; + int log_stderr_level; + int log_syslog_level; + char *log_syslog_ident; + fastd_log_file *log_files; unsigned keepalive_interval; unsigned peer_stale_time; @@ -163,6 +182,8 @@ struct _fastd_config { struct _fastd_context { const fastd_config *conf; + fastd_log_fd *log_files; + char *ifname; struct timespec now; @@ -198,13 +219,14 @@ void fastd_handle_receive(fastd_context *ctx, fastd_peer *peer, fastd_buffer buf void fastd_resolve_peer(fastd_context *ctx, const fastd_peer_config *peer); -void fastd_printf(const fastd_context *ctx, const char *format, ...); +int fastd_vsnprintf(const fastd_context *ctx, char *buffer, size_t size, const char *format, va_list ap); void fastd_read_peer_dir(fastd_context *ctx, fastd_config *conf, const char *dir); bool fastd_read_config(fastd_context *ctx, fastd_config *conf, const char *filename, bool peer_config, int depth); bool fastd_config_protocol(fastd_context *ctx, fastd_config *conf, const char *name); bool fastd_config_method(fastd_context *ctx, fastd_config *conf, const char *name); +bool fastd_config_add_log_file(fastd_context *ctx, fastd_config *conf, const char *name, int level); void fastd_configure(fastd_context *ctx, fastd_config *conf, int argc, char *const argv[]); void fastd_reconfigure(fastd_context *ctx, fastd_config *conf); void fastd_config_release(fastd_context *ctx, fastd_config *conf); @@ -216,36 +238,71 @@ static inline int fastd_rand(fastd_context *ctx, int min, int max) { return (r%(max-min) + min); } -#define pr_log(ctx, level, prefix, args...) do { \ - if ((ctx)->conf == NULL || (level) <= (ctx)->conf->loglevel) { \ - char timestr[100]; \ - time_t t; \ - struct tm tm; \ - \ - t = time(NULL); \ - if (localtime_r(&t, &tm) != NULL) { \ - if (strftime(timestr, sizeof(timestr), "%F %T %z --- ", &tm) > 0) \ - fputs(timestr, stderr); \ - } \ - \ - fputs(prefix, stderr); \ - fastd_printf(ctx, args); \ - fputs("\n", stderr); \ - } \ - } while(0) - -#define is_error(ctx) ((ctx)->conf == NULL || LOG_ERROR <= (ctx)->conf->loglevel) -#define is_warn(ctx) ((ctx)->conf == NULL || LOG_WARN <= (ctx)->conf->loglevel) -#define is_info(ctx) ((ctx)->conf == NULL || LOG_INFO <= (ctx)->conf->loglevel) -#define is_verbose(ctx) ((ctx)->conf == NULL || LOG_VERBOSE <= (ctx)->conf->loglevel) -#define is_debug(ctx) ((ctx)->conf == NULL || LOG_DEBUG <= (ctx)->conf->loglevel) - -#define pr_fatal(ctx, args...) pr_log(ctx, LOG_FATAL, "Fatal: ", args) -#define pr_error(ctx, args...) pr_log(ctx, LOG_ERROR, "Error: ", args) -#define pr_warn(ctx, args...) pr_log(ctx, LOG_WARN, "Warning: ", args) -#define pr_info(ctx, args...) pr_log(ctx, LOG_INFO, "Info: ", args) -#define pr_verbose(ctx, args...) pr_log(ctx, LOG_VERBOSE, "Verbose: ", args) -#define pr_debug(ctx, args...) pr_log(ctx, LOG_DEBUG, "DEBUG: ", args) + +#define FASTD_DEFAULT_LOG_LEVEL LOG_INFO + + +static inline const char* get_log_prefix(int log_level) { + switch(log_level) { + case LOG_CRIT: + return "Fatal: "; + case LOG_ERR: + return "Error: "; + case LOG_WARNING: + return "Warning: "; + case LOG_NOTICE: + return "Info: "; + case LOG_INFO: + return "Verbose: "; + case LOG_DEBUG: + return "DEBUG: "; + default: + return ""; + } +} + +static inline void pr_log(const fastd_context *ctx, int level, const char *format, ...) { + char buffer[1024]; + char timestr[100] = ""; + va_list ap; + + va_start(ap, format); + fastd_vsnprintf(ctx, buffer, sizeof(buffer), format, ap); + va_end(ap); + + buffer[sizeof(buffer)-1] = 0; + + if (ctx->conf == NULL || level <= ctx->conf->log_stderr_level || ctx->conf->log_files) { + time_t t; + struct tm tm; + + t = time(NULL); + if (localtime_r(&t, &tm) != NULL) { + if (strftime(timestr, sizeof(timestr), "%F %T %z --- ", &tm) <= 0) + *timestr = 0; + } + } + + if (ctx->conf == NULL || level <= ctx->conf->log_stderr_level) + fprintf(stderr, "%s%s%s\n", timestr, get_log_prefix(level), buffer); + + if (level <= ctx->conf->log_syslog_level) + syslog(level, "%s", buffer); + + fastd_log_fd *file; + for (file = ctx->log_files; file; file = file->next) { + if (level <= file->config->level) + dprintf(file->fd, "%s%s%s\n", timestr, get_log_prefix(level), buffer); + } +} + + +#define pr_fatal(ctx, args...) pr_log(ctx, LOG_CRIT, args) +#define pr_error(ctx, args...) pr_log(ctx, LOG_ERR, args) +#define pr_warn(ctx, args...) pr_log(ctx, LOG_WARNING, args) +#define pr_info(ctx, args...) pr_log(ctx, LOG_NOTICE, args) +#define pr_verbose(ctx, args...) pr_log(ctx, LOG_INFO, args) +#define pr_debug(ctx, args...) pr_log(ctx, LOG_DEBUG, args) #define pr_warn_errno(ctx, message) pr_warn(ctx, "%s: %s", message, strerror(errno)) #define pr_error_errno(ctx, message) pr_warn(ctx, "%s: %s", message, strerror(errno)) diff --git a/src/printf.c b/src/printf.c index cbecbc8..bf2bc35 100644 --- a/src/printf.c +++ b/src/printf.c @@ -28,207 +28,122 @@ #include "peer.h" #include -#include -static void print_peer_address(const fastd_context *ctx, const fastd_peer_address *address) { +static inline int snprintf_safe(char *buffer, size_t size, const char *format, ...) { + va_list ap; + va_start(ap, format); + int ret = vsnprintf(buffer, size, format, ap); + va_end(ap); + + return ret < 0 ? 0 : ret > size ? size : ret; +} + +static int snprint_peer_address(const fastd_context *ctx, char *buffer, size_t size, const fastd_peer_address *address) { char addr_buf[INET6_ADDRSTRLEN] = ""; switch (address->sa.sa_family) { case AF_UNSPEC: - fputs("floating", stderr); - return; + return snprintf(buffer, size, "floating"); case AF_INET: if (inet_ntop(AF_INET, &address->in.sin_addr, addr_buf, sizeof(addr_buf))) - fprintf(stderr, "%s:%u", addr_buf, ntohs(address->in.sin_port)); - return; + return snprintf_safe(buffer, size, "%s:%u", addr_buf, ntohs(address->in.sin_port)); + else + return 0; case AF_INET6: if (inet_ntop(AF_INET6, &address->in6.sin6_addr, addr_buf, sizeof(addr_buf))) - fprintf(stderr, "[%s]:%u", addr_buf, ntohs(address->in6.sin6_port)); - break; + return snprintf_safe(buffer, size, "[%s]:%u", addr_buf, ntohs(address->in6.sin6_port)); + else + return 0; default: exit_bug(ctx, "unsupported address family"); } } -static void print_peer_str(const fastd_context *ctx, const fastd_peer *peer) { - if (peer->config && peer->config->name) { - fprintf(stderr, "<%s>", peer->config->name); - } - else { - fputs("<(null)>", stderr); - } +static int snprint_peer_str(const fastd_context *ctx, char *buffer, size_t size, const fastd_peer *peer) { + if (peer->config && peer->config->name) + return snprintf_safe(buffer, size, "<%s>", peer->config->name); + else + return snprintf_safe(buffer, size, "<(null)>"); } -#pragma GCC diagnostic ignored "-Wformat-security" +int fastd_vsnprintf(const fastd_context *ctx, char *buffer, size_t size, const char *format, va_list ap) { + char *buffer_start = buffer; + char *buffer_end = buffer+size; -void fastd_printf(const fastd_context *ctx, const char *format, ...) { - va_list ap; - va_start(ap, format); + *buffer = 0; - char *format_dup = strdup(format); - char *str; - for (str = format_dup; *str; str++) { - if (*str != '%') { - fputc(*str, stderr); + for (; *format; format++) { + const void *p; + const fastd_eth_addr *eth_addr; + + if (buffer >= buffer_end) + break; + + if (*format != '%') { + *buffer = *format; + buffer++; continue; } - int len, flag_l = 0, flag_L = 0, flag_j = 0, flag_z = 0, flag_t = 0; - - for(len = 1; str[len]; len++) { - char last; - bool finished = true; - const void *p; - const fastd_eth_addr *eth_addr; - - switch (str[len]) { - case 'l': - flag_l++; - finished = false; - break; - - case 'L': - flag_L++; - finished = false; - break; - - case 'j': - flag_j++; - finished = false; - break; - - case 'z': - flag_z++; - finished = false; - break; - - case 't': - flag_t++; - finished = false; - break; - - case '%': - fputc('%', stderr); - break; - - case 'd': - case 'i': - case 'o': - case 'u': - case 'x': - case 'X': - last = str[len+1]; - str[len+1] = 0; - - if (flag_j) - fprintf(stderr, str, va_arg(ap, intmax_t)); - else if (flag_z) - fprintf(stderr, str, va_arg(ap, size_t)); - else if (flag_t) - fprintf(stderr, str, va_arg(ap, ptrdiff_t)); - else if (flag_l == 0) - fprintf(stderr, str, va_arg(ap, int)); - else if (flag_l == 1) - fprintf(stderr, str, va_arg(ap, long)); - else - fprintf(stderr, str, va_arg(ap, long long)); - - str[len+1] = last; - break; - - case 'e': - case 'f': - case 'F': - case 'g': - case 'G': - case 'a': - case 'A': - last = str[len+1]; - str[len+1] = 0; - - if (flag_L) - fprintf(stderr, str, va_arg(ap, long double)); - else - fprintf(stderr, str, va_arg(ap, double)); - - str[len+1] = last; - break; - - case 'c': - last = str[len+1]; - str[len+1] = 0; - - fprintf(stderr, str, va_arg(ap, int)); - - str[len+1] = last; - break; - - case 's': - case 'p': - last = str[len+1]; - str[len+1] = 0; - - fprintf(stderr, str, va_arg(ap, void*)); - - str[len+1] = last; - break; - - case 'm': - last = str[len+1]; - str[len+1] = 0; - - fprintf(stderr, str); - - str[len+1] = last; - break; - - case 'E': - eth_addr = va_arg(ap, const fastd_eth_addr*); - - if (eth_addr) { - fprintf(stderr, "%02x:%02x:%02x:%02x:%02x:%02x", - eth_addr->data[0], eth_addr->data[1], eth_addr->data[2], - eth_addr->data[3], eth_addr->data[4], eth_addr->data[5]); - } - else { - fputs("(null)", stderr); - } - break; - - case 'P': - p = va_arg(ap, const fastd_peer*); - - if (p) - print_peer_str(ctx, (const fastd_peer*)p); - else - fputs("(null)", stderr); - break; - - case 'I': - p = va_arg(ap, const fastd_peer_address*); - - if (p) - print_peer_address(ctx, (const fastd_peer_address*)p); - else - fputs("(null)", stderr); - break; - - default: - finished = false; - } + format++; + + switch(*format) { + case 'i': + buffer += snprintf_safe(buffer, buffer_end-buffer, "%i", va_arg(ap, int)); + break; + + case 'u': + buffer += snprintf_safe(buffer, buffer_end-buffer, "%u", va_arg(ap, unsigned int)); + break; - if (finished) { - str += len; - break; + case 's': + buffer += snprintf_safe(buffer, buffer_end-buffer, "%s", va_arg(ap, char*)); + break; + + case 'E': + eth_addr = va_arg(ap, const fastd_eth_addr*); + + if (eth_addr) { + buffer += snprintf_safe(buffer, buffer_end-buffer, "%02x:%02x:%02x:%02x:%02x:%02x", + eth_addr->data[0], eth_addr->data[1], eth_addr->data[2], + eth_addr->data[3], eth_addr->data[4], eth_addr->data[5]); } + else { + buffer += snprintf_safe(buffer, buffer_end-buffer, "(null)"); + } + break; + + case 'P': + p = va_arg(ap, const fastd_peer*); + + if (p) + buffer += snprint_peer_str(ctx, buffer, buffer_end-buffer, (const fastd_peer*)p); + else + buffer += snprintf_safe(buffer, buffer_end-buffer, "(null)"); + break; + + case 'I': + p = va_arg(ap, const fastd_peer_address*); + + if (p) + buffer += snprint_peer_address(ctx, buffer, buffer_end-buffer, (const fastd_peer_address*)p); + else + buffer += snprintf_safe(buffer, buffer_end-buffer, "(null)"); + break; + + default: + pr_warn(ctx, "fastd_vsnprintf: unknown format conversion specifier '%c'", *format); + *buffer_start = 0; + return -1; } } - free(format_dup); + if (buffer < buffer_end) + *buffer = 0; - va_end(ap); + return buffer-buffer_start; } diff --git a/src/types.h b/src/types.h index 6efd224..c213118 100644 --- a/src/types.h +++ b/src/types.h @@ -33,15 +33,6 @@ #ifndef _FASTD_TYPES_H_ #define _FASTD_TYPES_H_ -typedef enum _fastd_loglevel { - LOG_FATAL = 0, - LOG_ERROR, - LOG_WARN, - LOG_INFO, - LOG_VERBOSE, - LOG_DEBUG, -} fastd_loglevel; - typedef enum _fastd_mode { MODE_TAP, MODE_TUN, @@ -56,6 +47,9 @@ typedef struct _fastd_eth_addr fastd_eth_addr; typedef struct _fastd_peer fastd_peer; typedef struct _fastd_peer_eth_addr fastd_peer_eth_addr; +typedef struct _fastd_log_file fastd_log_file; +typedef struct _fastd_log_fd fastd_log_fd; + typedef struct _fastd_config fastd_config; typedef struct _fastd_context fastd_context; -- cgit v1.2.3