]> git.ipfire.org Git - people/ms/strongswan.git/blame - Source/charon/utils/logger.c
- rewrote a lot of RSA stuff
[people/ms/strongswan.git] / Source / charon / utils / logger.c
CommitLineData
61c3cdc2
MW
1/**
2 * @file logger.c
3 *
adad211c 4 * @brief Implementation of logger_t.
61c3cdc2
MW
5 *
6 */
7
8/*
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
61c3cdc2
MW
23#include <syslog.h>
24#include <stdarg.h>
69dd9581 25#include <string.h>
dba9cf64 26#include <stdio.h>
ffd555f5 27#include <time.h>
41fc4f74 28#include <pthread.h>
ffd555f5
JH
29
30#include "logger.h"
88878242 31
021c2322
MW
32#include <daemon.h>
33#include <utils/allocator.h>
61c3cdc2 34
69dd9581 35/**
d794bcdb 36 * Maximum length of a log entry (only used for logger_s.log).
69dd9581
MW
37 */
38#define MAX_LOG 8192
61c3cdc2 39
d794bcdb 40
5796aa16
MW
41typedef struct private_logger_t private_logger_t;
42
61c3cdc2 43/**
d794bcdb 44 * @brief Private data of a logger_t object.
61c3cdc2 45 */
5796aa16 46struct private_logger_t {
61c3cdc2 47 /**
d794bcdb 48 * Public data.
61c3cdc2
MW
49 */
50 logger_t public;
61c3cdc2 51 /**
ffd555f5 52 * Detail-level of logger.
61c3cdc2 53 */
dec59822 54 log_level_t level;
61c3cdc2 55 /**
ffd555f5 56 * Name of logger.
61c3cdc2
MW
57 */
58 char *name;
ffd555f5 59 /**
adad211c 60 * File to write log output to.
ffd555f5
JH
61 * NULL for syslog.
62 */
63 FILE *output;
64
41fc4f74 65 /**
25c41f4d 66 * Should a thread_id be included in the log?
41fc4f74 67 */
25c41f4d 68 bool log_thread_id;
41fc4f74 69
41fc4f74 70 /**
adad211c 71 * Applies a prefix to string and stores it in buffer.
41fc4f74 72 *
adad211c 73 * @warning: buffer must be at least have MAX_LOG size.
41fc4f74 74 */
dec59822 75 void (*prepend_prefix) (private_logger_t *this, log_level_t loglevel, char *string, char *buffer);
61c3cdc2
MW
76};
77
41fc4f74 78/**
adad211c 79 * Implementation of private_logger_t.prepend_prefix.
41fc4f74 80 */
dec59822 81static void prepend_prefix(private_logger_t *this, log_level_t loglevel, char *string, char *buffer)
41fc4f74
MW
82{
83 char log_type, log_details;
84 if (loglevel & CONTROL)
85 {
86 log_type = '~';
87 }
88 else if (loglevel & ERROR)
89 {
90 log_type = '!';
91 }
92 else if (loglevel & RAW)
93 {
94 log_type = '#';
95 }
96 else if (loglevel & PRIVATE)
97 {
98 log_type = '?';
99 }
39b2903f
JH
100 else if (loglevel & AUDIT)
101 {
102 log_type = '>';
103 }
41fc4f74
MW
104 else
105 {
106 log_type = '-';
107 }
108
aee3eb52 109 if (loglevel & (LEVEL3 - LEVEL2))
41fc4f74
MW
110 {
111 log_details = '3';
112 }
aee3eb52 113 else if (loglevel & (LEVEL2 - LEVEL1))
41fc4f74
MW
114 {
115 log_details = '2';
116 }
aee3eb52 117 else if (loglevel & LEVEL1)
41fc4f74
MW
118 {
119 log_details = '1';
120 }
121 else
122 {
123 log_details = '0';
124 }
125
25c41f4d 126 if (this->log_thread_id)
41fc4f74 127 {
25c41f4d 128 snprintf(buffer, MAX_LOG, "[%c%c] [%s] @%u %s", log_type, log_details, this->name, (int)pthread_self(), string);
41fc4f74
MW
129 }
130 else
131 {
132 snprintf(buffer, MAX_LOG, "[%c%c] [%s] %s", log_type, log_details, this->name, string);
133 }
41fc4f74
MW
134}
135
6ae4efda 136/**
adad211c
JH
137 * Implementation of logger_t.log.
138 *
ffd555f5 139 * Yes, logg is wrong written :-).
6ae4efda 140 */
dec59822 141static void logg(private_logger_t *this, log_level_t loglevel, char *format, ...)
61c3cdc2
MW
142{
143 if ((this->level & loglevel) == loglevel)
144 {
69dd9581 145 char buffer[MAX_LOG];
61c3cdc2 146 va_list args;
41fc4f74 147
69dd9581 148
ffd555f5
JH
149 if (this->output == NULL)
150 {
151 /* syslog */
41fc4f74 152 this->prepend_prefix(this, loglevel, format, buffer);
ffd555f5
JH
153 va_start(args, format);
154 vsyslog(LOG_INFO, buffer, args);
155 va_end(args);
156 }
157 else
158 {
159 /* File output */
41fc4f74 160 this->prepend_prefix(this, loglevel, format, buffer);
ffd555f5 161 va_start(args, format);
d6209900 162 vfprintf(this->output, buffer, args);
ffd555f5 163 va_end(args);
d6209900 164 fprintf(this->output, "\n");
ffd555f5
JH
165 }
166
167 }
69dd9581
MW
168}
169
69dd9581 170/**
adad211c 171 * Implementation of logger_t.log_bytes.
69dd9581 172 */
dec59822 173static void log_bytes(private_logger_t *this, log_level_t loglevel, char *label, char *bytes, size_t len)
69dd9581 174{
d6209900 175 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
aeda79ff 176
d6209900 177
69dd9581
MW
178 if ((this->level & loglevel) == loglevel)
179 {
41fc4f74 180 char buffer[MAX_LOG];
87a217f9 181 char ascii_buffer[17];
41fc4f74 182 char *format;
69dd9581
MW
183 char *buffer_pos;
184 char *bytes_pos, *bytes_roof;
185 int i;
aeda79ff
MW
186 int line_start = 0;
187
188 /* since me can't do multi-line output to syslog,
189 * we must do multiple syslogs. To avoid
190 * problems in output order, lock this by a mutex.
191 */
192 pthread_mutex_lock(&mutex);
41fc4f74
MW
193
194
efadbf79 195 format = "%s (%d bytes @%p)";
41fc4f74 196 this->prepend_prefix(this, loglevel, format, buffer);
69dd9581 197
ffd555f5
JH
198 if (this->output == NULL)
199 {
41fc4f74 200 syslog(LOG_INFO, buffer, label, len);
d6209900
MW
201 }
202 else
ffd555f5 203 {
efadbf79 204 fprintf(this->output, buffer, label, len, bytes);
d6209900 205 fprintf(this->output, "\n");
ffd555f5 206 }
61c3cdc2 207
69dd9581
MW
208 bytes_pos = bytes;
209 bytes_roof = bytes + len;
210 buffer_pos = buffer;
87a217f9 211 memset(ascii_buffer, 0, 17);
69dd9581
MW
212
213 for (i = 1; bytes_pos < bytes_roof; i++)
214 {
d6209900 215 static char hexdig[] = "0123456789ABCDEF";
69dd9581
MW
216 *buffer_pos++ = hexdig[(*bytes_pos >> 4) & 0xF];
217 *buffer_pos++ = hexdig[ *bytes_pos & 0xF];
218 if ((i % 16) == 0)
219 {
220 *buffer_pos++ = '\0';
221 buffer_pos = buffer;
ffd555f5
JH
222 if (this->output == NULL)
223 {
87a217f9 224 syslog(LOG_INFO, "[=>] [%5d ] %s %s", line_start, buffer, ascii_buffer);
ffd555f5
JH
225 }
226 else
227 {
87a217f9 228 fprintf(this->output, "[=>] [%5d ] %s %s\n", line_start, buffer, ascii_buffer);
ffd555f5 229 }
87a217f9 230 memset(ascii_buffer, 0, 16);
aeda79ff 231 line_start += 16;
69dd9581 232 }
69dd9581
MW
233 else if ((i % 4) == 0)
234 {
235 *buffer_pos++ = ' ';
87a217f9 236 // *buffer_pos++ = ' ';
69dd9581
MW
237 }
238 else
239 {
240 *buffer_pos++ = ' ';
241 }
242
87a217f9
MW
243 if (*bytes_pos > 31 && *bytes_pos < 127)
244 {
245 ascii_buffer[(i % 16)] = *bytes_pos;
246 }
247 else
248 {
249 ascii_buffer[(i % 16)] = '*';
250 }
251
69dd9581
MW
252 bytes_pos++;
253 }
254
255 *buffer_pos++ = '\0';
d6209900 256 if (buffer_pos > buffer + 1)
ffd555f5 257 {
d6209900
MW
258 buffer_pos = buffer;
259 if (this->output == NULL)
260 {
87a217f9 261 syslog(LOG_INFO, "[=>] [%5d ] %s %16s", line_start, buffer, ascii_buffer);
d6209900
MW
262 }
263 else
264 {
87a217f9 265 fprintf(this->output, "[=>] [%5d ] %s %16s\n", line_start, buffer, ascii_buffer);
d6209900 266 }
ffd555f5 267 }
aeda79ff 268 pthread_mutex_unlock(&mutex);
69dd9581 269 }
61c3cdc2 270}
6ae4efda 271
69dd9581 272/**
adad211c 273 * Implementation of logger_t.log_chunk.
69dd9581 274 */
dec59822 275static void log_chunk(logger_t *this, log_level_t loglevel, char *label, chunk_t chunk)
69dd9581 276{
16b9a73c 277 this->log_bytes(this, loglevel, label, chunk.ptr, chunk.len);
69dd9581
MW
278}
279
6ae4efda 280/**
adad211c 281 * Implementation of logger_t.enable_level.
6ae4efda 282 */
dec59822 283static void enable_level(private_logger_t *this, log_level_t log_level)
61c3cdc2
MW
284{
285 this->level |= log_level;
61c3cdc2 286}
6ae4efda
JH
287
288/**
adad211c 289 * Implementation of logger_t.disable_level.
6ae4efda 290 */
dec59822 291static void disable_level(private_logger_t *this, log_level_t log_level)
61c3cdc2 292{
69dd9581 293 this->level &= ~log_level;
61c3cdc2 294}
6ae4efda 295
efadbf79
MW
296/**
297 * Implementation of logger_t.set_output.
298 */
299static void set_output(private_logger_t *this, FILE * output)
300{
301 this->output = output;
302}
303
dec59822
MW
304/**
305 * Implementation of logger_t.get_level.
306 */
307static log_level_t get_level(private_logger_t *this)
308{
309 return this->level;
310}
311
6ae4efda 312/**
adad211c 313 * Implementation of logger_t.destroy.
69dd9581 314 */
d048df5c 315static void destroy(private_logger_t *this)
61c3cdc2 316{
96d72d32 317 allocator_free(this->name);
61c3cdc2 318 allocator_free(this);
61c3cdc2
MW
319}
320
6ae4efda 321/*
adad211c 322 * Described in header.
6ae4efda 323 */
dec59822 324logger_t *logger_create(char *logger_name, log_level_t log_level, bool log_thread_id, FILE * output)
61c3cdc2
MW
325{
326 private_logger_t *this = allocator_alloc_thing(private_logger_t);
61c3cdc2 327
d794bcdb 328 /* public functions */
dec59822
MW
329 this->public.log = (void(*)(logger_t*,log_level_t,char*,...))logg;
330 this->public.log_bytes = (void(*)(logger_t*, log_level_t, char*,char*,size_t))log_bytes;
69dd9581 331 this->public.log_chunk = log_chunk;
dec59822
MW
332 this->public.enable_level = (void(*)(logger_t*,log_level_t))enable_level;
333 this->public.disable_level = (void(*)(logger_t*,log_level_t))disable_level;
334 this->public.get_level = (log_level_t(*)(logger_t*))get_level;
efadbf79 335 this->public.set_output = (void(*)(logger_t*,FILE*))set_output;
d048df5c 336 this->public.destroy = (void(*)(logger_t*))destroy;
61c3cdc2 337
d794bcdb 338 /* private functions */
41fc4f74 339 this->prepend_prefix = prepend_prefix;
ffd555f5 340
d794bcdb
JH
341 if (logger_name == NULL)
342 {
343 logger_name = "";
344 }
345
ffd555f5 346 /* private variables */
61c3cdc2 347 this->level = log_level;
25c41f4d 348 this->log_thread_id = log_thread_id;
96d72d32 349 this->name = allocator_alloc(strlen(logger_name) + 1);
d048df5c 350
96d72d32 351 strcpy(this->name,logger_name);
ffd555f5 352 this->output = output;
61c3cdc2 353
ffd555f5
JH
354 if (output == NULL)
355 {
db715454 356 openlog(DAEMON_NAME, 0, LOG_DAEMON);
ffd555f5 357 }
61c3cdc2
MW
358
359 return (logger_t*)this;
360}