summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2012-05-18 03:08:40 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2012-05-18 03:08:40 +0200
commitb34b3e2817950c6cccbc9cf2fce8cc137f433a88 (patch)
tree973428ea13a6d36b7658644d6f32f21edaea9a10
parenta2b9f2c732232200fd4822e34d60d4c7f5ad37d2 (diff)
downloadfastd-b34b3e2817950c6cccbc9cf2fce8cc137f433a88.tar
fastd-b34b3e2817950c6cccbc9cf2fce8cc137f433a88.zip
New logging facilities
-rw-r--r--src/config.c87
-rw-r--r--src/config.l3
-rw-r--r--src/config.y68
-rw-r--r--src/fastd.c41
-rw-r--r--src/fastd.h121
-rw-r--r--src/printf.c259
-rw-r--r--src/types.h12
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", "<ident>", "Sets the syslog identification; default is 'fastd'") \
OPTION_ARG(option_config, "--config" OR "-c", "<filename>", "Loads a config file") \
OPTION_ARG(option_config_peer, "--config-peer", "<filename>", "Loads a config file for a single peer") \
OPTION_ARG(option_config_peer_dir, "--config-peer-dir", "<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 <num> maybe_log_level
+%type <num> log_level
%type <num> port
%type <boolean> boolean
%type <num> 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 <errno.h>
#include <linux/if_ether.h>
#include <netinet/in.h>
+#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <syslog.h>
#include <sys/uio.h>
#include <sys/socket.h>
#include <time.h>
@@ -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 <arpa/inet.h>
-#include <stdarg.h>
-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;