merged the modularization branch (credentials) back to trunk
[strongswan.git] / src / libstrongswan / utils.c
1 /*
2 * Copyright (C) 2005-2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 *
15 * $Id$
16 */
17
18 #include "utils.h"
19
20 #include <string.h>
21 #include <pthread.h>
22 #include <stdio.h>
23
24 #include <enum.h>
25
26 ENUM(status_names, SUCCESS, DESTROY_ME,
27 "SUCCESS",
28 "FAILED",
29 "OUT_OF_RES",
30 "ALREADY_DONE",
31 "NOT_SUPPORTED",
32 "INVALID_ARG",
33 "NOT_FOUND",
34 "PARSE_ERROR",
35 "VERIFY_ERROR",
36 "INVALID_STATE",
37 "DESTROY_ME",
38 "NEED_MORE",
39 );
40
41 /**
42 * Described in header.
43 */
44 void *clalloc(void * pointer, size_t size)
45 {
46 void *data;
47 data = malloc(size);
48
49 memcpy(data, pointer, size);
50
51 return (data);
52 }
53
54 /**
55 * Described in header.
56 */
57 void memxor(u_int8_t dest[], u_int8_t src[], size_t n)
58 {
59 size_t i;
60 for (i = 0; i < n; i++)
61 {
62 dest[i] ^= src[i];
63 }
64 }
65
66 /**
67 * We use a single mutex for all refcount variables. This
68 * is not optimal for performance, but the critical section
69 * is not that long...
70 * TODO: Consider to include a mutex in each refcount_t variable.
71 */
72 static pthread_mutex_t ref_mutex = PTHREAD_MUTEX_INITIALIZER;
73
74 /**
75 * Described in header.
76 *
77 * TODO: May be implemented with atomic CPU instructions
78 * instead of a mutex.
79 */
80 void ref_get(refcount_t *ref)
81 {
82 pthread_mutex_lock(&ref_mutex);
83 (*ref)++;
84 pthread_mutex_unlock(&ref_mutex);
85 }
86
87 /**
88 * Described in header.
89 *
90 * TODO: May be implemented with atomic CPU instructions
91 * instead of a mutex.
92 */
93 bool ref_put(refcount_t *ref)
94 {
95 bool more_refs;
96
97 pthread_mutex_lock(&ref_mutex);
98 more_refs = --(*ref);
99 pthread_mutex_unlock(&ref_mutex);
100 return !more_refs;
101 }
102
103 /**
104 * output handler in printf() for time_t
105 */
106 static int time_print(FILE *stream, const struct printf_info *info,
107 const void *const *args)
108 {
109 static const char* months[] = {
110 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
111 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
112 };
113 time_t *time = *((time_t**)(args[0]));
114 bool utc = TRUE;
115 struct tm t;
116
117 if (info->alt)
118 {
119 utc = *((bool*)(args[1]));
120 }
121 if (time == UNDEFINED_TIME)
122 {
123 return fprintf(stream, "--- -- --:--:--%s----",
124 info->alt ? " UTC " : " ");
125 }
126 if (utc)
127 {
128 gmtime_r(time, &t);
129 }
130 else
131 {
132 localtime_r(time, &t);
133 }
134 return fprintf(stream, "%s %02d %02d:%02d:%02d%s%04d",
135 months[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min,
136 t.tm_sec, utc ? " UTC " : " ", t.tm_year + 1900);
137 }
138
139 /**
140 * arginfo handler for printf() time
141 */
142 static int time_arginfo(const struct printf_info *info, size_t n, int *argtypes)
143 {
144 if (info->alt)
145 {
146 if (n > 1)
147 {
148 argtypes[0] = PA_POINTER;
149 argtypes[1] = PA_INT;
150 }
151 return 2;
152 }
153
154 if (n > 0)
155 {
156 argtypes[0] = PA_POINTER;
157 }
158 return 1;
159 }
160
161 /**
162 * output handler in printf() for time deltas
163 */
164 static int time_delta_print(FILE *stream, const struct printf_info *info,
165 const void *const *args)
166 {
167 char* unit = "second";
168 time_t *arg1, *arg2;
169 time_t delta;
170
171 arg1 = *((time_t**)(args[0]));
172 if (info->alt)
173 {
174 arg2 = *((time_t**)(args[1]));
175 delta = abs(*arg1 - *arg2);
176 }
177 else
178 {
179 delta = *arg1;
180 }
181
182 if (delta > 2 * 60 * 60 * 24)
183 {
184 delta /= 60 * 60 * 24;
185 unit = "day";
186 }
187 else if (delta > 2 * 60 * 60)
188 {
189 delta /= 60 * 60;
190 unit = "hour";
191 }
192 else if (delta > 2 * 60)
193 {
194 delta /= 60;
195 unit = "minute";
196 }
197 return fprintf(stream, "%d %s%s", delta, unit, (delta == 1)? "":"s");
198 }
199
200 /**
201 * arginfo handler for printf() time deltas
202 */
203 int time_delta_arginfo(const struct printf_info *info, size_t n, int *argtypes)
204 {
205 if (info->alt)
206 {
207 if (n > 1)
208 {
209 argtypes[0] = PA_POINTER;
210 argtypes[1] = PA_POINTER;
211 }
212 return 2;
213 }
214
215 if (n > 0)
216 {
217 argtypes[0] = PA_POINTER;
218 }
219 return 1;
220 }
221
222 /**
223 * Number of bytes per line to dump raw data
224 */
225 #define BYTES_PER_LINE 16
226
227 static char hexdig_upper[] = "0123456789ABCDEF";
228
229 /**
230 * output handler in printf() for mem ranges
231 */
232 static int mem_print(FILE *stream, const struct printf_info *info,
233 const void *const *args)
234 {
235 char *bytes = *((void**)(args[0]));
236 int len = *((size_t*)(args[1]));
237
238 char buffer[BYTES_PER_LINE * 3];
239 char ascii_buffer[BYTES_PER_LINE + 1];
240 char *buffer_pos = buffer;
241 char *bytes_pos = bytes;
242 char *bytes_roof = bytes + len;
243 int line_start = 0;
244 int i = 0;
245 int written = 0;
246
247 written += fprintf(stream, "=> %d bytes @ %p", len, bytes);
248
249 while (bytes_pos < bytes_roof)
250 {
251 *buffer_pos++ = hexdig_upper[(*bytes_pos >> 4) & 0xF];
252 *buffer_pos++ = hexdig_upper[ *bytes_pos & 0xF];
253
254 ascii_buffer[i++] =
255 (*bytes_pos > 31 && *bytes_pos < 127) ? *bytes_pos : '.';
256
257 if (++bytes_pos == bytes_roof || i == BYTES_PER_LINE)
258 {
259 int padding = 3 * (BYTES_PER_LINE - i);
260 int written;
261
262 while (padding--)
263 {
264 *buffer_pos++ = ' ';
265 }
266 *buffer_pos++ = '\0';
267 ascii_buffer[i] = '\0';
268
269 written += fprintf(stream, "\n%4d: %s %s",
270 line_start, buffer, ascii_buffer);
271
272
273 buffer_pos = buffer;
274 line_start += BYTES_PER_LINE;
275 i = 0;
276 }
277 else
278 {
279 *buffer_pos++ = ' ';
280 }
281 }
282 return written;
283 }
284
285 /**
286 * arginfo handler for printf() mem ranges
287 */
288 int mem_arginfo(const struct printf_info *info, size_t n, int *argtypes)
289 {
290 if (n > 1)
291 {
292 argtypes[0] = PA_POINTER;
293 argtypes[1] = PA_INT;
294 }
295 return 2;
296 }
297
298 /**
299 * return printf hook functions for a time
300 */
301 printf_hook_functions_t time_get_printf_hooks()
302 {
303 printf_hook_functions_t hooks = {time_print, time_arginfo};
304
305 return hooks;
306 }
307
308 /**
309 * return printf hook functions for a time delta
310 */
311 printf_hook_functions_t time_delta_get_printf_hooks()
312 {
313 printf_hook_functions_t hooks = {time_delta_print, time_delta_arginfo};
314
315 return hooks;
316 }
317
318 /**
319 * return printf hook functions for mem ranges
320 */
321 printf_hook_functions_t mem_get_printf_hooks()
322 {
323 printf_hook_functions_t hooks = {mem_print, mem_arginfo};
324
325 return hooks;
326 }
327