2 * util/log.c - implementation of the log code
4 * Copyright (c) 2007, NLnet Labs. All rights reserved.
6 * This software is open source.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
19 * Neither the name of the NLNET LABS nor the names of its contributors may
20 * be used to endorse or promote products derived from this software without
21 * specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 * Implementation of log.h.
42 #include "util/locks.h"
43 #include "ldns/sbuffer.h"
51 /**define LOG_ constants */
54 # define LOG_WARNING 4
60 # include "winrc/win_svc.h"
63 /* default verbosity */
64 enum verbosity_value verbosity
= 0;
65 /** the file logged to. */
66 static FILE* logfile
= 0;
67 /** if key has been created */
68 static int key_created
= 0;
69 /** pthread key for thread ids in logfile */
70 static ub_thread_key_t logkey
;
71 #ifndef THREADS_DISABLED
72 /** pthread mutex to protect FILE* */
73 static lock_quick_t log_lock
;
75 /** the identity of this executable/process */
76 static const char* ident
="unbound";
77 #if defined(HAVE_SYSLOG_H) || defined(UB_ON_WINDOWS)
78 /** are we using syslog(3) to log to */
79 static int logging_to_syslog
= 0;
80 #endif /* HAVE_SYSLOG_H */
81 /** time to print in log, if NULL, use time(2) */
82 static time_t* log_now
= NULL
;
83 /** print time in UTC or in secondsfrom1970 */
84 static int log_time_asc
= 0;
87 log_init(const char* filename
, int use_syslog
, const char* chrootdir
)
92 ub_thread_key_create(&logkey
, NULL
);
93 lock_quick_init(&log_lock
);
95 lock_quick_lock(&log_lock
);
97 #if defined(HAVE_SYSLOG_H) || defined(UB_ON_WINDOWS)
101 lock_quick_unlock(&log_lock
); /* verbose() needs the lock */
102 verbose(VERB_QUERY
, "switching log to %s",
103 use_syslog
?"syslog":(filename
&&filename
[0]?filename
:"stderr"));
104 lock_quick_lock(&log_lock
);
106 if(logfile
&& logfile
!= stderr
)
109 if(logging_to_syslog
) {
111 logging_to_syslog
= 0;
114 /* do not delay opening until first write, because we may
115 * chroot and no longer be able to access dev/log and so on */
116 openlog(ident
, LOG_NDELAY
, LOG_DAEMON
);
117 logging_to_syslog
= 1;
118 lock_quick_unlock(&log_lock
);
121 #elif defined(UB_ON_WINDOWS)
122 if(logging_to_syslog
) {
123 logging_to_syslog
= 0;
126 logging_to_syslog
= 1;
127 lock_quick_unlock(&log_lock
);
130 #endif /* HAVE_SYSLOG_H */
131 if(!filename
|| !filename
[0]) {
133 lock_quick_unlock(&log_lock
);
136 /* open the file for logging */
137 if(chrootdir
&& chrootdir
[0] && strncmp(filename
, chrootdir
,
138 strlen(chrootdir
)) == 0)
139 filename
+= strlen(chrootdir
);
140 f
= fopen(filename
, "a");
142 lock_quick_unlock(&log_lock
);
143 log_err("Could not open logfile %s: %s", filename
,
147 #ifndef UB_ON_WINDOWS
148 /* line buffering does not work on windows */
149 setvbuf(f
, NULL
, (int)_IOLBF
, 0);
152 lock_quick_unlock(&log_lock
);
155 void log_file(FILE *f
)
157 lock_quick_lock(&log_lock
);
159 lock_quick_unlock(&log_lock
);
162 void log_thread_set(int* num
)
164 ub_thread_key_set(logkey
, num
);
167 void log_ident_set(const char* id
)
172 void log_set_time(time_t* t
)
177 void log_set_time_asc(int use_asc
)
179 log_time_asc
= use_asc
;
183 log_vmsg(int pri
, const char* type
,
184 const char *format
, va_list args
)
186 char message
[MAXSYSLOGMSGLEN
];
187 unsigned int* tid
= (unsigned int*)ub_thread_key_get(logkey
);
189 #if defined(HAVE_STRFTIME) && defined(HAVE_LOCALTIME_R)
192 #elif defined(UB_ON_WINDOWS)
193 char tmbuf
[128], dtbuf
[128];
196 vsnprintf(message
, sizeof(message
), format
, args
);
198 if(logging_to_syslog
) {
199 syslog(pri
, "[%d:%x] %s: %s",
200 (int)getpid(), tid
?*tid
:0, type
, message
);
203 #elif defined(UB_ON_WINDOWS)
204 if(logging_to_syslog
) {
208 DWORD tp
= MSG_GENERIC_ERR
;
209 WORD wt
= EVENTLOG_ERROR_TYPE
;
210 if(strcmp(type
, "info") == 0) {
212 wt
=EVENTLOG_INFORMATION_TYPE
;
213 } else if(strcmp(type
, "warning") == 0) {
215 wt
=EVENTLOG_WARNING_TYPE
;
216 } else if(strcmp(type
, "notice") == 0
217 || strcmp(type
, "debug") == 0) {
218 tp
=MSG_GENERIC_SUCCESS
;
221 snprintf(m
, sizeof(m
), "[%s:%x] %s: %s",
222 ident
, tid
?*tid
:0, type
, message
);
223 s
= RegisterEventSource(NULL
, SERVICE_NAME
);
225 ReportEvent(s
, wt
, 0, tp
, NULL
, 1, 0, &str
, NULL
);
226 DeregisterEventSource(s
);
229 #endif /* HAVE_SYSLOG_H */
230 lock_quick_lock(&log_lock
);
232 lock_quick_unlock(&log_lock
);
236 now
= (time_t)*log_now
;
237 else now
= (time_t)time(NULL
);
238 #if defined(HAVE_STRFTIME) && defined(HAVE_LOCALTIME_R)
239 if(log_time_asc
&& strftime(tmbuf
, sizeof(tmbuf
), "%b %d %H:%M:%S",
240 localtime_r(&now
, &tm
))%(sizeof(tmbuf
)) != 0) {
241 /* %sizeof buf!=0 because old strftime returned max on error */
242 fprintf(logfile
, "%s %s[%d:%x] %s: %s\n", tmbuf
,
243 ident
, (int)getpid(), tid
?*tid
:0, type
, message
);
245 #elif defined(UB_ON_WINDOWS)
246 if(log_time_asc
&& GetTimeFormat(LOCALE_USER_DEFAULT
, 0, NULL
, NULL
,
247 tmbuf
, sizeof(tmbuf
)) && GetDateFormat(LOCALE_USER_DEFAULT
, 0,
248 NULL
, NULL
, dtbuf
, sizeof(dtbuf
))) {
249 fprintf(logfile
, "%s %s %s[%d:%x] %s: %s\n", dtbuf
, tmbuf
,
250 ident
, (int)getpid(), tid
?*tid
:0, type
, message
);
253 fprintf(logfile
, "[" ARG_LL
"d] %s[%d:%x] %s: %s\n", (long long)now
,
254 ident
, (int)getpid(), tid
?*tid
:0, type
, message
);
256 /* line buffering does not work on windows */
259 lock_quick_unlock(&log_lock
);
263 * implementation of log_info
264 * @param format: format string printf-style.
267 log_info(const char *format
, ...)
270 va_start(args
, format
);
271 log_vmsg(LOG_INFO
, "info", format
, args
);
276 * implementation of log_err
277 * @param format: format string printf-style.
280 log_err(const char *format
, ...)
283 va_start(args
, format
);
284 log_vmsg(LOG_ERR
, "error", format
, args
);
289 * implementation of log_warn
290 * @param format: format string printf-style.
293 log_warn(const char *format
, ...)
296 va_start(args
, format
);
297 log_vmsg(LOG_WARNING
, "warning", format
, args
);
302 * implementation of fatal_exit
303 * @param format: format string printf-style.
306 fatal_exit(const char *format
, ...)
309 va_start(args
, format
);
310 log_vmsg(LOG_CRIT
, "fatal error", format
, args
);
316 * implementation of verbose
317 * @param level: verbose level for the message.
318 * @param format: format string printf-style.
321 verbose(enum verbosity_value level
, const char* format
, ...)
324 va_start(args
, format
);
325 if(verbosity
>= level
) {
326 if(level
== VERB_OPS
)
327 log_vmsg(LOG_NOTICE
, "notice", format
, args
);
328 else if(level
== VERB_DETAIL
)
329 log_vmsg(LOG_INFO
, "info", format
, args
);
330 else log_vmsg(LOG_DEBUG
, "debug", format
, args
);
337 log_hex_f(enum verbosity_value v
, const char* msg
, void* data
, size_t length
)
340 uint8_t* data8
= (uint8_t*)data
;
341 const char* hexchar
= "0123456789ABCDEF";
342 char buf
[1024+1]; /* alloc blocksize hex chars + \0 */
343 const size_t blocksize
= 512;
347 verbose(v
, "%s[%u]", msg
, (unsigned)length
);
351 for(i
=0; i
<length
; i
+=blocksize
/2) {
353 if(length
- i
< blocksize
/2)
355 for(j
=0; j
<len
; j
++) {
356 buf
[j
*2] = hexchar
[ data8
[i
+j
] >> 4 ];
357 buf
[j
*2 + 1] = hexchar
[ data8
[i
+j
] & 0xF ];
360 verbose(v
, "%s[%u:%u] %.*s", msg
, (unsigned)length
,
361 (unsigned)i
, (int)len
*2, buf
);
366 log_hex(const char* msg
, void* data
, size_t length
)
368 log_hex_f(verbosity
, msg
, data
, length
);
371 void log_buf(enum verbosity_value level
, const char* msg
, sldns_buffer
* buf
)
373 if(verbosity
< level
)
375 log_hex_f(level
, msg
, sldns_buffer_begin(buf
), sldns_buffer_limit(buf
));
379 char* wsa_strerror(DWORD err
)
381 static char unknown
[32];
384 case WSA_INVALID_HANDLE
: return "Specified event object handle is invalid.";
385 case WSA_NOT_ENOUGH_MEMORY
: return "Insufficient memory available.";
386 case WSA_INVALID_PARAMETER
: return "One or more parameters are invalid.";
387 case WSA_OPERATION_ABORTED
: return "Overlapped operation aborted.";
388 case WSA_IO_INCOMPLETE
: return "Overlapped I/O event object not in signaled state.";
389 case WSA_IO_PENDING
: return "Overlapped operations will complete later.";
390 case WSAEINTR
: return "Interrupted function call.";
391 case WSAEBADF
: return "File handle is not valid.";
392 case WSAEACCES
: return "Permission denied.";
393 case WSAEFAULT
: return "Bad address.";
394 case WSAEINVAL
: return "Invalid argument.";
395 case WSAEMFILE
: return "Too many open files.";
396 case WSAEWOULDBLOCK
: return "Resource temporarily unavailable.";
397 case WSAEINPROGRESS
: return "Operation now in progress.";
398 case WSAEALREADY
: return "Operation already in progress.";
399 case WSAENOTSOCK
: return "Socket operation on nonsocket.";
400 case WSAEDESTADDRREQ
: return "Destination address required.";
401 case WSAEMSGSIZE
: return "Message too long.";
402 case WSAEPROTOTYPE
: return "Protocol wrong type for socket.";
403 case WSAENOPROTOOPT
: return "Bad protocol option.";
404 case WSAEPROTONOSUPPORT
: return "Protocol not supported.";
405 case WSAESOCKTNOSUPPORT
: return "Socket type not supported.";
406 case WSAEOPNOTSUPP
: return "Operation not supported.";
407 case WSAEPFNOSUPPORT
: return "Protocol family not supported.";
408 case WSAEAFNOSUPPORT
: return "Address family not supported by protocol family.";
409 case WSAEADDRINUSE
: return "Address already in use.";
410 case WSAEADDRNOTAVAIL
: return "Cannot assign requested address.";
411 case WSAENETDOWN
: return "Network is down.";
412 case WSAENETUNREACH
: return "Network is unreachable.";
413 case WSAENETRESET
: return "Network dropped connection on reset.";
414 case WSAECONNABORTED
: return "Software caused connection abort.";
415 case WSAECONNRESET
: return "Connection reset by peer.";
416 case WSAENOBUFS
: return "No buffer space available.";
417 case WSAEISCONN
: return "Socket is already connected.";
418 case WSAENOTCONN
: return "Socket is not connected.";
419 case WSAESHUTDOWN
: return "Cannot send after socket shutdown.";
420 case WSAETOOMANYREFS
: return "Too many references.";
421 case WSAETIMEDOUT
: return "Connection timed out.";
422 case WSAECONNREFUSED
: return "Connection refused.";
423 case WSAELOOP
: return "Cannot translate name.";
424 case WSAENAMETOOLONG
: return "Name too long.";
425 case WSAEHOSTDOWN
: return "Host is down.";
426 case WSAEHOSTUNREACH
: return "No route to host.";
427 case WSAENOTEMPTY
: return "Directory not empty.";
428 case WSAEPROCLIM
: return "Too many processes.";
429 case WSAEUSERS
: return "User quota exceeded.";
430 case WSAEDQUOT
: return "Disk quota exceeded.";
431 case WSAESTALE
: return "Stale file handle reference.";
432 case WSAEREMOTE
: return "Item is remote.";
433 case WSASYSNOTREADY
: return "Network subsystem is unavailable.";
434 case WSAVERNOTSUPPORTED
: return "Winsock.dll version out of range.";
435 case WSANOTINITIALISED
: return "Successful WSAStartup not yet performed.";
436 case WSAEDISCON
: return "Graceful shutdown in progress.";
437 case WSAENOMORE
: return "No more results.";
438 case WSAECANCELLED
: return "Call has been canceled.";
439 case WSAEINVALIDPROCTABLE
: return "Procedure call table is invalid.";
440 case WSAEINVALIDPROVIDER
: return "Service provider is invalid.";
441 case WSAEPROVIDERFAILEDINIT
: return "Service provider failed to initialize.";
442 case WSASYSCALLFAILURE
: return "System call failure.";
443 case WSASERVICE_NOT_FOUND
: return "Service not found.";
444 case WSATYPE_NOT_FOUND
: return "Class type not found.";
445 case WSA_E_NO_MORE
: return "No more results.";
446 case WSA_E_CANCELLED
: return "Call was canceled.";
447 case WSAEREFUSED
: return "Database query was refused.";
448 case WSAHOST_NOT_FOUND
: return "Host not found.";
449 case WSATRY_AGAIN
: return "Nonauthoritative host not found.";
450 case WSANO_RECOVERY
: return "This is a nonrecoverable error.";
451 case WSANO_DATA
: return "Valid name, no data record of requested type.";
452 case WSA_QOS_RECEIVERS
: return "QOS receivers.";
453 case WSA_QOS_SENDERS
: return "QOS senders.";
454 case WSA_QOS_NO_SENDERS
: return "No QOS senders.";
455 case WSA_QOS_NO_RECEIVERS
: return "QOS no receivers.";
456 case WSA_QOS_REQUEST_CONFIRMED
: return "QOS request confirmed.";
457 case WSA_QOS_ADMISSION_FAILURE
: return "QOS admission error.";
458 case WSA_QOS_POLICY_FAILURE
: return "QOS policy failure.";
459 case WSA_QOS_BAD_STYLE
: return "QOS bad style.";
460 case WSA_QOS_BAD_OBJECT
: return "QOS bad object.";
461 case WSA_QOS_TRAFFIC_CTRL_ERROR
: return "QOS traffic control error.";
462 case WSA_QOS_GENERIC_ERROR
: return "QOS generic error.";
463 case WSA_QOS_ESERVICETYPE
: return "QOS service type error.";
464 case WSA_QOS_EFLOWSPEC
: return "QOS flowspec error.";
465 case WSA_QOS_EPROVSPECBUF
: return "Invalid QOS provider buffer.";
466 case WSA_QOS_EFILTERSTYLE
: return "Invalid QOS filter style.";
467 case WSA_QOS_EFILTERTYPE
: return "Invalid QOS filter type.";
468 case WSA_QOS_EFILTERCOUNT
: return "Incorrect QOS filter count.";
469 case WSA_QOS_EOBJLENGTH
: return "Invalid QOS object length.";
470 case WSA_QOS_EFLOWCOUNT
: return "Incorrect QOS flow count.";
471 /*case WSA_QOS_EUNKOWNPSOBJ: return "Unrecognized QOS object.";*/
472 case WSA_QOS_EPOLICYOBJ
: return "Invalid QOS policy object.";
473 case WSA_QOS_EFLOWDESC
: return "Invalid QOS flow descriptor.";
474 case WSA_QOS_EPSFLOWSPEC
: return "Invalid QOS provider-specific flowspec.";
475 case WSA_QOS_EPSFILTERSPEC
: return "Invalid QOS provider-specific filterspec.";
476 case WSA_QOS_ESDMODEOBJ
: return "Invalid QOS shape discard mode object.";
477 case WSA_QOS_ESHAPERATEOBJ
: return "Invalid QOS shaping rate object.";
478 case WSA_QOS_RESERVED_PETYPE
: return "Reserved policy QOS element type.";
480 snprintf(unknown
, sizeof(unknown
),
481 "unknown WSA error code %d", (int)err
);
485 #endif /* USE_WINSOCK */