1/*	$NetBSD: plog.c,v 1.4.6.2 2009/04/20 13:35:36 tteras Exp $	*/
2
3/* Id: plog.c,v 1.11 2006/06/20 09:57:31 vanhu Exp */
4
5/*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "config.h"
35
36#include <sys/types.h>
37#include <sys/param.h>
38
39#include <stdlib.h>
40#include <stdio.h>
41#include <string.h>
42#include <errno.h>
43#ifdef HAVE_STDARG_H
44#include <stdarg.h>
45#else
46#include <varargs.h>
47#endif
48#if TIME_WITH_SYS_TIME
49# include <sys/time.h>
50# include <time.h>
51#else
52# if HAVE_SYS_TIME_H
53#  include <sys/time.h>
54# else
55#  include <time.h>
56# endif
57#endif
58#include <ctype.h>
59#include <err.h>
60
61#include "var.h"
62#include "misc.h"
63#include "plog.h"
64#include "logger.h"
65#include "debug.h"
66#include "gcmalloc.h"
67
68#ifndef VA_COPY
69# define VA_COPY(dst,src) memcpy(&(dst), &(src), sizeof(va_list))
70#endif
71
72char *pname = NULL;
73u_int32_t loglevel = LLV_BASE;
74int f_foreground = 0;
75
76int print_location = 0;
77
78static struct log *logp = NULL;
79static char *logfile = NULL;
80
81static char *plog_common __P((int, const char *, const char *));
82
83static struct plogtags {
84	char *name;
85	int priority;
86} ptab[] = {
87	{ "(not defined)",	0, },
88	{ "ERROR",		LOG_INFO, },
89	{ "WARNING",		LOG_INFO, },
90	{ "NOTIFY",		LOG_INFO, },
91	{ "INFO",		LOG_INFO, },
92	{ "DEBUG",		LOG_DEBUG, },
93	{ "DEBUG2",		LOG_DEBUG, },
94};
95
96static char *
97plog_common(pri, fmt, func)
98	int pri;
99	const char *fmt, *func;
100{
101	static char buf[800];	/* XXX shoule be allocated every time ? */
102	char *p;
103	int reslen, len;
104
105	p = buf;
106	reslen = sizeof(buf);
107
108	if (logfile || f_foreground) {
109		time_t t;
110		struct tm *tm;
111
112		t = time(0);
113		tm = localtime(&t);
114		len = strftime(p, reslen, "%Y-%m-%d %T: ", tm);
115		p += len;
116		reslen -= len;
117	}
118
119	if (pri < ARRAYLEN(ptab)) {
120		len = snprintf(p, reslen, "%s: ", ptab[pri].name);
121		if (len >= 0 && len < reslen) {
122			p += len;
123			reslen -= len;
124		} else
125			*p = '\0';
126	}
127
128	if (print_location)
129		snprintf(p, reslen, "%s: %s", func, fmt);
130	else
131		snprintf(p, reslen, "%s", fmt);
132#ifdef BROKEN_PRINTF
133	while ((p = strstr(buf,"%z")) != NULL)
134		p[1] = 'l';
135#endif
136
137	return buf;
138}
139
140void
141_plog(int pri, const char *func, struct sockaddr *sa, const char *fmt, ...)
142{
143	va_list ap;
144
145	va_start(ap, fmt);
146	plogv(pri, func, sa, fmt, ap);
147	va_end(ap);
148}
149
150void
151plogv(int pri, const char *func, struct sockaddr *sa,
152	const char *fmt, va_list ap)
153{
154	char *newfmt;
155	va_list ap_bak;
156
157	if (pri > loglevel)
158		return;
159
160	newfmt = plog_common(pri, fmt, func);
161
162	VA_COPY(ap_bak, ap);
163
164	if (f_foreground)
165		vprintf(newfmt, ap);
166
167	if (logfile)
168		log_vaprint(logp, newfmt, ap_bak);
169	else {
170		if (pri < ARRAYLEN(ptab))
171			vsyslog(ptab[pri].priority, newfmt, ap_bak);
172		else
173			vsyslog(LOG_ALERT, newfmt, ap_bak);
174	}
175}
176
177void
178plogdump(pri, data, len)
179	int pri;
180	void *data;
181	size_t len;
182{
183	caddr_t buf;
184	size_t buflen;
185	int i, j;
186
187	if (pri > loglevel)
188		return;
189
190	/*
191	 * 2 words a bytes + 1 space 4 bytes + 1 newline 32 bytes
192	 * + 2 newline + '\0'
193	 */
194	buflen = (len * 2) + (len / 4) + (len / 32) + 3;
195	buf = racoon_malloc(buflen);
196
197	i = 0;
198	j = 0;
199	while (j < len) {
200		if (j % 32 == 0)
201			buf[i++] = '\n';
202		else
203		if (j % 4 == 0)
204			buf[i++] = ' ';
205		snprintf(&buf[i], buflen - i, "%02x",
206			((unsigned char *)data)[j] & 0xff);
207		i += 2;
208		j++;
209	}
210	if (buflen - i >= 2) {
211		buf[i++] = '\n';
212		buf[i] = '\0';
213	}
214	plog(pri, LOCATION, NULL, "%s", buf);
215
216	racoon_free(buf);
217}
218
219void
220ploginit()
221{
222	if (logfile) {
223		logp = log_open(250, logfile);
224		if (logp == NULL)
225			errx(1, "ERROR: failed to open log file %s.", logfile);
226		return;
227	}
228
229        openlog(pname, LOG_NDELAY, LOG_DAEMON);
230}
231
232void
233plogset(file)
234	char *file;
235{
236	if (logfile != NULL)
237		racoon_free(logfile);
238	logfile = racoon_strdup(file);
239	STRDUP_FATAL(logfile);
240}
241
242/*
243   Returns a printable string from (possibly) binary data ;
244   concatenates all unprintable chars to one space.
245   XXX Maybe the printable chars range is too large...
246 */
247char*
248binsanitize(binstr, n)
249	char *binstr;
250	size_t n;
251{
252	int p,q;
253	char* d;
254
255	d = racoon_malloc(n + 1);
256	for (p = 0, q = 0; p < n; p++) {
257		if (isgraph((int)binstr[p])) {
258			d[q++] = binstr[p];
259		} else {
260			if (q && d[q - 1] != ' ')
261				d[q++] = ' ';
262		}
263	}
264	d[q++] = '\0';
265
266	return d;
267}
268
269