5864099d3f239c5828212fa5997a4d20de8ba303
1 /* misc. universal things
2 * Copyright (C) 1998-2001 D. Hugh Redelmeier.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 #include <sys/types.h>
27 #include "constants.h"
30 #include "whack.h" /* for RC_LOG_SERIOUS */
32 const chunk_t empty_chunk
= { NULL
, 0 };
35 all_zero(const unsigned char *m
, size_t len
)
39 for (i
= 0; i
!= len
; i
++)
47 * LEAK_DETECTIVE puts a wrapper around each allocation and maintains
48 * a list of live ones. If a dead one is freed, an assertion MIGHT fail.
49 * If the live list is currupted, that will often be detected.
50 * In the end, report_leaks() is called, and the names of remaining
51 * live allocations are printed. At the moment, it is hoped, not that
52 * the list is empty, but that there will be no surprises.
55 * - "struct iface" and "device name" (for "discovered" net interfaces)
56 * - "struct event in event_schedule()" (events not associated with states)
57 * - "Pluto lock name" (one only, needed until end -- why bother?)
62 /* this magic number is 3671129837 decimal (623837458 complemented) */
63 #define LEAK_MAGIC 0xDAD0FEEDul
68 union mhdr
*older
, *newer
;
71 unsigned long junk
; /* force maximal alignment */
74 static union mhdr
*allocs
= NULL
;
76 void *alloc_bytes(size_t size
, const char *name
)
78 union mhdr
*p
= malloc(sizeof(union mhdr
) + size
);
81 exit_log("unable to malloc %lu bytes for %s"
82 , (unsigned long) size
, name
);
89 p
->i
.magic
= LEAK_MAGIC
;
91 memset(p
+1, '\0', size
);
96 clone_bytes(const void *orig
, size_t size
, const char *name
)
98 void *p
= alloc_bytes(size
, name
);
100 memcpy(p
, orig
, size
);
109 passert(ptr
!= NULL
);
110 p
= ((union mhdr
*)ptr
) - 1;
111 passert(p
->i
.magic
== LEAK_MAGIC
);
112 if (p
->i
.older
!= NULL
)
114 passert(p
->i
.older
->i
.newer
== p
);
115 p
->i
.older
->i
.newer
= p
->i
.newer
;
117 if (p
->i
.newer
== NULL
)
119 passert(p
== allocs
);
124 passert(p
->i
.newer
->i
.older
== p
);
125 p
->i
.newer
->i
.older
= p
->i
.older
;
127 p
->i
.magic
= ~LEAK_MAGIC
;
141 passert(p
->i
.magic
== LEAK_MAGIC
);
142 passert(pprev
== p
->i
.newer
);
146 if (p
== NULL
|| pprev
->i
.name
!= p
->i
.name
)
149 plog("leak: %lu * %s", n
, pprev
->i
.name
);
151 plog("leak: %s", pprev
->i
.name
);
157 #else /* !LEAK_DETECTIVE */
159 void *alloc_bytes(size_t size
, const char *name
)
161 void *p
= malloc(size
);
164 exit_log("unable to malloc %lu bytes for %s"
165 , (unsigned long) size
, name
);
166 memset(p
, '\0', size
);
170 void *clone_bytes(const void *orig
, size_t size
, const char *name
)
172 void *p
= malloc(size
);
175 exit_log("unable to malloc %lu bytes for %s"
176 , (unsigned long) size
, name
);
177 memcpy(p
, orig
, size
);
180 #endif /* !LEAK_DETECTIVE */
182 /* Note that there may be as many as six IDs that are temporary at
183 * one time before unsharing the two ends of a connection. So we need
184 * at least six temporary buffers for DER_ASN1_DN IDs.
185 * We rotate them. Be careful!
190 temporary_cyclic_buffer(void)
192 static char buf
[MAX_BUF
][BUF_LEN
]; /* MAX_BUF internal buffers */
193 static int counter
= 0; /* cyclic counter */
195 if (++counter
== MAX_BUF
) counter
= 0; /* next internal buffer */
196 return buf
[counter
]; /* assign temporary buffer */
199 /* concatenates two sub paths into a string with a maximum size of BUF_LEN
200 * use for temporary storage only
203 concatenate_paths(const char *a
, const char *b
)
207 if (*b
== '/' || *b
== '.')
210 c
= temporary_cyclic_buffer();
211 snprintf(c
, BUF_LEN
, "%s/%s", a
, b
);
215 /* compare two chunks, returns zero if a equals b
216 * negative/positive if a is earlier/later in the alphabet than b
219 cmp_chunk(chunk_t a
, chunk_t b
)
221 int cmp_len
, len
, cmp_value
;
223 cmp_len
= a
.len
- b
.len
;
224 len
= (cmp_len
< 0)? a
.len
: b
.len
;
225 cmp_value
= memcmp(a
.ptr
, b
.ptr
, len
);
227 return (cmp_value
== 0)? cmp_len
: cmp_value
;
230 /* moves a chunk to a memory position, chunk is freed afterwards
231 * position pointer is advanced after the insertion point
234 mv_chunk(u_char
**pos
, chunk_t content
)
238 chunkcpy(*pos
, content
);
239 freeanychunk(content
);
244 * write the binary contents of a chunk_t to a file
247 write_chunk(const char *filename
, const char *label
, chunk_t ch
248 , mode_t mask
, bool force
)
255 fd
= fopen(filename
, "r");
259 plog(" %s file '%s' already exists", label
, filename
);
265 oldmask
= umask(mask
);
267 fd
= fopen(filename
, "w");
271 fwrite(ch
.ptr
, sizeof(u_char
), ch
.len
, fd
);
273 plog(" written %s file '%s' (%d bytes)", label
, filename
, (int)ch
.len
);
279 plog(" could not open %s file '%s' for writing", label
, filename
);
285 /* Names of the months */
287 static const char* months
[] = {
288 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
289 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
294 * Display a date either in local or UTC time
297 timetoa(const time_t *time
, bool utc
)
299 static char buf
[TIMETOA_BUF
];
301 if (*time
== UNDEFINED_TIME
)
302 sprintf(buf
, "--- -- --:--:--%s----", (utc
)?
" UTC ":" ");
305 struct tm
*t
= (utc
)?
gmtime(time
) : localtime(time
);
307 sprintf(buf
, "%s %02d %02d:%02d:%02d%s%04d",
308 months
[t
->tm_mon
], t
->tm_mday
, t
->tm_hour
, t
->tm_min
, t
->tm_sec
,
309 (utc
)?
" UTC ":" ", t
->tm_year
+ 1900
315 /* checks if the expiration date has been reached and
316 * warns during the warning_interval of the imminent
317 * expiry. strict=TRUE declares a fatal error,
318 * strict=FALSE issues a warning upon expiry.
321 check_expiry(time_t expiration_date
, int warning_interval
, bool strict
)
326 if (expiration_date
== UNDEFINED_TIME
)
327 return "ok (expires never)";
329 /* determine the current time */
332 time_left
= (expiration_date
- now
);
334 return strict?
"fatal (expired)" : "warning (expired)";
336 if (time_left
> 86400*warning_interval
)
339 static char buf
[35]; /* temporary storage */
340 const char* unit
= "second";
342 if (time_left
> 172800)
347 else if (time_left
> 7200)
352 else if (time_left
> 120)
357 snprintf(buf
, 35, "warning (expires in %d %s%s)", time_left
,
358 unit
, (time_left
== 1)?
"":"s");
365 * Filter eliminating the directory entries '.' and '..'
368 file_select(const struct dirent
*entry
)
370 return strcmp(entry
->d_name
, "." ) &&
371 strcmp(entry
->d_name
, "..");