/* * DEBUG - debugging functions * * Author: * Emile van Bergen, emile@evbergen.xs4all.nl * * Permission to redistribute an original or modified version of this program * in source, intermediate or object code form is hereby granted exclusively * under the terms of the GNU General Public License, version 2. Please see the * file COPYING for details, or refer to http://www.gnu.org/copyleft/gpl.html. * * History: * 2000/12/02 - EvB - Created * 2001/02/06 - EvB - Made dbg_cvtstr NULL-proof * 2001/11/01 - EvB - Added standard logging functions * 2002/02/06 - EvB - Added msg_line interface and made meta_printav * and hexdump use it instead of writing to stderr * 2005/06/20 - EvB - Add tag if we run as a module */ char debug_id[] = "DEBUG - Copyright (C) 2000 Emile van Bergen."; /* * INCLUDES & DEFINES */ #include #include #include #include /* For vsprintf / vsnprintf */ #include /* For MIN */ #include /* For meta_atoprt() and meta_ordtoa() */ #include #include /* * GLOBALS */ int debuglevel = 0; /* Backwards compatibility only */ int msg_syslogfac = -1; /* Syslog facility to which we output all */ int msg_nostderr = 0; /* Be quiet on stderr */ char *msg_tag = 0; /* Extra tag to add to each line */ int msg_tagl = 0; int msg_thresh[F_CNT] = { /* Priority threshold (only lower-numbered */ L_ERR, L_ERR, /* or equal gets through */ L_ERR, L_ERR, L_ERR, L_ERR }; char *msg_f_names[F_CNT+1] = { /* Names for our own internal facilities */ "misc", /* miscellaneous */ "text", /* textfile handling (dictionary) */ "lang", /* language */ "proc", /* subprocess events */ "recv", /* packet reception */ "send", /* packet sending */ 0 /* not found */ }; #ifdef HAVE_SYSLOG #include #define SYSLOG_F_CNT 18 /* Syslog facilities */ struct { char *name; int fac; } syslog_f_map[SYSLOG_F_CNT + 1] = { { "auth", LOG_AUTH }, { "cron", LOG_CRON }, { "daemon", LOG_DAEMON }, { "kern", LOG_KERN }, { "lpr", LOG_LPR }, { "mail", LOG_MAIL }, { "news", LOG_NEWS }, { "syslog", LOG_SYSLOG }, { "user", LOG_USER }, { "uucp", LOG_UUCP }, { "local0", LOG_LOCAL0 }, { "local1", LOG_LOCAL1 }, { "local2", LOG_LOCAL2 }, { "local3", LOG_LOCAL3 }, { "local4", LOG_LOCAL4 }, { "local5", LOG_LOCAL5 }, { "local6", LOG_LOCAL6 }, { "local7", LOG_LOCAL7 }, { 0, -1 }, /* not found */ }; #ifndef LOG_MAKEPRI #define LOG_MAKEPRI(f, p) ((f) | (p)) #endif #endif /* * FUNCTIONS */ void msg_init(int syslogfac, int nostderr) { msg_syslogfac = syslogfac; msg_nostderr = nostderr; #ifdef HAVE_SYSLOG if (msg_syslogfac != -1) openlog("openradius", 0, msg_syslogfac); #endif } void msg_setthresh(int ourfac, int level) { if (ourfac >= 0 && ourfac < F_CNT) msg_thresh[ourfac] = level; } void msg_settag(char *tag, int tagl) { if (tagl < 32 && tag) { msg_tag = tag; msg_tagl = tagl; } } int msg_getfacbyname(char *name) { int ret; for(ret = 0; ret < F_CNT && strcmp(name, msg_f_names[ret]); ret++); return ret; } #if 0 char *msg_getfacbynr(int ourfac) { return (ourfac >= 0 && ourfac < F_CNT) ? msg_f_names[ourfac] : "****"; } #endif int msg_getsyslogfacbyname(char *name) { #ifdef HAVE_SYSLOG int ret; for(ret = 0; ret < SYSLOG_F_CNT && strcmp(name, syslog_f_map[ret].name); ret++); return syslog_f_map[ret].fac; #else return -1; #endif } void msg(int ourfac, int level, char *fmt, ...) { static char logline[4096]; char *o; int n; va_list ap; /* Return if level is not high (numerically low) enough */ if (level > msg_thresh[ourfac]) return; /* Init logline */ o = logline; if (msg_tagl && msg_tag) { *o++ = '['; memcpy(o, msg_tag, msg_tagl); o += msg_tagl; *o++ = ']'; *o++ = ' '; } *o++ = '['; memcpy(o, msg_f_names[ourfac], 4); o += 4; *o ++ = ']'; *o ++ = ' '; /* Prepare arglist and create formatted line */ va_start(ap, fmt); n = logline + sizeof(logline) - 16 - o; #ifdef HAVE_VSNPRINTF vsnprintf(o, n, fmt, ap); #else if (vsprintf(o, fmt, ap) >= n) _exit(254); /* safest */ #endif msg_line(level, logline); va_end(ap); } void msg_line(int level, char *logline) { /* Write line to stderr if we haven't been told to be quiet */ if (!msg_nostderr) write(2, logline, strlen(logline)); #ifdef HAVE_SYSLOG /* Write line to syslog if facility is not none */ if (msg_syslogfac != -1) syslog(LOG_MAKEPRI(msg_syslogfac, level), "%s", logline); #endif } char *dbg_cvtstr(char *s, int slen) { static char dbg_cvtbuf[DBG_CVTBUFLEN]; int len; len = s ? meta_atoprt(s,slen, 0,0,0,0, dbg_cvtbuf,DBG_CVTBUFLEN-1) : 0; dbg_cvtbuf[len] = 0; return dbg_cvtbuf; } #define DBG_HEXBUFLEN (4 + 2 + 16 * 3 + 1 + 16 + 1 + 1) void hexdump(char *s, int slen) { static char hexbuf[DBG_HEXBUFLEN]; char *o; int ofs, i; for(ofs = 0; ofs < slen; ofs += 16, s += 16) { o = hexbuf; memset(o, ' ', DBG_HEXBUFLEN - 1); o += meta_ordtoa(o, 4, 4, 16, ofs) + 2; for(i = 0; i < MIN(slen - ofs, 16); i++) o += meta_ordtoa(o, 2, 2, 16, s[i] & 0xff) + 1; o = hexbuf + 4 + 2 + 16 * 3 + 1; for(i = 0; i < MIN(slen - ofs, 16); i++) *o++ = s[i] > 31 && s[i] < 127 ? s[i] : '.'; hexbuf[4 + 2 + 16 * 3 + 1 + 16] = '\n'; hexbuf[DBG_HEXBUFLEN - 1] = 0; msg_line(L_DEBUG, hexbuf); } }