/* * Copyright (C) 2002 - 2003 Ardis Technologies * Copyright (C) 2007 - 2018 Vladislav Bolkhovitin * Copyright (C) 2007 - 2018 Western Digital Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, version 2 * of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include #include #include #include #include #include #include "iscsid.h" int log_daemon = 1; int log_level = 0; void log_init(void) { if (log_daemon) openlog("iscsi-scstd", 0, LOG_DAEMON); } static void dolog_nofunc(int prio, const char *fmt, va_list ap) { if (log_daemon) { int len = strlen(fmt); char f[len+1+1]; if (fmt[len] != '\n') sprintf(f, "%s\n", fmt); else sprintf(f, "%s", fmt); vsyslog(prio, f, ap); } else { struct timeval time; gettimeofday(&time, NULL); fprintf(stderr, "%ld.%06ld: ", time.tv_sec, time.tv_usec); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); fflush(stderr); } } static void dolog(int prio, const char *func, int line, const char *fmt, va_list ap) { if (log_level == 0) { dolog_nofunc(prio, fmt, ap); return; } if (log_daemon) { int len = strlen(func) + strlen(fmt); char f[len+1+1]; if (fmt[len] != '\n') sprintf(f, "%s:%d: %s %s\n", func, line, (prio == LOG_ERR) ? "ERROR:" : "", fmt); else sprintf(f, "%s:%d: %s %s", func, line, (prio == LOG_ERR) ? "ERROR: " : "", fmt); vsyslog(prio, f, ap); } else { struct timeval time; gettimeofday(&time, NULL); fprintf(stderr, "%ld.%06ld: %s:%d: ", time.tv_sec, time.tv_usec, func, line); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); fflush(stderr); } } void __log(const char *func, int line, int prio, int level, const char *fmt, ...) { va_list ap; if (level) { prio = LOG_DEBUG; if (log_level < level) return; } va_start(ap, fmt); dolog(prio, func, line, fmt, ap); va_end(ap); } /* Definition for __log_pdu buffer */ #define BUFFER_SIZE 16 /* * size required for a hex dump of BUFFER_SIZE bytes (' ' + 2 chars = 3 chars * per byte) with a ' |' separator each 4th byte: */ #define LINE_SIZE (BUFFER_SIZE * 3 + BUFFER_SIZE / 4 * 2 + 1) static void __dump_line(const char *func, int line_num, int level, unsigned char *buf, int *cp) { char line[LINE_SIZE], *lp = line; int i, cnt; cnt = *cp; if (!cnt) return; for (i = 0; i < BUFFER_SIZE; i++) { if (i < cnt) lp += sprintf(lp, " %02x", buf[i]); else lp += sprintf(lp, " "); if ((i % 4) == 3) lp += sprintf(lp, " |"); if (i >= cnt || !isprint(buf[i])) buf[i] = ' '; } /* buf is not \0-terminated! */ __log(func, line_num, LOG_DEBUG, level, "%s %.*s |", line, BUFFER_SIZE, buf); *cp = 0; } static void __dump_char(const char *func, int line, int level, unsigned char *buf, int *cp, int ch) { int cnt = (*cp)++; buf[cnt] = ch; if (cnt == BUFFER_SIZE - 1) __dump_line(func, line, level, buf, cp); } #define dump_line() __dump_line(func, line, level, char_buf, &char_cnt) #define dump_char(ch) __dump_char(func, line, level, char_buf, &char_cnt, ch) void __log_pdu(const char *func, int line, int level, struct PDU *pdu) { unsigned char char_buf[BUFFER_SIZE]; int char_cnt = 0; unsigned char *buf; int i; if (log_level < level) return; buf = (void *)&pdu->bhs; __log(func, line, LOG_DEBUG, level, "BHS: (%p)", buf); for (i = 0; i < BHS_SIZE; i++) dump_char(*buf++); dump_line(); buf = (void *)pdu->ahs; __log(func, line, LOG_DEBUG, level, "AHS: (%p)", buf); for (i = 0; i < pdu->ahssize; i++) dump_char(*buf++); dump_line(); buf = (void *)pdu->data; __log(func, line, LOG_DEBUG, level, "Data: (%p)", buf); for (i = 0; i < pdu->datasize; i++) dump_char(*buf++); dump_line(); }