File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / log.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:39:23 2021 UTC (3 years, 9 months ago) by misho
Branches: mpd, MAIN
CVS tags: v5_9p16, v5_9, HEAD
mpd 5.9


/*
 * log.c
 *
 * Written by Toshiharu OHNO <tony-o@iij.ad.jp>
 * Copyright (c) 1993, Internet Initiative Japan, Inc. All rights reserved.
 * See ``COPYRIGHT.iij''
 * 
 * Rewritten by Archie Cobbs <archie@freebsd.org>
 * Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
 * See ``COPYRIGHT.whistle''
 */

#include "ppp.h"
#ifdef SYSLOG_FACILITY
#include <syslog.h>
#endif

/*
 * DEFINITIONS
 */

  #define DUMP_BYTES_PER_LINE	16
  #define ROUNDUP(x,r)		(((x)%(r))?((x)+((r)-((x)%(r)))):(x))
  #define MAX_LOG_LINE		500

/* Log option descriptor */

  struct logopt
  {
    int		mask;
    const char	*name;
    const char	*desc;
  };

/*
 * GLOBAL VARIABLES
 */

  int	gLogOptions = LG_DEFAULT_OPT | LG_ALWAYS;
#ifdef SYSLOG_FACILITY
  char	gSysLogIdent[32];
#endif

/*
 * INTERNAL VARIABLES
 */

  #define ADD_OPT(x,d)	{ LG_ ##x, #x, d },

  static struct logopt	LogOptionList[] =
  {
#ifdef LG_BUND
    ADD_OPT(BUND,	"Bundle events")
#endif
#ifdef LG_BUND2
    ADD_OPT(BUND2,	"Detailed bundle events")
#endif
#ifdef LG_LINK
    ADD_OPT(LINK,	"Link events")
#endif
#ifdef LG_REP
    ADD_OPT(REP,	"Repeater events")
#endif
#ifdef LG_LCP
    ADD_OPT(LCP,	"LCP negotiation")
#endif
#ifdef LG_LCP2
    ADD_OPT(LCP2,	"LCP events and debugging")
#endif
#ifdef LG_AUTH
    ADD_OPT(AUTH,	"Link authentication events")
#endif
#ifdef LG_AUTH2
    ADD_OPT(AUTH2,	"Link authentication details")
#endif
#ifdef LG_IPCP
    ADD_OPT(IPCP,	"IPCP negotiation")
#endif
#ifdef LG_IPCP2
    ADD_OPT(IPCP2,	"IPCP events and debugging")
#endif
#ifdef LG_IPV6CP
    ADD_OPT(IPV6CP,	"IPV6CP negotiation")
#endif
#ifdef LG_IPV6CP2
    ADD_OPT(IPV6CP2,	"IPV6CP events and debugging")
#endif
#ifdef LG_CCP
    ADD_OPT(CCP,	"CCP negotiation")
#endif
#ifdef LG_CCP2
    ADD_OPT(CCP2,	"CCP events and debugging")
#endif
#ifdef LG_ECP
    ADD_OPT(ECP,	"ECP negotiation")
#endif
#ifdef LG_ECP2
    ADD_OPT(ECP2,	"ECP events and debugging")
#endif
#ifdef LG_FSM
    ADD_OPT(FSM,	"All FSM events (except echo & reset)")
#endif
#ifdef LG_ECHO
    ADD_OPT(ECHO,	"Echo/reply events for all automata")
#endif
#ifdef LG_PHYS
    ADD_OPT(PHYS,	"Physical layer events")
#endif
#ifdef LG_PHYS2
    ADD_OPT(PHYS2,	"Physical layer debug")
#endif
#ifdef LG_PHYS3
    ADD_OPT(PHYS3,	"Physical layer control packet dump")
#endif
#ifdef LG_CHAT
    ADD_OPT(CHAT,	"Modem chat script")
#endif
#ifdef LG_CHAT2
    ADD_OPT(CHAT2,	"Chat script extra debugging output")
#endif
#ifdef LG_IFACE
    ADD_OPT(IFACE,	"IP interface and route management")
#endif
#ifdef LG_IFACE2
    ADD_OPT(IFACE2,	"IP interface and route management debug")
#endif
#ifdef LG_FRAME
    ADD_OPT(FRAME,	"Dump all incoming & outgoing frames")
#endif
#ifdef LG_RADIUS
    ADD_OPT(RADIUS,	"Radius authentication events")
#endif
#ifdef LG_RADIUS2
    ADD_OPT(RADIUS2,	"Radius authentication debug")
#endif
#ifdef LG_CONSOLE
    ADD_OPT(CONSOLE,	"Console events")
#endif
#ifdef LG_EVENTS
    ADD_OPT(EVENTS,	"Daemon events debug")
#endif
  };

  #define NUM_LOG_LEVELS (sizeof(LogOptionList) / sizeof(*LogOptionList))

/*
 * LogOpen()
 */

int
LogOpen(void)
{
#ifdef SYSLOG_FACILITY
    if (!*gSysLogIdent)
	strcpy(gSysLogIdent, "mpd");
    openlog(gSysLogIdent, 0, LOG_DAEMON);
#endif
    return(0);
}

/*
 * LogClose()
 */

void
LogClose(void)
{
#ifdef SYSLOG_FACILITY
    closelog();
#endif
}

/*
 * LogCommand()
 */

int
LogCommand(Context ctx, int ac, const char *const av[], const void *arg)
{
    u_int	k;
    int		bits, add;
    const char	*s;

    (void)arg;
    if (ac == 0) {
#define LG_FMT	"    %-12s  %-10s  %s\r\n"

	Printf(LG_FMT, "Log Option", "Enabled", "Description");
	Printf(LG_FMT, "----------", "-------", "-----------");
	for (k = 0; k < NUM_LOG_LEVELS; k++) {
    	    Printf("  " LG_FMT, LogOptionList[k].name,
		(gLogOptions & LogOptionList[k].mask) ? "Yes" : "No",
		LogOptionList[k].desc);
	}
	return(0);
    }

    while (ac--) {
	s = *av;
	switch (*s) {
    	    case '+':
		s++;
    	    default:
		add = TRUE;
		break;
    	    case '-':
		add = FALSE;
		s++;
	    break;
	}
	for (k = 0;
    	    k < NUM_LOG_LEVELS && strcasecmp(s, LogOptionList[k].name);
    	    k++);
	if (k < NUM_LOG_LEVELS)
    	    bits = LogOptionList[k].mask;
	else {
    	    if (!strcasecmp(s, "all")) {
		for (bits = k = 0; k < NUM_LOG_LEVELS; k++)
		    bits |= LogOptionList[k].mask;
    	    } else {
		Printf("\"%s\" is unknown. Enter \"log\" for list.\r\n", s);
		bits = 0;
    	    }
	}
	if (add)
    	    gLogOptions |= bits;
	else
    	    gLogOptions &= ~bits;
	av++;
    }
    return(0);
}

/*
 * LogPrintf()
 *
 * The way to print something to the log
 */

void
LogPrintf(const char *fmt, ...)
{
    va_list       args;

    va_start(args, fmt);
    vLogPrintf(fmt, args);
    va_end(args);
}

void
vLogPrintf(const char *fmt, va_list args) NO_THREAD_SAFETY_ANALYSIS
{
    if (!SLIST_EMPTY(&gConsole.sessions)) {
	char		buf[1000];
	ConsoleSession	s;

        vsnprintf(buf, sizeof(buf), fmt, args);
#ifdef SYSLOG_FACILITY
        syslog(LOG_INFO, "%s", buf);
#endif
	pthread_cleanup_push(ConsoleCancelCleanup, gConsole.lock);
	RWLOCK_RDLOCK(gConsole.lock);
	SLIST_FOREACH(s, &gConsole.sessions, next) {
	    if (Enabled(&s->options, CONSOLE_LOGGING))
		s->write(s, "%s\r\n", buf);
	}
	pthread_cleanup_pop(1);
#ifdef SYSLOG_FACILITY
    } else {
        vsyslog(LOG_INFO, fmt, args);
#endif
    }
}

/*
 * LogPrintf2()
 *
 * The way to print something to the log
 */

void
LogPrintf2(const char *fmt, ...)
{
    va_list       args;

    va_start(args, fmt);
#ifdef SYSLOG_FACILITY
    vsyslog(LOG_INFO, fmt, args);
#endif
    va_end(args);
}

/*
 * LogDumpBp2()
 *
 * Dump the contents of an Mbuf to the log
 */

void
LogDumpBp2(Mbuf bp, const char *fmt, ...)
{
    int		k;
    unsigned	total;
    u_char	bytes[DUMP_BYTES_PER_LINE];
    char	line[128];
    int		linelen;
    va_list	ap;

	/* Do header */
	va_start(ap, fmt);
	vLogPrintf(fmt, ap);
	va_end(ap);

	/* Do data */
	line[0]=' ';
	line[1]=' ';
        line[2]=' ';
        line[3]=0;
        linelen=3;
  
        total = 0;
	if (bp) {
    	    int	start, last = 0;
    	    unsigned stop;

    	    stop = ROUNDUP(total + MBLEN(bp), DUMP_BYTES_PER_LINE);
    	    for (start = total; total < stop; ) {
    		u_int	const byte = (MBDATAU(bp))[total - start];

    		if (total < start + MBLEN(bp)) {
		    sprintf(line+linelen, " %02x", byte);
		    last = total % DUMP_BYTES_PER_LINE;
    		} else
		    sprintf(line+linelen, "   ");
    		linelen+=3;
      
    		bytes[total % DUMP_BYTES_PER_LINE] = byte;
    		total++;
      
    		if (total % DUMP_BYTES_PER_LINE == 0) {
		    snprintf(line+linelen, sizeof(line), "  ");
        	    linelen+=2;
		    for (k = 0; k <= last; k++) {
			line[linelen++] = isgraph(bytes[k]) ? bytes[k] : '.';
			line[linelen] = 0;
		    }
		    LogPrintf("%s",line);
		    line[0]=' ';
		    line[1]=' ';
		    line[2]=' ';
		    line[3]=0;
		    linelen=3;
    		}
    	    }
	}
}

/*
 * LogDumpBuf2()
 *
 * Dump the contents of a buffer to the log
 */

void
LogDumpBuf2(const u_char *buf, int count, const char *fmt, ...)
{
    int		k, stop, total;
    char	line[128];
    int		linelen;
    va_list	ap;

	/* Do header */
	va_start(ap, fmt);
        vLogPrintf(fmt, ap);
        va_end(ap);

	/* Do data */
        line[0]=' ';
        line[1]=' ';
        line[2]=' ';
        line[3]=0;
        linelen=3;

        stop = ROUNDUP(count, DUMP_BYTES_PER_LINE);
        for (total = 0; total < stop; ) {
	    if (total < count)
		sprintf(line+linelen, " %02x", buf[total]);
	    else
		sprintf(line+linelen, "   ");
            linelen+=3;
    	    total++;
	    if (total % DUMP_BYTES_PER_LINE == 0) {
		snprintf(line+linelen, sizeof(line), "  ");
    		linelen+=2;
    		for (k = total - DUMP_BYTES_PER_LINE; k < total && k < count; k++) {
		    line[linelen++] = isgraph(buf[k]) ? buf[k] : '.';
		    line[linelen] = 0;
		}
		LogPrintf("%s",line);
		line[0]=' ';
		line[1]=' ';
		line[2]=' ';
		line[3]=0;
		linelen=3;
	    }
	}
}

/*
 * Perror()
 */

void
Perror(const char *fmt, ...)
{
    va_list	args;
    char	buf[200];

    va_start(args, fmt);
    vsnprintf(buf, sizeof(buf), fmt, args);
    va_end(args);
    snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
	": %s", strerror(errno));
    Log(LG_ERR, ("%s", buf));
}

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>