1/*	$NetBSD: plog.c,v 1.7 2011/01/28 12:51:40 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 <arpa/inet.h>
40#include <stdlib.h>
41#include <stdio.h>
42#include <string.h>
43#include <errno.h>
44#ifdef HAVE_STDARG_H
45#include <stdarg.h>
46#else
47#include <varargs.h>
48#endif
49#if TIME_WITH_SYS_TIME
50# include <sys/time.h>
51# include <time.h>
52#else
53# if HAVE_SYS_TIME_H
54#  include <sys/time.h>
55# else
56#  include <time.h>
57# endif
58#endif
59#include <ctype.h>
60#include <err.h>
61
62#include "var.h"
63#include "misc.h"
64#include "plog.h"
65#include "logger.h"
66#include "debug.h"
67#include "gcmalloc.h"
68
69#ifndef VA_COPY
70# define VA_COPY(dst,src) memcpy(&(dst), &(src), sizeof(va_list))
71#endif
72
73char *pname = NULL;
74u_int32_t loglevel = LLV_BASE;
75int f_foreground = 0;
76
77int print_location = 0;
78
79static struct log *logp = NULL;
80static char *logfile = NULL;
81
82static char *plog_common __P((int, const char *, const char *, struct sockaddr *));
83
84static struct plogtags {
85	char *name;
86	int priority;
87} ptab[] = {
88	{ "(not defined)",	0, },
89	{ "ERROR",		LOG_INFO, },
90	{ "WARNING",		LOG_INFO, },
91	{ "NOTIFY",		LOG_INFO, },
92	{ "INFO",		LOG_INFO, },
93	{ "DEBUG",		LOG_DEBUG, },
94	{ "DEBUG2",		LOG_DEBUG, },
95};
96
97static char *
98plog_common(pri, fmt, func, sa)
99	int pri;
100	const char *fmt, *func;
101	struct sockaddr *sa;
102{
103	static char buf[800];	/* XXX shoule be allocated every time ? */
104	void *addr;
105	char *p;
106	int reslen, len;
107
108	p = buf;
109	reslen = sizeof(buf);
110
111	if (logfile || f_foreground) {
112		time_t t;
113		struct tm *tm;
114
115		t = time(0);
116		tm = localtime(&t);
117		len = strftime(p, reslen, "%Y-%m-%d %T: ", tm);
118		p += len;
119		reslen -= len;
120	}
121
122	if (sa && reslen > 3) {
123		addr = NULL;
124		switch (sa->sa_family) {
125		case AF_INET:
126			addr = &((struct sockaddr_in*)sa)->sin_addr;
127			break;
128		case AF_INET6:
129			addr = &((struct sockaddr_in6*)sa)->sin6_addr;
130			break;
131		}
132		if (inet_ntop(sa->sa_family, addr, p + 1, reslen - 3) != NULL) {
133			*p++ = '[';
134			len = strlen(p);
135			p += len;
136			*p++ = ']';
137			*p++ = ' ';
138			reslen -= len + 3;
139		}
140	}
141
142	if (pri < ARRAYLEN(ptab)) {
143		len = snprintf(p, reslen, "%s: ", ptab[pri].name);
144		p += len;
145		reslen -= len;
146	}
147
148	if (print_location)
149		len = snprintf(p, reslen, "%s: %s", func, fmt);
150	else
151		len = snprintf(p, reslen, "%s", fmt);
152	p += len;
153	reslen -= len;
154
155	/* Force nul termination */
156	if (reslen == 0)
157		p[-1] = 0;
158
159#ifdef BROKEN_PRINTF
160	while ((p = strstr(buf,"%z")) != NULL)
161		p[1] = 'l';
162#endif
163
164	return buf;
165}
166
167void
168_plog(int pri, const char *func, struct sockaddr *sa, const char *fmt, ...)
169{
170	va_list ap;
171
172	va_start(ap, fmt);
173	plogv(pri, func, sa, fmt, ap);
174	va_end(ap);
175}
176
177void
178plogv(int pri, const char *func, struct sockaddr *sa,
179	const char *fmt, va_list ap)
180{
181	char *newfmt;
182	va_list ap_bak;
183
184	if (pri > loglevel)
185		return;
186
187	newfmt = plog_common(pri, fmt, func, sa);
188
189	VA_COPY(ap_bak, ap);
190
191	if (f_foreground)
192		vprintf(newfmt, ap);
193
194	if (logfile)
195		log_vaprint(logp, newfmt, ap_bak);
196	else {
197		if (pri < ARRAYLEN(ptab))
198			vsyslog(ptab[pri].priority, newfmt, ap_bak);
199		else
200			vsyslog(LOG_ALERT, newfmt, ap_bak);
201	}
202}
203
204void
205plogdump(pri, data, len)
206	int pri;
207	void *data;
208	size_t len;
209{
210	caddr_t buf;
211	size_t buflen;
212	int i, j;
213
214	if (pri > loglevel)
215		return;
216
217	/*
218	 * 2 words a bytes + 1 space 4 bytes + 1 newline 32 bytes
219	 * + 2 newline + '\0'
220	 */
221	buflen = (len * 2) + (len / 4) + (len / 32) + 3;
222	buf = racoon_malloc(buflen);
223
224	i = 0;
225	j = 0;
226	while (j < len) {
227		if (j % 32 == 0)
228			buf[i++] = '\n';
229		else
230		if (j % 4 == 0)
231			buf[i++] = ' ';
232		snprintf(&buf[i], buflen - i, "%02x",
233			((unsigned char *)data)[j] & 0xff);
234		i += 2;
235		j++;
236	}
237	if (buflen - i >= 2) {
238		buf[i++] = '\n';
239		buf[i] = '\0';
240	}
241	plog(pri, LOCATION, NULL, "%s", buf);
242
243	racoon_free(buf);
244}
245
246void
247ploginit()
248{
249	if (logfile) {
250		logp = log_open(250, logfile);
251		if (logp == NULL)
252			errx(1, "ERROR: failed to open log file %s.", logfile);
253		return;
254	}
255
256        openlog(pname, LOG_NDELAY, LOG_DAEMON);
257}
258
259void
260plogset(file)
261	char *file;
262{
263	if (logfile != NULL)
264		racoon_free(logfile);
265	logfile = racoon_strdup(file);
266	STRDUP_FATAL(logfile);
267}
268
269/*
270   Returns a printable string from (possibly) binary data ;
271   concatenates all unprintable chars to one space.
272   XXX Maybe the printable chars range is too large...
273 */
274char*
275binsanitize(binstr, n)
276	char *binstr;
277	size_t n;
278{
279	int p,q;
280	char* d;
281
282	d = racoon_malloc(n + 1);
283	for (p = 0, q = 0; p < n; p++) {
284		if (isgraph((int)binstr[p])) {
285			d[q++] = binstr[p];
286		} else {
287			if (q && d[q - 1] != ' ')
288				d[q++] = ' ';
289		}
290	}
291	d[q++] = '\0';
292
293	return d;
294}
295
296