OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / freeswan / pluto / defs.c
1 /* misc. universal things
2  * Copyright (C) 1998-2001  D. Hugh Redelmeier.
3  *
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>.
8  *
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
12  * for more details.
13  *
14  * RCSID $Id: defs.c,v 1.20 2002/03/09 20:45:37 dhr Exp $
15  */
16
17 #include <stdlib.h>
18 #include <string.h>
19 #include <stdio.h>
20 #include <time.h>
21 #include <sys/types.h>
22
23 #include <freeswan.h>
24
25 #include "constants.h"
26 #include "defs.h"
27 #include "log.h"
28 #include "whack.h"      /* for RC_LOG_SERIOUS */
29
30 const chunk_t empty_chunk = { NULL, 0 };
31
32 bool
33 all_zero(const unsigned char *m, size_t len)
34 {
35     size_t i;
36
37     for (i = 0; i != len; i++)
38         if (m[i] != '\0')
39             return FALSE;
40     return TRUE;
41 }
42
43 /* Convert MP_INT to network form (binary octets, big-endian).
44  * We do the malloc; caller must eventually do free.
45  */
46 chunk_t
47 mpz_to_n(const MP_INT *mp, size_t bytes)
48 {
49     chunk_t r;
50     MP_INT temp1, temp2;
51     int i;
52
53     r.len = bytes;
54     r.ptr = alloc_bytes(r.len, "host representation of large integer");
55
56     mpz_init(&temp1);
57     mpz_init(&temp2);
58
59     mpz_set(&temp1, mp);
60
61     for (i = r.len-1; i >= 0; i--)
62     {
63         r.ptr[i] = mpz_mdivmod_ui(&temp2, NULL, &temp1, 1 << BITS_PER_BYTE);
64         mpz_set(&temp1, &temp2);
65     }
66
67     passert(mpz_sgn(&temp1) == 0);      /* we must have done all the bits */
68     mpz_clear(&temp1);
69     mpz_clear(&temp2);
70
71     return r;
72 }
73
74 /* Convert network form (binary bytes, big-endian) to MP_INT.
75  * The *mp must not be previously mpz_inited.
76  */
77 void
78 n_to_mpz(MP_INT *mp, const u_char *nbytes, size_t nlen)
79 {
80     size_t i;
81
82     mpz_init_set_ui(mp, 0);
83
84     for (i = 0; i != nlen; i++)
85     {
86         mpz_mul_ui(mp, mp, 1 << BITS_PER_BYTE);
87         mpz_add_ui(mp, mp, nbytes[i]);
88     }
89 }
90
91
92 /* memory allocation
93  *
94  * LEAK_DETECTIVE puts a wrapper around each allocation and maintains
95  * a list of live ones.  If a dead one is freed, an assertion MIGHT fail.
96  * If the live list is currupted, that will often be detected.
97  * In the end, report_leaks() is called, and the names of remaining
98  * live allocations are printed.  At the moment, it is hoped, not that
99  * the list is empty, but that there will be no surprises.
100  *
101  * Accepted Leaks:
102  * - "struct iface" and "device name" (for "discovered" net interfaces)
103  * - "struct event in event_schedule()" (events not associated with states)
104  * - "Pluto lock name" (one only, needed until end -- why bother?)
105  */
106
107 #ifdef LEAK_DETECTIVE
108
109 /* this magic number is 3671129837 decimal (623837458 complemented) */
110 #define LEAK_MAGIC 0xDAD0FEEDul
111
112 union mhdr {
113     struct {
114         const char *name;
115         union mhdr *older, *newer;
116         unsigned long magic;
117     } i;    /* info */
118     unsigned long junk; /* force maximal alignment */
119 };
120
121 static union mhdr *allocs = NULL;
122
123 void *alloc_bytes(size_t size, const char *name)
124 {
125         union mhdr *p = malloc(sizeof(union mhdr) + size);
126
127         if (p == NULL)
128                 exit_log("unable to malloc %lu bytes for %s",
129                         (unsigned long) size, name);
130         p->i.name = name;
131         p->i.older = allocs;
132         if (allocs != NULL)
133             allocs->i.newer = p;
134         allocs = p;
135         p->i.newer = NULL;
136         p->i.magic = LEAK_MAGIC;
137
138         memset(p+1, '\0', size);
139         return p+1;
140 }
141
142 void *
143 clone_bytes(const void *orig, size_t size, const char *name)
144 {
145         void *p = alloc_bytes(size, name);
146
147         memcpy(p, orig, size);
148         return p;
149 }
150
151 void
152 pfree(void *ptr)
153 {
154         union mhdr *p;
155
156         passert(ptr != NULL);
157         p = ((union mhdr *)ptr) - 1;
158         passert(p->i.magic == LEAK_MAGIC);
159         if (p->i.older != NULL)
160         {
161                 passert(p->i.older->i.newer == p);
162                 p->i.older->i.newer = p->i.newer;
163         }
164         if (p->i.newer == NULL)
165         {
166                 passert(p == allocs);
167                 allocs = p->i.older;
168         }
169         else
170         {
171                 passert(p->i.newer->i.older == p);
172                 p->i.newer->i.older = p->i.older;
173         }
174         p->i.magic = ~LEAK_MAGIC;
175         free(p);
176 }
177
178 void
179 report_leaks(void)
180 {
181         union mhdr
182                 *p = allocs,
183                 *pprev = NULL;
184         unsigned long n = 0;
185
186         while (p != NULL)
187         {
188                 passert(p->i.magic == LEAK_MAGIC);
189                 passert(pprev == p->i.newer);
190                 pprev = p;
191                 p = p->i.older;
192                 n++;
193                 if (p == NULL || pprev->i.name != p->i.name)
194                 {
195                         if (n != 1)
196                             log("leak: %lu * %s", n, pprev->i.name);
197                         else
198                             log("leak: %s", pprev->i.name);
199                         n = 0;
200                 }
201         }
202 }
203
204 #else /* !LEAK_DETECTIVE */
205
206 void *alloc_bytes(size_t size, const char *name)
207 {
208         void *p = malloc(size);
209
210         if (p == NULL)
211                 exit_log("unable to malloc %lu bytes for %s",
212                         (unsigned long) size, name);
213         memset(p, '\0', size);
214         return p;
215 }
216
217 void *clone_bytes(const void *orig, size_t size, const char *name)
218 {
219         void *p = malloc(size);
220
221         if (p == NULL)
222                 exit_log("unable to malloc %lu bytes for %s",
223                         (unsigned long) size, name);
224         memcpy(p, orig, size);
225         return p;
226 }
227 #endif /* !LEAK_DETECTIVE */
228
229
230 /* Names of the months */
231
232 static const char* months[] = {
233     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
234     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
235 };
236
237
238 /*
239  *  Display a date either in local or UTC time
240  */
241 char*
242 timetoa(const time_t *time, bool utc)
243 {
244     static char buf[TIMETOA_BUF];
245
246     if (*time == UNDEFINED_TIME)
247         sprintf(buf, "--- -- --:--:--%s----", (utc)?" UTC ":" ");
248     else
249     {
250         struct tm *t = (utc)? gmtime(time) : localtime(time);
251
252         sprintf(buf, "%s %02d %02d:%02d:%02d%s%04d",
253             months[t->tm_mon], t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec,
254             (utc)?" UTC ":" ", t->tm_year + 1900
255         );
256     }
257     return buf;
258 }
259
260 /*  checks if the expiration date has been reached and
261  *  warns during the warning_interval of the imminent
262  *  expiry. strict=TRUE declares a fatal error,
263  *  strict=FALSE issues a warning upon expiry.
264  */
265 const char*
266 check_expiry(time_t expiration_date, int warning_interval, bool strict)
267 {
268     time_t now;
269     int time_left;
270
271     if (expiration_date == UNDEFINED_TIME)
272       return "ok (expires never)";
273
274     /* determine the current time */
275     time(&now);
276
277     time_left = (expiration_date - now);
278     if (time_left < 0)
279         return strict? "fatal (expired)" : "warning (expired)";
280
281     if (time_left > 86400*warning_interval)
282         return "ok";
283     {
284         static char buf[35]; /* temporary storage */
285         const char* unit = "second";
286
287         if (time_left > 86400)
288         {
289             time_left /= 86400;
290             unit = "day";
291         }
292         else if (time_left > 3600)
293         {
294             time_left /= 3600;
295             unit = "hour";
296         }
297         else if (time_left > 60)
298         {
299             time_left /= 60;
300             unit = "minute";
301         }
302         snprintf(buf, 35, "warning (expires in %d %s%s)", time_left,
303                  unit, (time_left == 1)?"":"s");
304         return buf;
305     }
306 }
307