log.c revision 49527
125184Sjkh/*-
225184Sjkh * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
350472Speter * All rights reserved.
425184Sjkh *
525184Sjkh * Redistribution and use in source and binary forms, with or without
625184Sjkh * modification, are permitted provided that the following conditions
725184Sjkh * are met:
825184Sjkh * 1. Redistributions of source code must retain the above copyright
925184Sjkh *    notice, this list of conditions and the following disclaimer.
1025184Sjkh * 2. Redistributions in binary form must reproduce the above copyright
1125184Sjkh *    notice, this list of conditions and the following disclaimer in the
1225184Sjkh *    documentation and/or other materials provided with the distribution.
1325184Sjkh *
1425184Sjkh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1525184Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1625184Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1750357Ssheldonh * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1825184Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1925184Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2025184Sjkh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2125184Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2250357Ssheldonh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2350357Ssheldonh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2425184Sjkh * SUCH DAMAGE.
2525184Sjkh *
2625184Sjkh *	$Id: log.c,v 1.39 1999/06/01 16:01:48 brian Exp $
2725184Sjkh */
2840006Sphk
2950357Ssheldonh#include <sys/types.h>
3040006Sphk
3140006Sphk#include <ctype.h>
3240006Sphk#include <stdarg.h>
3340006Sphk#include <stdio.h>
3442621Shm#include <string.h>
3550357Ssheldonh#include <syslog.h>
3642621Shm#include <termios.h>
3742621Shm
3842621Shm#include "defs.h"
3942627Sjoerg#include "command.h"
4042627Sjoerg#include "mbuf.h"
4142627Sjoerg#include "log.h"
4242627Sjoerg#include "descriptor.h"
4342627Sjoerg#include "prompt.h"
4442627Sjoerg
4542627Sjoergstatic const char *LogNames[] = {
4642627Sjoerg  "Async",
4742627Sjoerg  "CBCP",
4842627Sjoerg  "CCP",
4942627Sjoerg  "Chat",
5042627Sjoerg  "Command",
5142627Sjoerg  "Connect",
5242627Sjoerg  "Debug",
5325184Sjkh  "HDLC",
5450357Ssheldonh  "ID0",
5548687Speter  "IPCP",
5648687Speter  "LCP",
5748687Speter  "LQM",
5848662Speter  "Phase",
5925184Sjkh  "Physical",
6033682Sbrian  "Sync",
6148662Speter  "TCP/IP",
6225184Sjkh  "Timer",
6325184Sjkh  "Tun",
6425184Sjkh  "Warning",
6525184Sjkh  "Error",
6648842Sjkh  "Alert"
6750470Sjkh};
6848842Sjkh
6948842Sjkh#define MSK(n) (1<<((n)-1))
7048842Sjkh
7148842Sjkhstatic u_long LogMask = MSK(LogPHASE);
7248662Speterstatic u_long LogMaskLocal = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
7325184Sjkhstatic int LogTunno = -1;
7425184Sjkhstatic struct prompt *promptlist;	/* Where to log local stuff */
7525184Sjkhint log_PromptListChanged;
7625184Sjkh
7725184Sjkhstruct prompt *
7825184Sjkhlog_PromptList()
7925184Sjkh{
8025184Sjkh  return promptlist;
8148662Speter}
8225184Sjkh
8325184Sjkhvoid
8425184Sjkhlog_RegisterPrompt(struct prompt *prompt)
8525184Sjkh{
8625184Sjkh  prompt->next = promptlist;
8725184Sjkh  promptlist = prompt;
8825184Sjkh  prompt->active = 1;
8925184Sjkh  log_DiscardAllLocal(&prompt->logmask);
9025184Sjkh}
9148662Speter
9225184Sjkhvoid
9348662Speterlog_ActivatePrompt(struct prompt *prompt)
9448662Speter{
9548662Speter  prompt->active = 1;
9648662Speter  LogMaskLocal |= prompt->logmask;
9725184Sjkh}
9829300Sdanny
9949122Sbrianstatic void
10050357SsheldonhLogSetMaskLocal(void)
10149122Sbrian{
10250357Ssheldonh  struct prompt *p;
10350357Ssheldonh
10449122Sbrian  LogMaskLocal = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
10549122Sbrian  for (p = promptlist; p; p = p->next)
10649122Sbrian    LogMaskLocal |= p->logmask;
10749122Sbrian}
10849122Sbrian
10950357Ssheldonhvoid
11050193Sbrianlog_DeactivatePrompt(struct prompt *prompt)
11149122Sbrian{
11249122Sbrian  if (prompt->active) {
11350063Sbrian    prompt->active = 0;
11449122Sbrian    LogSetMaskLocal();
11549122Sbrian  }
11629300Sdanny}
11729300Sdanny
11829300Sdannyvoid
11932382Salexlog_UnRegisterPrompt(struct prompt *prompt)
12032382Salex{
12132382Salex  if (prompt) {
12229300Sdanny    struct prompt **p;
12329300Sdanny
12429300Sdanny    for (p = &promptlist; *p; p = &(*p)->next)
12550357Ssheldonh      if (*p == prompt) {
12641077Speter        *p = prompt->next;
12729300Sdanny        prompt->next = NULL;
12829300Sdanny        break;
12929300Sdanny      }
13029300Sdanny    LogSetMaskLocal();
13129300Sdanny    log_PromptListChanged++;
13229300Sdanny  }
13329300Sdanny}
13429300Sdanny
13550357Ssheldonhvoid
13645542Sdeslog_DestroyPrompts(struct server *s)
13745542Sdes{
13845542Sdes  struct prompt *p, *pn, *pl;
13950357Ssheldonh
14045542Sdes  p = promptlist;
14145622Sbrian  pl = NULL;
14244992Sbrian  while (p) {
14344992Sbrian    pn = p->next;
14450357Ssheldonh    if (s && p->owner == s) {
14544992Sbrian      if (pl)
14644992Sbrian        pl->next = p->next;
14744992Sbrian      else
14844992Sbrian        promptlist = p->next;
14944992Sbrian      p->next = NULL;
15044992Sbrian      prompt_Destroy(p, 1);
15144992Sbrian    } else
15244992Sbrian      pl = p;
15344992Sbrian    p = pn;
15429300Sdanny  }
15533337Salex}
15650357Ssheldonh
15733149Salexvoid
15833149Salexlog_DisplayPrompts()
15933149Salex{
16033149Salex  struct prompt *p;
16129300Sdanny
16225184Sjkh  for (p = promptlist; p; p = p->next)
16325184Sjkh    prompt_Required(p);
16440006Sphk}
16540006Sphk
16640006Sphkvoid
16740006Sphklog_WritePrompts(struct datalink *dl, const char *fmt,...)
16840006Sphk{
16929300Sdanny  va_list ap;
17029300Sdanny  struct prompt *p;
17150357Ssheldonh
17225184Sjkh  va_start(ap, fmt);
17325184Sjkh  for (p = promptlist; p; p = p->next)
17425184Sjkh    if (prompt_IsTermMode(p, dl))
17525184Sjkh      prompt_vPrintf(p, fmt, ap);
17625184Sjkh  va_end(ap);
17750357Ssheldonh}
17825184Sjkh
17925184Sjkhvoid
18025184Sjkhlog_SetTtyCommandMode(struct datalink *dl)
18125184Sjkh{
18225184Sjkh  struct prompt *p;
18325184Sjkh
18425184Sjkh  for (p = promptlist; p; p = p->next)
18550357Ssheldonh    if (prompt_IsTermMode(p, dl))
18627218Spst      prompt_TtyCommandMode(p);
18747755Sbde}
18827218Spst
18927218Spststatic int
19050357SsheldonhsyslogLevel(int lev)
19145096Simp{
19247755Sbde  switch (lev) {
19347755Sbde  case LogDEBUG:
19445096Simp  case LogTIMER:
19545096Simp    return LOG_DEBUG;
19650357Ssheldonh  case LogWARN:
19739267Sjkoshy    return LOG_WARNING;
19847755Sbde  case LogERROR:
19939267Sjkoshy    return LOG_ERR;
20049603Sdes  case LogALERT:
20150357Ssheldonh    return LOG_ALERT;
20249603Sdes  }
20349603Sdes  return lev >= LogMIN && lev <= LogMAX ? LOG_INFO : 0;
20449603Sdes}
20549603Sdes
20650357Ssheldonhconst char *
20749603Sdeslog_Name(int id)
20849603Sdes{
20949603Sdes  return id < LogMIN || id > LogMAX ? "Unknown" : LogNames[id - 1];
21039267Sjkoshy}
21150357Ssheldonh
21225365Sjkhvoid
21347755Sbdelog_Keep(int id)
21425184Sjkh{
21525184Sjkh  if (id >= LogMIN && id <= LogMAXCONF)
21650357Ssheldonh    LogMask |= MSK(id);
21733439Sguido}
21847755Sbde
21933439Sguidovoid
22033439Sguidolog_KeepLocal(int id, u_long *mask)
22150357Ssheldonh{
22233439Sguido  if (id >= LogMIN && id <= LogMAXCONF) {
22347755Sbde    LogMaskLocal |= MSK(id);
22433439Sguido    *mask |= MSK(id);
22533439Sguido  }
22650357Ssheldonh}
22747752Sphk
22847755Sbdevoid
22947752Sphklog_Discard(int id)
23047752Sphk{
23150357Ssheldonh  if (id >= LogMIN && id <= LogMAXCONF)
23225365Sjkh    LogMask &= ~MSK(id);
23347755Sbde}
23425184Sjkh
23525184Sjkhvoid
23650357Ssheldonhlog_DiscardLocal(int id, u_long *mask)
23747755Sbde{
23847755Sbde  if (id >= LogMIN && id <= LogMAXCONF) {
23936174Sjkh    *mask &= ~MSK(id);
24036174Sjkh    LogSetMaskLocal();
24136174Sjkh  }
24236174Sjkh}
24350357Ssheldonh
24436174Sjkhvoid
24536174Sjkhlog_DiscardAll()
24636174Sjkh{
24750357Ssheldonh  LogMask = 0;
24836174Sjkh}
24925184Sjkh
25025184Sjkhvoid
25125765Sjkhlog_DiscardAllLocal(u_long *mask)
25250357Ssheldonh{
25336174Sjkh  *mask = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
25425765Sjkh  LogSetMaskLocal();
25536174Sjkh}
25650357Ssheldonh
25734395Sjkhint
25834395Sjkhlog_IsKept(int id)
25925184Sjkh{
26025184Sjkh  if (id < LogMIN || id > LogMAX)
26125184Sjkh    return 0;
26225184Sjkh  if (id > LogMAXCONF)
26325184Sjkh    return LOG_KEPT_LOCAL | LOG_KEPT_SYSLOG;
26425184Sjkh
26550357Ssheldonh  return ((LogMaskLocal & MSK(id)) ? LOG_KEPT_LOCAL : 0) |
26632949Swollman    ((LogMask & MSK(id)) ? LOG_KEPT_SYSLOG : 0);
26725184Sjkh}
26825184Sjkh
26950357Ssheldonhint
27035787Sandreaslog_IsKeptLocal(int id, u_long mask)
27131472Sobrien{
27225184Sjkh  if (id < LogMIN || id > LogMAX)
27350357Ssheldonh    return 0;
27435787Sandreas  if (id > LogMAXCONF)
27525184Sjkh    return LOG_KEPT_LOCAL | LOG_KEPT_SYSLOG;
27625184Sjkh
27750357Ssheldonh  return ((mask & MSK(id)) ? LOG_KEPT_LOCAL : 0) |
27825184Sjkh    ((LogMask & MSK(id)) ? LOG_KEPT_SYSLOG : 0);
27925184Sjkh}
28025184Sjkh
28150357Ssheldonhvoid
28244668Sjfitzlog_Open(const char *Name)
28325184Sjkh{
28425184Sjkh  openlog(Name, LOG_PID, LOG_DAEMON);
28525184Sjkh}
28625184Sjkh
28750357Ssheldonhvoid
28825184Sjkhlog_SetTun(int tunno)
28925184Sjkh{
29050357Ssheldonh  LogTunno = tunno;
29125184Sjkh}
29225184Sjkh
29325184Sjkhvoid
29450357Ssheldonhlog_Close()
29525184Sjkh{
29625184Sjkh  closelog();
29725184Sjkh  LogTunno = -1;
29825184Sjkh}
29925184Sjkh
30050357Ssheldonhvoid
30125184Sjkhlog_Printf(int lev, const char *fmt,...)
30250357Ssheldonh{
30325184Sjkh  va_list ap;
30425184Sjkh  struct prompt *prompt;
30525184Sjkh
30625184Sjkh  va_start(ap, fmt);
30735149Smarkm  if (log_IsKept(lev)) {
30850357Ssheldonh    char nfmt[200];
30935149Smarkm
31035149Smarkm    if ((log_IsKept(lev) & LOG_KEPT_LOCAL) && promptlist) {
31135149Smarkm      if ((log_IsKept(LogTUN) & LOG_KEPT_LOCAL) && LogTunno != -1)
31250357Ssheldonh        snprintf(nfmt, sizeof nfmt, "%s%d: %s: %s", TUN_NAME,
31335149Smarkm	         LogTunno, log_Name(lev), fmt);
31435149Smarkm      else
31535149Smarkm        snprintf(nfmt, sizeof nfmt, "%s: %s", log_Name(lev), fmt);
31640006Sphk
31740006Sphk      for (prompt = promptlist; prompt; prompt = prompt->next)
31840006Sphk        if (lev > LogMAXCONF || (prompt->logmask & MSK(lev)))
31940006Sphk          prompt_vPrintf(prompt, nfmt, ap);
32040006Sphk    }
32125184Sjkh
32225184Sjkh    if ((log_IsKept(lev) & LOG_KEPT_SYSLOG) &&
32325184Sjkh        (lev != LogWARN || !promptlist)) {
32425184Sjkh      if ((log_IsKept(LogTUN) & LOG_KEPT_SYSLOG) && LogTunno != -1)
32525184Sjkh        snprintf(nfmt, sizeof nfmt, "%s%d: %s: %s", TUN_NAME,
32625184Sjkh	         LogTunno, log_Name(lev), fmt);
32725184Sjkh      else
32850357Ssheldonh        snprintf(nfmt, sizeof nfmt, "%s: %s", log_Name(lev), fmt);
32925184Sjkh      vsyslog(syslogLevel(lev), nfmt, ap);
33050357Ssheldonh    }
33125184Sjkh  }
33225184Sjkh  va_end(ap);
33325184Sjkh}
33450357Ssheldonh
33547755Sbdevoid
33647755Sbdelog_DumpBp(int lev, const char *hdr, const struct mbuf *bp)
33725184Sjkh{
33825916Sjkh  if (log_IsKept(lev)) {
33950357Ssheldonh    char buf[68];
34025184Sjkh    char *b, *c;
34125184Sjkh    const u_char *ptr;
34250357Ssheldonh    int f;
34325184Sjkh
34425184Sjkh    if (hdr && *hdr)
34525184Sjkh      log_Printf(lev, "%s\n", hdr);
34625184Sjkh
34750357Ssheldonh    b = buf;
34825916Sjkh    c = b + 50;
34950357Ssheldonh    do {
35047755Sbde      f = bp->cnt;
35141371Sjkoshy      ptr = CONST_MBUF_CTOP(bp);
35247755Sbde      while (f--) {
35341185Smsmith	sprintf(b, " %02x", (int) *ptr);
35425184Sjkh        *c++ = isprint(*ptr) ? *ptr : '.';
35525184Sjkh        ptr++;
35650357Ssheldonh        b += 3;
35725184Sjkh        if (b == buf + 48) {
35850357Ssheldonh          memset(b, ' ', 2);
35939380Scracauer          *c = '\0';
36035459Sphk          log_Printf(lev, "%s\n", buf);
36150357Ssheldonh          b = buf;
36247838Sbrian          c = b + 50;
36347838Sbrian        }
36447838Sbrian      }
36547838Sbrian    } while ((bp = bp->next) != NULL);
36647838Sbrian
36725184Sjkh    if (b > buf) {
36825184Sjkh      memset(b, ' ', 50 - (b - buf));
36950357Ssheldonh      *c = '\0';
37042270Sjkh      log_Printf(lev, "%s\n", buf);
37125184Sjkh    }
37225184Sjkh  }
37325184Sjkh}
37450357Ssheldonh
37550357Ssheldonhvoid
37631033Sseflog_DumpBuff(int lev, const char *hdr, const u_char *ptr, int n)
37731033Ssef{
37831033Ssef  if (log_IsKept(lev)) {
37931033Ssef    char buf[68];
38031033Ssef    char *b, *c;
38138316Sphk
38250357Ssheldonh    if (hdr && *hdr)
38331033Ssef      log_Printf(lev, "%s\n", hdr);
38438316Sphk    while (n > 0) {
38531033Ssef      b = buf;
38631033Ssef      c = b + 50;
38725184Sjkh      for (b = buf; b != buf + 48 && n--; b += 3, ptr++) {
38825184Sjkh	sprintf(b, " %02x", (int) *ptr);
38925184Sjkh        *c++ = isprint(*ptr) ? *ptr : '.';
39025184Sjkh      }
39125184Sjkh      memset(b, ' ', 50 - (b - buf));
392      *c = '\0';
393      log_Printf(lev, "%s\n", buf);
394    }
395  }
396}
397
398int
399log_ShowLevel(struct cmdargs const *arg)
400{
401  int i;
402
403  prompt_Printf(arg->prompt, "Log:  ");
404  for (i = LogMIN; i <= LogMAX; i++)
405    if (log_IsKept(i) & LOG_KEPT_SYSLOG)
406      prompt_Printf(arg->prompt, " %s", log_Name(i));
407
408  prompt_Printf(arg->prompt, "\nLocal:");
409  for (i = LogMIN; i <= LogMAX; i++)
410    if (log_IsKeptLocal(i, arg->prompt->logmask) & LOG_KEPT_LOCAL)
411      prompt_Printf(arg->prompt, " %s", log_Name(i));
412
413  prompt_Printf(arg->prompt, "\n");
414
415  return 0;
416}
417
418int
419log_SetLevel(struct cmdargs const *arg)
420{
421  int i, res, argc, local;
422  char const *const *argv, *argp;
423
424  argc = arg->argc - arg->argn;
425  argv = arg->argv + arg->argn;
426  res = 0;
427
428  if (argc == 0 || strcasecmp(argv[0], "local"))
429    local = 0;
430  else {
431    if (arg->prompt == NULL) {
432      log_Printf(LogWARN, "set log local: Only available on the command line\n");
433      return 1;
434    }
435    argc--;
436    argv++;
437    local = 1;
438  }
439
440  if (argc == 0 || (argv[0][0] != '+' && argv[0][0] != '-')) {
441    if (local)
442      log_DiscardAllLocal(&arg->prompt->logmask);
443    else
444      log_DiscardAll();
445  }
446
447  while (argc--) {
448    argp = **argv == '+' || **argv == '-' ? *argv + 1 : *argv;
449    for (i = LogMIN; i <= LogMAX; i++)
450      if (strcasecmp(argp, log_Name(i)) == 0) {
451	if (**argv == '-') {
452          if (local)
453            log_DiscardLocal(i, &arg->prompt->logmask);
454          else
455	    log_Discard(i);
456	} else if (local)
457          log_KeepLocal(i, &arg->prompt->logmask);
458        else
459          log_Keep(i);
460	break;
461      }
462    if (i > LogMAX) {
463      log_Printf(LogWARN, "%s: Invalid log value\n", argp);
464      res = -1;
465    }
466    argv++;
467  }
468  return res;
469}
470
471int
472log_ShowWho(struct cmdargs const *arg)
473{
474  struct prompt *p;
475
476  for (p = promptlist; p; p = p->next) {
477    prompt_Printf(arg->prompt, "%s (%s)", p->src.type, p->src.from);
478    if (p == arg->prompt)
479      prompt_Printf(arg->prompt, " *");
480    if (!p->active)
481      prompt_Printf(arg->prompt, " ^Z");
482    prompt_Printf(arg->prompt, "\n");
483  }
484
485  return 0;
486}
487