1 /*        $NetBSD: plog.c,v 1.9 2025/03/08 16:39:08 christos 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 
73 char *pname = NULL;
74 uint32_t loglevel = LLV_BASE;
75 int f_foreground = 0;
76 
77 int print_location = 0;
78 
79 static struct log *logp = NULL;
80 static char *logfile = NULL;
81 
82 static char *plog_common(int, const char *, const char *, struct sockaddr *);
83 
84 static struct plogtags {
85           const 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 
97 static char *
plog_common(int pri,const char * fmt,const char * func,struct sockaddr * sa)98 plog_common(int pri, const char *fmt, const char *func, struct sockaddr *sa)
99 {
100           static char buf[800];         /* XXX shoule be allocated every time ? */
101           void *addr;
102           char *p;
103           size_t reslen;
104           size_t len;
105 
106           p = buf;
107           reslen = sizeof(buf);
108 
109           if (logfile || f_foreground) {
110                     time_t t;
111                     struct tm *tm;
112 
113                     t = time(0);
114                     tm = localtime(&t);
115                     len = strftime(p, reslen, "%Y-%m-%d %T: ", tm);
116                     p += len;
117                     reslen -= len;
118           }
119 
120           if (sa && reslen > 3) {
121                     addr = NULL;
122                     switch (sa->sa_family) {
123                     case AF_INET:
124                               addr = &((struct sockaddr_in*)sa)->sin_addr;
125                               break;
126                     case AF_INET6:
127                               addr = &((struct sockaddr_in6*)sa)->sin6_addr;
128                               break;
129                     }
130                     if (inet_ntop(sa->sa_family, addr, p + 1, reslen - 3) != NULL) {
131                               *p++ = '[';
132                               len = strlen(p);
133                               p += len;
134                               *p++ = ']';
135                               *p++ = ' ';
136                               reslen -= len + 3;
137                     }
138           }
139 
140           if (pri < ARRAYLEN(ptab)) {
141                     len = snprintf(p, reslen, "%s: ", ptab[pri].name);
142                     p += len;
143                     reslen -= len;
144           }
145 
146           if (print_location)
147                     len = snprintf(p, reslen, "%s: %s", func, fmt);
148           else
149                     len = snprintf(p, reslen, "%s", fmt);
150           p += len;
151           reslen -= len;
152 
153           /* Force nul termination */
154           if (reslen == 0)
155                     p[-1] = 0;
156 
157 #ifdef BROKEN_PRINTF
158           while ((p = strstr(buf,"%z")) != NULL)
159                     p[1] = 'l';
160 #endif
161 
162           return buf;
163 }
164 
165 void
_plog(int pri,const char * func,struct sockaddr * sa,const char * fmt,...)166 _plog(int pri, const char *func, struct sockaddr *sa, const char *fmt, ...)
167 {
168           va_list ap;
169 
170           va_start(ap, fmt);
171           plogv(pri, func, sa, fmt, ap);
172           va_end(ap);
173 }
174 
175 void
plogv(int pri,const char * func,struct sockaddr * sa,const char * fmt,va_list ap)176 plogv(int pri, const char *func, struct sockaddr *sa,
177           const char *fmt, va_list ap)
178 {
179           char *newfmt;
180           va_list ap_bak;
181 
182           if (pri > loglevel)
183                     return;
184 
185           newfmt = plog_common(pri, fmt, func, sa);
186 
187           VA_COPY(ap_bak, ap);
188 
189           if (f_foreground)
190                     vprintf(newfmt, ap);
191 
192           if (logfile)
193                     log_vaprint(logp, newfmt, ap_bak);
194           else {
195                     if (pri < ARRAYLEN(ptab))
196                               vsyslog(ptab[pri].priority, newfmt, ap_bak);
197                     else
198                               vsyslog(LOG_ALERT, newfmt, ap_bak);
199           }
200 }
201 
202 void
plogdump(int pri,const void * data,size_t len)203 plogdump(int pri, const void *data, size_t len)
204 {
205           caddr_t buf;
206           size_t buflen;
207           int i, j;
208 
209           if (pri > loglevel)
210                     return;
211 
212           /*
213            * 2 words a bytes + 1 space 4 bytes + 1 newline 32 bytes
214            * + 2 newline + '\0'
215            */
216           buflen = (len * 2) + (len / 4) + (len / 32) + 3;
217           buf = racoon_malloc(buflen);
218 
219           i = 0;
220           j = 0;
221           while (j < len) {
222                     if (j % 32 == 0)
223                               buf[i++] = '\n';
224                     else
225                     if (j % 4 == 0)
226                               buf[i++] = ' ';
227                     snprintf(&buf[i], buflen - i, "%02x",
228                               ((const unsigned char *)data)[j] & 0xff);
229                     i += 2;
230                     j++;
231           }
232           if (buflen - i >= 2) {
233                     buf[i++] = '\n';
234                     buf[i] = '\0';
235           }
236           plog(pri, LOCATION, NULL, "%s", buf);
237 
238           racoon_free(buf);
239 }
240 
241 void
ploginit(void)242 ploginit(void)
243 {
244           if (logfile) {
245                     logp = log_open(250, logfile);
246                     if (logp == NULL)
247                               errx(1, "ERROR: failed to open log file %s.", logfile);
248                     return;
249           }
250 
251         openlog(pname, LOG_NDELAY, LOG_DAEMON);
252 }
253 
254 void
plogset(char * file)255 plogset(char *file)
256 {
257           if (logfile != NULL)
258                     racoon_free(logfile);
259           logfile = racoon_strdup(file);
260           STRDUP_FATAL(logfile);
261 }
262 
263 /*
264    Returns a printable string from (possibly) binary data ;
265    concatenates all unprintable chars to one space.
266    XXX Maybe the printable chars range is too large...
267  */
268 char*
binsanitize(char * binstr,size_t n)269 binsanitize(char *binstr, size_t n)
270 {
271           int p,q;
272           char* d;
273 
274           d = racoon_malloc(n + 1);
275           for (p = 0, q = 0; p < n; p++) {
276                     if (isgraph((unsigned char)binstr[p])) {
277                               d[q++] = binstr[p];
278                     } else {
279                               if (q && d[q - 1] != ' ')
280                                         d[q++] = ' ';
281                     }
282           }
283           d[q++] = '\0';
284 
285           return d;
286 }
287 
288