log.c revision 1.6
1/*	$OpenBSD: log.c,v 1.6 1999/04/19 19:53:41 niklas Exp $	*/
2/*	$EOM: log.c,v 1.23 1999/04/18 15:17:24 niklas Exp $	*/
3
4/*
5 * Copyright (c) 1998, 1999 Niklas Hallqvist.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by Ericsson Radio Systems.
18 * 4. The name of the author may not be used to endorse or promote products
19 *    derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * This code was written under funding by Ericsson Radio Systems.
35 */
36
37#include <sys/time.h>
38#include <errno.h>
39#include <stdio.h>
40#include <string.h>
41#include <syslog.h>
42#ifdef __STDC__
43#include <stdarg.h>
44#else
45#include <varargs.h>
46#endif
47
48#include "sysdep.h"
49
50#include "log.h"
51
52static void _log_print (int, int, const char *, va_list, int, int);
53
54static FILE *log_output = stderr;
55static int log_level[LOG_ENDCLASS];
56
57void
58log_to (FILE *f)
59{
60  if (!log_output && f)
61    closelog ();
62  log_output = f;
63  if (!f)
64    openlog ("isakmpd", LOG_CONS, LOG_DAEMON);
65}
66
67FILE *
68log_current (void)
69{
70  return log_output;
71}
72
73static char *
74_log_get_class (int error_class)
75{
76  /* XXX For test purposes. To be removed later on?  */
77  static char *class_text[] = LOG_CLASSES_TEXT;
78
79  if (error_class < 0)
80    return "Dflt";
81  else if (error_class >= LOG_ENDCLASS)
82    return "Unkn";
83  else
84    return class_text[error_class];
85}
86
87static void
88_log_print (int error, int syslog_level, const char *fmt, va_list ap,
89	    int class, int level)
90{
91  char buffer[LOG_SIZE], nbuf[LOG_SIZE + 32];
92  static const char fallback_msg[] =
93    "write to log file failed (errno %d), redirecting output to syslog";
94  int len;
95  struct tm *tm;
96  struct timeval now;
97  time_t t;
98
99  len = vsnprintf (buffer, LOG_SIZE, fmt, ap);
100  if (len < LOG_SIZE - 1 && error)
101    snprintf (buffer + len, LOG_SIZE - len, ": %s", strerror (errno));
102  if (log_output)
103    {
104      gettimeofday (&now, 0);
105      t = now.tv_sec;
106      tm = localtime (&t);
107      if (class >= 0)
108	sprintf (nbuf, "%02d%02d%02d.%06ld %s %02d ", tm->tm_hour,
109		 tm->tm_min, tm->tm_sec, now.tv_usec, _log_get_class (class),
110		 level);
111      else /* LOG_PRINT (-1) or LOG_REPORT (-2) */
112	sprintf (nbuf, "%02d%02d%02d.%06ld %s ", tm->tm_hour,
113		 tm->tm_min, tm->tm_sec, now.tv_usec,
114		 class == LOG_PRINT ? "Default" : "Report>");
115      strcat (nbuf, buffer);
116      strcat (nbuf, "\n");
117
118      if (fwrite (nbuf, strlen (nbuf), 1, log_output) == 0)
119	{
120	  /* Report fallback.  */
121	  syslog (LOG_ALERT, fallback_msg, errno);
122	  fprintf (log_output, fallback_msg, errno);
123
124	  /* Fallback to syslog.  */
125	  log_to (0);
126
127	  /* (Re)send current message to syslog(). */
128	  syslog (class == LOG_REPORT ? LOG_ALERT : syslog_level, buffer);
129	}
130    }
131  else
132    syslog (class == LOG_REPORT ? LOG_ALERT : syslog_level, buffer);
133}
134
135void
136#ifdef __STDC__
137log_debug (int cls, int level, const char *fmt, ...)
138#else
139log_debug (cls, level, fmt, va_alist)
140     int cls;
141     int level;
142     const char *fmt;
143     va_dcl
144#endif
145{
146  va_list ap;
147
148  /*
149   * If we are not debugging this class, or the level is too low, just return.
150   */
151  if (cls >= 0 && (log_level[cls] == 0 || level > log_level[cls]))
152    return;
153#ifdef __STDC__
154  va_start (ap, fmt);
155#else
156  va_start (ap);
157  fmt = va_arg (ap, const char *);
158#endif
159  _log_print (0, LOG_DEBUG, fmt, ap, cls, level);
160  va_end (ap);
161}
162
163void
164log_debug_buf (int cls, int level, const char *header, const u_int8_t *buf,
165	       size_t sz)
166{
167  char s[73];
168  int i, j;
169
170  /*
171   * If we are not debugging this class, or the level is too low, just return.
172   */
173  if (cls >= 0 && (log_level[cls] == 0 || level > log_level[cls]))
174    return;
175
176  log_debug (cls, level, "%s:", header);
177  for (i = j = 0; i < sz;)
178    {
179      sprintf (s + j, "%02x", buf[i++]);
180      j += 2;
181      if (i % 4 == 0)
182	{
183	  if (i % 32 == 0)
184	    {
185	      s[j] = '\0';
186	      log_debug (cls, level, "%s", s);
187	      j = 0;
188	    }
189	  else
190	    s[j++] = ' ';
191	}
192    }
193  if (j)
194    {
195      s[j] = '\0';
196      log_debug (cls, level, "%s", s);
197    }
198}
199
200void
201#ifdef __STDC__
202log_print (const char *fmt, ...)
203#else
204log_print (fmt, va_alist)
205     const char *fmt;
206     va_dcl
207#endif
208{
209  va_list ap;
210
211#ifdef __STDC__
212  va_start (ap, fmt);
213#else
214  va_start (ap);
215  fmt = va_arg (ap, const char *);
216#endif
217  _log_print (0, LOG_NOTICE, fmt, ap, LOG_PRINT, 0);
218  va_end (ap);
219}
220
221void
222#ifdef __STDC__
223log_error (const char *fmt, ...)
224#else
225log_error (fmt, va_alist)
226     const char *fmt;
227     va_dcl
228#endif
229{
230  va_list ap;
231
232#ifdef __STDC__
233  va_start (ap, fmt);
234#else
235  va_start (ap);
236  fmt = va_arg (ap, const char *);
237#endif
238  _log_print (1, LOG_ERR, fmt, ap, LOG_PRINT, 0);
239  va_end (ap);
240}
241
242void
243#ifdef __STDC__
244log_fatal (const char *fmt, ...)
245#else
246log_fatal (fmt, va_alist)
247     const char *fmt;
248     va_dcl
249#endif
250{
251  va_list ap;
252
253#ifdef __STDC__
254  va_start (ap, fmt);
255#else
256  va_start (ap);
257  fmt = va_arg (ap, const char *);
258#endif
259  _log_print (1, LOG_CRIT, fmt, ap, LOG_PRINT, 0);
260  va_end (ap);
261  exit (1);
262}
263
264void
265log_debug_cmd (int cls, int level)
266{
267  if (cls < 0 || cls >= LOG_ENDCLASS)
268    {
269      log_print ("log_debug_cmd: invalid debugging class %d", cls);
270      return;
271    }
272
273  if (level < 0)
274    {
275      log_print ("log_debug_cmd: invalid debugging level %d for class %d",
276		 level, cls);
277      return;
278    }
279
280  if (level == log_level[cls])
281    log_print ("log_debug_cmd: log level unchanged for class %d", cls);
282  else
283    {
284      log_print ("log_debug_cmd: log level changed from %d to %d for class %d",
285		 log_level[cls], level, cls);
286      log_level[cls] = level;
287    }
288}
289