summaryrefslogtreecommitdiff
path: root/src/pluto/defs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pluto/defs.c')
-rw-r--r--src/pluto/defs.c374
1 files changed, 374 insertions, 0 deletions
diff --git a/src/pluto/defs.c b/src/pluto/defs.c
new file mode 100644
index 000000000..9ae32a480
--- /dev/null
+++ b/src/pluto/defs.c
@@ -0,0 +1,374 @@
+/* misc. universal things
+ * Copyright (C) 1998-2001 D. Hugh Redelmeier.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: defs.c,v 1.9 2006/01/04 21:00:43 as Exp $
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <freeswan.h>
+
+#include "constants.h"
+#include "defs.h"
+#include "log.h"
+#include "whack.h" /* for RC_LOG_SERIOUS */
+
+const chunk_t empty_chunk = { NULL, 0 };
+
+bool
+all_zero(const unsigned char *m, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i != len; i++)
+ if (m[i] != '\0')
+ return FALSE;
+ return TRUE;
+}
+
+/* memory allocation
+ *
+ * LEAK_DETECTIVE puts a wrapper around each allocation and maintains
+ * a list of live ones. If a dead one is freed, an assertion MIGHT fail.
+ * If the live list is currupted, that will often be detected.
+ * In the end, report_leaks() is called, and the names of remaining
+ * live allocations are printed. At the moment, it is hoped, not that
+ * the list is empty, but that there will be no surprises.
+ *
+ * Accepted Leaks:
+ * - "struct iface" and "device name" (for "discovered" net interfaces)
+ * - "struct event in event_schedule()" (events not associated with states)
+ * - "Pluto lock name" (one only, needed until end -- why bother?)
+ */
+
+#ifdef LEAK_DETECTIVE
+
+/* this magic number is 3671129837 decimal (623837458 complemented) */
+#define LEAK_MAGIC 0xDAD0FEEDul
+
+union mhdr {
+ struct {
+ const char *name;
+ union mhdr *older, *newer;
+ unsigned long magic;
+ } i; /* info */
+ unsigned long junk; /* force maximal alignment */
+};
+
+static union mhdr *allocs = NULL;
+
+void *alloc_bytes(size_t size, const char *name)
+{
+ union mhdr *p = malloc(sizeof(union mhdr) + size);
+
+ if (p == NULL)
+ exit_log("unable to malloc %lu bytes for %s"
+ , (unsigned long) size, name);
+ p->i.name = name;
+ p->i.older = allocs;
+ if (allocs != NULL)
+ allocs->i.newer = p;
+ allocs = p;
+ p->i.newer = NULL;
+ p->i.magic = LEAK_MAGIC;
+
+ memset(p+1, '\0', size);
+ return p+1;
+}
+
+void *
+clone_bytes(const void *orig, size_t size, const char *name)
+{
+ void *p = alloc_bytes(size, name);
+
+ memcpy(p, orig, size);
+ return p;
+}
+
+void
+pfree(void *ptr)
+{
+ union mhdr *p;
+
+ passert(ptr != NULL);
+ p = ((union mhdr *)ptr) - 1;
+ passert(p->i.magic == LEAK_MAGIC);
+ if (p->i.older != NULL)
+ {
+ passert(p->i.older->i.newer == p);
+ p->i.older->i.newer = p->i.newer;
+ }
+ if (p->i.newer == NULL)
+ {
+ passert(p == allocs);
+ allocs = p->i.older;
+ }
+ else
+ {
+ passert(p->i.newer->i.older == p);
+ p->i.newer->i.older = p->i.older;
+ }
+ p->i.magic = ~LEAK_MAGIC;
+ free(p);
+}
+
+void
+report_leaks(void)
+{
+ union mhdr
+ *p = allocs,
+ *pprev = NULL;
+ unsigned long n = 0;
+
+ while (p != NULL)
+ {
+ passert(p->i.magic == LEAK_MAGIC);
+ passert(pprev == p->i.newer);
+ pprev = p;
+ p = p->i.older;
+ n++;
+ if (p == NULL || pprev->i.name != p->i.name)
+ {
+ if (n != 1)
+ plog("leak: %lu * %s", n, pprev->i.name);
+ else
+ plog("leak: %s", pprev->i.name);
+ n = 0;
+ }
+ }
+}
+
+#else /* !LEAK_DETECTIVE */
+
+void *alloc_bytes(size_t size, const char *name)
+{
+ void *p = malloc(size);
+
+ if (p == NULL)
+ exit_log("unable to malloc %lu bytes for %s"
+ , (unsigned long) size, name);
+ memset(p, '\0', size);
+ return p;
+}
+
+void *clone_bytes(const void *orig, size_t size, const char *name)
+{
+ void *p = malloc(size);
+
+ if (p == NULL)
+ exit_log("unable to malloc %lu bytes for %s"
+ , (unsigned long) size, name);
+ memcpy(p, orig, size);
+ return p;
+}
+#endif /* !LEAK_DETECTIVE */
+
+/* Note that there may be as many as six IDs that are temporary at
+ * one time before unsharing the two ends of a connection. So we need
+ * at least six temporary buffers for DER_ASN1_DN IDs.
+ * We rotate them. Be careful!
+ */
+#define MAX_BUF 10
+
+char*
+temporary_cyclic_buffer(void)
+{
+ static char buf[MAX_BUF][BUF_LEN]; /* MAX_BUF internal buffers */
+ static int counter = 0; /* cyclic counter */
+
+ if (++counter == MAX_BUF) counter = 0; /* next internal buffer */
+ return buf[counter]; /* assign temporary buffer */
+}
+
+/* concatenates two sub paths into a string with a maximum size of BUF_LEN
+ * use for temporary storage only
+ */
+const char*
+concatenate_paths(const char *a, const char *b)
+{
+ char *c;
+
+ if (*b == '/' || *b == '.')
+ return b;
+
+ c = temporary_cyclic_buffer();
+ snprintf(c, BUF_LEN, "%s/%s", a, b);
+ return c;
+}
+
+/* compare two chunks, returns zero if a equals b
+ * negative/positive if a is earlier/later in the alphabet than b
+ */
+int
+cmp_chunk(chunk_t a, chunk_t b)
+{
+ int cmp_len, len, cmp_value;
+
+ cmp_len = a.len - b.len;
+ len = (cmp_len < 0)? a.len : b.len;
+ cmp_value = memcmp(a.ptr, b.ptr, len);
+
+ return (cmp_value == 0)? cmp_len : cmp_value;
+};
+
+/* moves a chunk to a memory position, chunk is freed afterwards
+ * position pointer is advanced after the insertion point
+ */
+void
+mv_chunk(u_char **pos, chunk_t content)
+{
+ if (content.len > 0)
+ {
+ chunkcpy(*pos, content);
+ freeanychunk(content);
+ }
+}
+
+/*
+ * write the binary contents of a chunk_t to a file
+ */
+bool
+write_chunk(const char *filename, const char *label, chunk_t ch
+, mode_t mask, bool force)
+{
+ mode_t oldmask;
+ FILE *fd;
+
+ if (!force)
+ {
+ fd = fopen(filename, "r");
+ if (fd)
+ {
+ fclose(fd);
+ plog(" %s file '%s' already exists", label, filename);
+ return FALSE;
+ }
+ }
+
+ /* set umask */
+ oldmask = umask(mask);
+
+ fd = fopen(filename, "w");
+
+ if (fd)
+ {
+ fwrite(ch.ptr, sizeof(u_char), ch.len, fd);
+ fclose(fd);
+ plog(" written %s file '%s' (%d bytes)", label, filename, (int)ch.len);
+ umask(oldmask);
+ return TRUE;
+ }
+ else
+ {
+ plog(" could not open %s file '%s' for writing", label, filename);
+ umask(oldmask);
+ return FALSE;
+ }
+}
+
+/* Names of the months */
+
+static const char* months[] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+
+/*
+ * Display a date either in local or UTC time
+ */
+char*
+timetoa(const time_t *time, bool utc)
+{
+ static char buf[TIMETOA_BUF];
+
+ if (*time == UNDEFINED_TIME)
+ sprintf(buf, "--- -- --:--:--%s----", (utc)?" UTC ":" ");
+ else
+ {
+ struct tm *t = (utc)? gmtime(time) : localtime(time);
+
+ sprintf(buf, "%s %02d %02d:%02d:%02d%s%04d",
+ months[t->tm_mon], t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec,
+ (utc)?" UTC ":" ", t->tm_year + 1900
+ );
+ }
+ return buf;
+}
+
+/* checks if the expiration date has been reached and
+ * warns during the warning_interval of the imminent
+ * expiry. strict=TRUE declares a fatal error,
+ * strict=FALSE issues a warning upon expiry.
+ */
+const char*
+check_expiry(time_t expiration_date, int warning_interval, bool strict)
+{
+ time_t now;
+ int time_left;
+
+ if (expiration_date == UNDEFINED_TIME)
+ return "ok (expires never)";
+
+ /* determine the current time */
+ time(&now);
+
+ time_left = (expiration_date - now);
+ if (time_left < 0)
+ return strict? "fatal (expired)" : "warning (expired)";
+
+ if (time_left > 86400*warning_interval)
+ return "ok";
+ {
+ static char buf[35]; /* temporary storage */
+ const char* unit = "second";
+
+ if (time_left > 172800)
+ {
+ time_left /= 86400;
+ unit = "day";
+ }
+ else if (time_left > 7200)
+ {
+ time_left /= 3600;
+ unit = "hour";
+ }
+ else if (time_left > 120)
+ {
+ time_left /= 60;
+ unit = "minute";
+ }
+ snprintf(buf, 35, "warning (expires in %d %s%s)", time_left,
+ unit, (time_left == 1)?"":"s");
+ return buf;
+ }
+}
+
+
+/*
+ * Filter eliminating the directory entries '.' and '..'
+ */
+int
+file_select(const struct dirent *entry)
+{
+ return strcmp(entry->d_name, "." ) &&
+ strcmp(entry->d_name, "..");
+}
+
+