- added log_bytes and log_chunk
[strongswan.git] / Source / charon / logger.c
1 /**
2 * @file logger.c
3 *
4 * @brief Logger object, allows fine-controlled logging
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
23
24
25 #include "logger.h"
26 #include "types.h"
27 #include "allocator.h"
28
29 #include <syslog.h>
30 #include <stdarg.h>
31 #include <string.h>
32
33 /**
34 * Maximum length of al log entry (only used for logger_s.log)
35 */
36 #define MAX_LOG 8192
37
38 /**
39 * @brief The logger object
40 */
41 typedef struct private_logger_s private_logger_t;
42 struct private_logger_s {
43 /**
44 * Public data
45 */
46 logger_t public;
47 /**
48 * detail-level of logger
49 */
50 logger_level_t level;
51 /**
52 * name of logger
53 */
54 char *name;
55 };
56
57
58 /**
59 * implements logger_t-function log
60 * @see logger_s.log
61 */
62 static status_t logg(private_logger_t *this, logger_level_t loglevel, char *format, ...)
63 {
64 if ((this->level & loglevel) == loglevel)
65 {
66 char buffer[MAX_LOG];
67 snprintf(buffer, MAX_LOG, "%s: %s", this->name, format);
68 va_list args;
69 va_start(args, format);
70 vsyslog(LOG_INFO, buffer, args);
71 va_end(args);
72 }
73
74 return SUCCESS;
75 }
76
77
78 /**
79 * implements logger_t-function destroy
80 * @see logger_s.log_bytes
81 */
82 static status_t log_bytes(private_logger_t *this, logger_level_t loglevel, char *label, char *bytes, size_t len)
83 {
84 if ((this->level & loglevel) == loglevel)
85 {
86 char buffer[64];
87 char *buffer_pos;
88 char *bytes_pos, *bytes_roof;
89 int i;
90
91 syslog(LOG_INFO, "%s: %s (%d bytes)", this->name, label, len);
92
93 bytes_pos = bytes;
94 bytes_roof = bytes + len;
95 buffer_pos = buffer;
96
97 for (i = 1; bytes_pos < bytes_roof; i++)
98 {
99 static const char hexdig[] = "0123456789ABCDEF";
100 *buffer_pos++ = hexdig[(*bytes_pos >> 4) & 0xF];
101 *buffer_pos++ = hexdig[ *bytes_pos & 0xF];
102 if ((i % 16) == 0)
103 {
104 *buffer_pos++ = '\0';
105 buffer_pos = buffer;
106 syslog(LOG_INFO, "| %s", buffer);
107 }
108 else if ((i % 8) == 0)
109 {
110 *buffer_pos++ = ' ';
111 *buffer_pos++ = ' ';
112 *buffer_pos++ = ' ';
113 }
114 else if ((i % 4) == 0)
115 {
116 *buffer_pos++ = ' ';
117 *buffer_pos++ = ' ';
118 }
119 else
120 {
121 *buffer_pos++ = ' ';
122 }
123
124 bytes_pos++;
125 }
126
127 *buffer_pos++ = '\0';
128 buffer_pos = buffer;
129 syslog(LOG_INFO, "| %s", buffer);
130 }
131
132 return SUCCESS;
133 }
134
135
136 /**
137 * implements logger_t-function log_chunk
138 * @see logger_s.log_chunk
139 */
140 static status_t log_chunk(logger_t *this, logger_level_t loglevel, char *label, chunk_t *chunk)
141 {
142 this->log_bytes(this, loglevel, label, chunk->ptr, chunk->len);
143 return SUCCESS;
144 }
145
146
147 /**
148 * implements logger_t-function enable_level
149 * @see logger_s.enable_level
150 */
151 static status_t enable_level(private_logger_t *this, logger_level_t log_level)
152 {
153 this->level |= log_level;
154 return SUCCESS;
155 }
156
157 /**
158 * implements logger_t-function disable_level
159 * @see logger_s.disable_level
160 */
161 static status_t disable_level(private_logger_t *this, logger_level_t log_level)
162 {
163 this->level &= ~log_level;
164 return SUCCESS;
165 }
166
167 /**
168 * implements logger_t-function destroy
169 * @see logger_s.destroy
170 */
171 static status_t destroy(private_logger_t *this)
172 {
173 allocator_free(this);
174 return SUCCESS;
175 }
176
177 /*
178 * Described in Header
179 */
180 logger_t *logger_create(char *logger_name, logger_level_t log_level)
181 {
182 private_logger_t *this = allocator_alloc_thing(private_logger_t);
183
184 if (this == NULL)
185 {
186 return NULL;
187 }
188
189 this->public.log = (status_t(*)(logger_t*,logger_level_t,char*,...))logg;
190 this->public.log_bytes = (status_t(*)(logger_t*, logger_level_t, char*,char*,size_t))log_bytes;
191 this->public.log_chunk = log_chunk;
192 this->public.enable_level = (status_t(*)(logger_t*,logger_level_t))enable_level;
193 this->public.disable_level = (status_t(*)(logger_t*,logger_level_t))disable_level;
194 this->public.destroy = (status_t(*)(logger_t*))destroy;
195
196 this->level = log_level;
197 this->name = logger_name;
198
199 openlog("charon", 0, LOG_DAEMON);
200
201 return (logger_t*)this;
202 }