]> git.ipfire.org Git - people/ms/strongswan.git/blame - src/libstrongswan/utils.c
splitted IKE_SA manager destroy to allow plugin interaction
[people/ms/strongswan.git] / src / libstrongswan / utils.c
CommitLineData
552cc11b
MW
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
26ENUM(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 */
44void *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 */
57void 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
081ae2eb
MW
66/**
67 * return null
68 */
69void *return_null()
70{
71 return NULL;
72}
73
552cc11b
MW
74/**
75 * We use a single mutex for all refcount variables. This
76 * is not optimal for performance, but the critical section
77 * is not that long...
78 * TODO: Consider to include a mutex in each refcount_t variable.
79 */
80static pthread_mutex_t ref_mutex = PTHREAD_MUTEX_INITIALIZER;
81
82/**
83 * Described in header.
84 *
85 * TODO: May be implemented with atomic CPU instructions
86 * instead of a mutex.
87 */
88void ref_get(refcount_t *ref)
89{
90 pthread_mutex_lock(&ref_mutex);
91 (*ref)++;
92 pthread_mutex_unlock(&ref_mutex);
93}
94
95/**
96 * Described in header.
97 *
98 * TODO: May be implemented with atomic CPU instructions
99 * instead of a mutex.
100 */
101bool ref_put(refcount_t *ref)
102{
103 bool more_refs;
104
105 pthread_mutex_lock(&ref_mutex);
106 more_refs = --(*ref);
107 pthread_mutex_unlock(&ref_mutex);
108 return !more_refs;
109}
110
111/**
112 * output handler in printf() for time_t
113 */
114static int time_print(FILE *stream, const struct printf_info *info,
115 const void *const *args)
116{
117 static const char* months[] = {
118 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
119 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
120 };
121 time_t *time = *((time_t**)(args[0]));
122 bool utc = TRUE;
123 struct tm t;
124
125 if (info->alt)
126 {
127 utc = *((bool*)(args[1]));
128 }
129 if (time == UNDEFINED_TIME)
130 {
131 return fprintf(stream, "--- -- --:--:--%s----",
132 info->alt ? " UTC " : " ");
133 }
134 if (utc)
135 {
136 gmtime_r(time, &t);
137 }
138 else
139 {
140 localtime_r(time, &t);
141 }
142 return fprintf(stream, "%s %02d %02d:%02d:%02d%s%04d",
143 months[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min,
144 t.tm_sec, utc ? " UTC " : " ", t.tm_year + 1900);
145}
146
147/**
148 * arginfo handler for printf() time
149 */
150static int time_arginfo(const struct printf_info *info, size_t n, int *argtypes)
151{
152 if (info->alt)
153 {
154 if (n > 1)
155 {
156 argtypes[0] = PA_POINTER;
157 argtypes[1] = PA_INT;
158 }
159 return 2;
160 }
161
162 if (n > 0)
163 {
164 argtypes[0] = PA_POINTER;
165 }
166 return 1;
167}
168
169/**
170 * output handler in printf() for time deltas
171 */
172static int time_delta_print(FILE *stream, const struct printf_info *info,
173 const void *const *args)
174{
175 char* unit = "second";
176 time_t *arg1, *arg2;
177 time_t delta;
178
179 arg1 = *((time_t**)(args[0]));
180 if (info->alt)
181 {
182 arg2 = *((time_t**)(args[1]));
183 delta = abs(*arg1 - *arg2);
184 }
185 else
186 {
187 delta = *arg1;
188 }
189
190 if (delta > 2 * 60 * 60 * 24)
191 {
192 delta /= 60 * 60 * 24;
193 unit = "day";
194 }
195 else if (delta > 2 * 60 * 60)
196 {
197 delta /= 60 * 60;
198 unit = "hour";
199 }
200 else if (delta > 2 * 60)
201 {
202 delta /= 60;
203 unit = "minute";
204 }
205 return fprintf(stream, "%d %s%s", delta, unit, (delta == 1)? "":"s");
206}
207
208/**
209 * arginfo handler for printf() time deltas
210 */
211int time_delta_arginfo(const struct printf_info *info, size_t n, int *argtypes)
212{
213 if (info->alt)
214 {
215 if (n > 1)
216 {
217 argtypes[0] = PA_POINTER;
218 argtypes[1] = PA_POINTER;
219 }
220 return 2;
221 }
222
223 if (n > 0)
224 {
225 argtypes[0] = PA_POINTER;
226 }
227 return 1;
228}
229
230/**
231 * Number of bytes per line to dump raw data
232 */
233#define BYTES_PER_LINE 16
234
235static char hexdig_upper[] = "0123456789ABCDEF";
236
237/**
238 * output handler in printf() for mem ranges
239 */
240static int mem_print(FILE *stream, const struct printf_info *info,
241 const void *const *args)
242{
243 char *bytes = *((void**)(args[0]));
244 int len = *((size_t*)(args[1]));
245
246 char buffer[BYTES_PER_LINE * 3];
247 char ascii_buffer[BYTES_PER_LINE + 1];
248 char *buffer_pos = buffer;
249 char *bytes_pos = bytes;
250 char *bytes_roof = bytes + len;
251 int line_start = 0;
252 int i = 0;
253 int written = 0;
254
255 written += fprintf(stream, "=> %d bytes @ %p", len, bytes);
256
257 while (bytes_pos < bytes_roof)
258 {
259 *buffer_pos++ = hexdig_upper[(*bytes_pos >> 4) & 0xF];
260 *buffer_pos++ = hexdig_upper[ *bytes_pos & 0xF];
261
262 ascii_buffer[i++] =
263 (*bytes_pos > 31 && *bytes_pos < 127) ? *bytes_pos : '.';
264
265 if (++bytes_pos == bytes_roof || i == BYTES_PER_LINE)
266 {
267 int padding = 3 * (BYTES_PER_LINE - i);
268 int written;
269
270 while (padding--)
271 {
272 *buffer_pos++ = ' ';
273 }
274 *buffer_pos++ = '\0';
275 ascii_buffer[i] = '\0';
276
277 written += fprintf(stream, "\n%4d: %s %s",
278 line_start, buffer, ascii_buffer);
279
280
281 buffer_pos = buffer;
282 line_start += BYTES_PER_LINE;
283 i = 0;
284 }
285 else
286 {
287 *buffer_pos++ = ' ';
288 }
289 }
290 return written;
291}
292
293/**
294 * arginfo handler for printf() mem ranges
295 */
296int mem_arginfo(const struct printf_info *info, size_t n, int *argtypes)
297{
298 if (n > 1)
299 {
300 argtypes[0] = PA_POINTER;
301 argtypes[1] = PA_INT;
302 }
303 return 2;
304}
305
306/**
307 * return printf hook functions for a time
308 */
309printf_hook_functions_t time_get_printf_hooks()
310{
311 printf_hook_functions_t hooks = {time_print, time_arginfo};
312
313 return hooks;
314}
315
316/**
317 * return printf hook functions for a time delta
318 */
319printf_hook_functions_t time_delta_get_printf_hooks()
320{
321 printf_hook_functions_t hooks = {time_delta_print, time_delta_arginfo};
322
323 return hooks;
324}
325
326/**
327 * return printf hook functions for mem ranges
328 */
329printf_hook_functions_t mem_get_printf_hooks()
330{
331 printf_hook_functions_t hooks = {mem_print, mem_arginfo};
332
333 return hooks;
334}
335