Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright (c) 2018-2021 Yubico AB. All rights reserved.
      3  * Use of this source code is governed by a BSD-style
      4  * license that can be found in the LICENSE file.
      5  * SPDX-License-Identifier: BSD-2-Clause
      6  */
      7 
      8 #undef _GNU_SOURCE /* XSI strerror_r() */
      9 
     10 #include <stdarg.h>
     11 #include <stdio.h>
     12 
     13 #include "fido.h"
     14 
     15 #ifndef FIDO_NO_DIAGNOSTIC
     16 
     17 #define XXDLEN	32
     18 #define XXDROW	128
     19 #define LINELEN	256
     20 
     21 #ifndef TLS
     22 #define TLS
     23 #endif
     24 
     25 static TLS int logging;
     26 static TLS fido_log_handler_t *log_handler;
     27 
     28 static void
     29 log_on_stderr(const char *str)
     30 {
     31 	fprintf(stderr, "%s", str);
     32 }
     33 
     34 static void
     35 do_log(const char *suffix, const char *fmt, va_list args)
     36 {
     37 	char line[LINELEN], body[LINELEN];
     38 
     39 	vsnprintf(body, sizeof(body), fmt, args);
     40 
     41 	if (suffix != NULL)
     42 		snprintf(line, sizeof(line), "%.180s: %.70s\n", body, suffix);
     43 	else
     44 		snprintf(line, sizeof(line), "%.180s\n", body);
     45 
     46 	log_handler(line);
     47 }
     48 
     49 void
     50 fido_log_init(void)
     51 {
     52 	logging = 1;
     53 	log_handler = log_on_stderr;
     54 }
     55 
     56 void
     57 fido_log_debug(const char *fmt, ...)
     58 {
     59 	va_list args;
     60 
     61 	if (!logging || log_handler == NULL)
     62 		return;
     63 
     64 	va_start(args, fmt);
     65 	do_log(NULL, fmt, args);
     66 	va_end(args);
     67 }
     68 
     69 void
     70 fido_log_xxd(const void *buf, size_t count, const char *fmt, ...)
     71 {
     72 	const uint8_t *ptr = buf;
     73 	char row[XXDROW], xxd[XXDLEN];
     74 	va_list args;
     75 
     76 	if (!logging || log_handler == NULL)
     77 		return;
     78 
     79 	snprintf(row, sizeof(row), "buf=%p, len=%zu", buf, count);
     80 	va_start(args, fmt);
     81 	do_log(row, fmt, args);
     82 	va_end(args);
     83 	*row = '\0';
     84 
     85 	for (size_t i = 0; i < count; i++) {
     86 		*xxd = '\0';
     87 		if (i % 16 == 0)
     88 			snprintf(xxd, sizeof(xxd), "%04zu: %02x", i, *ptr++);
     89 		else
     90 			snprintf(xxd, sizeof(xxd), " %02x", *ptr++);
     91 		strlcat(row, xxd, sizeof(row));
     92 		if (i % 16 == 15 || i == count - 1) {
     93 			fido_log_debug("%s", row);
     94 			*row = '\0';
     95 		}
     96 	}
     97 }
     98 
     99 void
    100 fido_log_error(int errnum, const char *fmt, ...)
    101 {
    102 	char errstr[LINELEN];
    103 	va_list args;
    104 
    105 	if (!logging || log_handler == NULL)
    106 		return;
    107 	if (strerror_r(errnum, errstr, sizeof(errstr)) != 0)
    108 		snprintf(errstr, sizeof(errstr), "error %d", errnum);
    109 
    110 	va_start(args, fmt);
    111 	do_log(errstr, fmt, args);
    112 	va_end(args);
    113 }
    114 
    115 void
    116 fido_set_log_handler(fido_log_handler_t *handler)
    117 {
    118 	if (handler != NULL)
    119 		log_handler = handler;
    120 }
    121 
    122 #endif /* !FIDO_NO_DIAGNOSTIC */
    123