log.c revision 38013
1/*-
2 * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 *	$Id: log.c,v 1.31 1998/06/15 19:06:48 brian Exp $
27 */
28
29#include <sys/types.h>
30
31#include <stdarg.h>
32#include <stdio.h>
33#include <string.h>
34#include <syslog.h>
35#include <termios.h>
36
37#include "defs.h"
38#include "command.h"
39#include "mbuf.h"
40#include "log.h"
41#include "descriptor.h"
42#include "prompt.h"
43
44static const char *LogNames[] = {
45  "Async",
46  "CCP",
47  "Chat",
48  "Command",
49  "Connect",
50  "Debug",
51  "HDLC",
52  "ID0",
53  "IPCP",
54  "LCP",
55  "LQM",
56  "Phase",
57  "TCP/IP",
58  "Timer",
59  "Tun",
60  "Warning",
61  "Error",
62  "Alert"
63};
64
65#define MSK(n) (1<<((n)-1))
66
67static u_long LogMask = MSK(LogPHASE);
68static u_long LogMaskLocal = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
69static int LogTunno = -1;
70static struct prompt *promptlist;	/* Where to log local stuff */
71int log_PromptListChanged;
72
73struct prompt *
74log_PromptList()
75{
76  return promptlist;
77}
78
79void
80log_RegisterPrompt(struct prompt *prompt)
81{
82  prompt->next = promptlist;
83  promptlist = prompt;
84  prompt->active = 1;
85  log_DiscardAllLocal(&prompt->logmask);
86}
87
88void
89log_ActivatePrompt(struct prompt *prompt)
90{
91  prompt->active = 1;
92  LogMaskLocal |= prompt->logmask;
93}
94
95static void
96LogSetMaskLocal(void)
97{
98  struct prompt *p;
99
100  LogMaskLocal = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
101  for (p = promptlist; p; p = p->next)
102    LogMaskLocal |= p->logmask;
103}
104
105void
106log_DeactivatePrompt(struct prompt *prompt)
107{
108  if (prompt->active) {
109    prompt->active = 0;
110    LogSetMaskLocal();
111  }
112}
113
114void
115log_UnRegisterPrompt(struct prompt *prompt)
116{
117  if (prompt) {
118    struct prompt **p;
119
120    for (p = &promptlist; *p; p = &(*p)->next)
121      if (*p == prompt) {
122        *p = prompt->next;
123        prompt->next = NULL;
124        break;
125      }
126    LogSetMaskLocal();
127    log_PromptListChanged++;
128  }
129}
130
131void
132log_DestroyPrompts(struct server *s)
133{
134  struct prompt *p, *pn;
135
136  p = promptlist;
137  while (p) {
138    pn = p->next;
139    if (s && p->owner != s) {
140      p->next = NULL;
141      prompt_Destroy(p, 1);
142    }
143    p = pn;
144  }
145}
146
147void
148log_DisplayPrompts()
149{
150  struct prompt *p;
151
152  for (p = promptlist; p; p = p->next)
153    prompt_Required(p);
154}
155
156void
157log_WritePrompts(struct datalink *dl, const char *data, int len)
158{
159  struct prompt *p;
160
161  for (p = promptlist; p; p = p->next)
162    if (prompt_IsTermMode(p, dl))
163      prompt_Printf(p, "%.*s", len, data);
164}
165
166void
167log_SetTtyCommandMode(struct datalink *dl)
168{
169  struct prompt *p;
170
171  for (p = promptlist; p; p = p->next)
172    if (prompt_IsTermMode(p, dl))
173      prompt_TtyCommandMode(p);
174}
175
176static int
177syslogLevel(int lev)
178{
179  switch (lev) {
180  case LogDEBUG:
181  case LogTIMER:
182    return LOG_DEBUG;
183  case LogWARN:
184    return LOG_WARNING;
185  case LogERROR:
186    return LOG_ERR;
187  case LogALERT:
188    return LOG_ALERT;
189  }
190  return lev >= LogMIN && lev <= LogMAX ? LOG_INFO : 0;
191}
192
193const char *
194log_Name(int id)
195{
196  return id < LogMIN || id > LogMAX ? "Unknown" : LogNames[id - 1];
197}
198
199void
200log_Keep(int id)
201{
202  if (id >= LogMIN && id <= LogMAXCONF)
203    LogMask |= MSK(id);
204}
205
206void
207log_KeepLocal(int id, u_long *mask)
208{
209  if (id >= LogMIN && id <= LogMAXCONF) {
210    LogMaskLocal |= MSK(id);
211    *mask |= MSK(id);
212  }
213}
214
215void
216log_Discard(int id)
217{
218  if (id >= LogMIN && id <= LogMAXCONF)
219    LogMask &= ~MSK(id);
220}
221
222void
223log_DiscardLocal(int id, u_long *mask)
224{
225  if (id >= LogMIN && id <= LogMAXCONF) {
226    *mask &= ~MSK(id);
227    LogSetMaskLocal();
228  }
229}
230
231void
232log_DiscardAll()
233{
234  LogMask = 0;
235}
236
237void
238log_DiscardAllLocal(u_long *mask)
239{
240  *mask = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
241  LogSetMaskLocal();
242}
243
244int
245log_IsKept(int id)
246{
247  if (id < LogMIN || id > LogMAX)
248    return 0;
249  if (id > LogMAXCONF)
250    return LOG_KEPT_LOCAL | LOG_KEPT_SYSLOG;
251
252  return ((LogMaskLocal & MSK(id)) ? LOG_KEPT_LOCAL : 0) |
253    ((LogMask & MSK(id)) ? LOG_KEPT_SYSLOG : 0);
254}
255
256int
257log_IsKeptLocal(int id, u_long mask)
258{
259  if (id < LogMIN || id > LogMAX)
260    return 0;
261  if (id > LogMAXCONF)
262    return LOG_KEPT_LOCAL | LOG_KEPT_SYSLOG;
263
264  return ((mask & MSK(id)) ? LOG_KEPT_LOCAL : 0) |
265    ((LogMask & MSK(id)) ? LOG_KEPT_SYSLOG : 0);
266}
267
268void
269log_Open(const char *Name)
270{
271  openlog(Name, LOG_PID, LOG_DAEMON);
272}
273
274void
275log_SetTun(int tunno)
276{
277  LogTunno = tunno;
278}
279
280void
281log_Close()
282{
283  closelog();
284  LogTunno = -1;
285}
286
287void
288log_Printf(int lev, const char *fmt,...)
289{
290  va_list ap;
291  struct prompt *prompt;
292
293  va_start(ap, fmt);
294  if (log_IsKept(lev)) {
295    char nfmt[200];
296
297    if ((log_IsKept(lev) & LOG_KEPT_LOCAL) && promptlist) {
298      if ((log_IsKept(LogTUN) & LOG_KEPT_LOCAL) && LogTunno != -1)
299        snprintf(nfmt, sizeof nfmt, "%s%d: %s: %s", TUN_NAME,
300	         LogTunno, log_Name(lev), fmt);
301      else
302        snprintf(nfmt, sizeof nfmt, "%s: %s", log_Name(lev), fmt);
303
304      for (prompt = promptlist; prompt; prompt = prompt->next)
305        if (lev > LogMAXCONF || (prompt->logmask & MSK(lev)))
306          prompt_vPrintf(prompt, nfmt, ap);
307    }
308
309    if ((log_IsKept(lev) & LOG_KEPT_SYSLOG) &&
310        (lev != LogWARN || !promptlist)) {
311      if ((log_IsKept(LogTUN) & LOG_KEPT_SYSLOG) && LogTunno != -1)
312        snprintf(nfmt, sizeof nfmt, "%s%d: %s: %s", TUN_NAME,
313	         LogTunno, log_Name(lev), fmt);
314      else
315        snprintf(nfmt, sizeof nfmt, "%s: %s", log_Name(lev), fmt);
316      vsyslog(syslogLevel(lev), nfmt, ap);
317    }
318  }
319  va_end(ap);
320}
321
322void
323log_DumpBp(int lev, const char *hdr, const struct mbuf * bp)
324{
325  if (log_IsKept(lev)) {
326    char buf[50];
327    char *b;
328    u_char *ptr;
329    int f;
330
331    if (hdr && *hdr)
332      log_Printf(lev, "%s\n", hdr);
333
334    b = buf;
335    do {
336      f = bp->cnt;
337      ptr = MBUF_CTOP(bp);
338      while (f--) {
339	sprintf(b, " %02x", (int) *ptr++);
340        b += 3;
341        if (b == buf + sizeof buf - 2) {
342          strcpy(b, "\n");
343          log_Printf(lev, buf);
344          b = buf;
345        }
346      }
347    } while ((bp = bp->next) != NULL);
348
349    if (b > buf) {
350      strcpy(b, "\n");
351      log_Printf(lev, buf);
352    }
353  }
354}
355
356void
357log_DumpBuff(int lev, const char *hdr, const u_char * ptr, int n)
358{
359  if (log_IsKept(lev)) {
360    char buf[50];
361    char *b;
362
363    if (hdr && *hdr)
364      log_Printf(lev, "%s\n", hdr);
365    while (n > 0) {
366      b = buf;
367      for (b = buf; b != buf + sizeof buf - 2 && n--; b += 3)
368	sprintf(b, " %02x", (int) *ptr++);
369      strcpy(b, "\n");
370      log_Printf(lev, buf);
371    }
372  }
373}
374
375int
376log_ShowLevel(struct cmdargs const *arg)
377{
378  int i;
379
380  prompt_Printf(arg->prompt, "Log:  ");
381  for (i = LogMIN; i <= LogMAX; i++)
382    if (log_IsKept(i) & LOG_KEPT_SYSLOG)
383      prompt_Printf(arg->prompt, " %s", log_Name(i));
384
385  prompt_Printf(arg->prompt, "\nLocal:");
386  for (i = LogMIN; i <= LogMAX; i++)
387    if (log_IsKeptLocal(i, arg->prompt->logmask) & LOG_KEPT_LOCAL)
388      prompt_Printf(arg->prompt, " %s", log_Name(i));
389
390  prompt_Printf(arg->prompt, "\n");
391
392  return 0;
393}
394
395int
396log_SetLevel(struct cmdargs const *arg)
397{
398  int i, res, argc, local;
399  char const *const *argv, *argp;
400
401  argc = arg->argc - arg->argn;
402  argv = arg->argv + arg->argn;
403  res = 0;
404
405  if (argc == 0 || strcasecmp(argv[0], "local"))
406    local = 0;
407  else {
408    if (arg->prompt == NULL) {
409      log_Printf(LogWARN, "set log local: Only available on the command line\n");
410      return 1;
411    }
412    argc--;
413    argv++;
414    local = 1;
415  }
416
417  if (argc == 0 || (argv[0][0] != '+' && argv[0][0] != '-')) {
418    if (local)
419      log_DiscardAllLocal(&arg->prompt->logmask);
420    else
421      log_DiscardAll();
422  }
423
424  while (argc--) {
425    argp = **argv == '+' || **argv == '-' ? *argv + 1 : *argv;
426    for (i = LogMIN; i <= LogMAX; i++)
427      if (strcasecmp(argp, log_Name(i)) == 0) {
428	if (**argv == '-') {
429          if (local)
430            log_DiscardLocal(i, &arg->prompt->logmask);
431          else
432	    log_Discard(i);
433	} else if (local)
434          log_KeepLocal(i, &arg->prompt->logmask);
435        else
436          log_Keep(i);
437	break;
438      }
439    if (i > LogMAX) {
440      log_Printf(LogWARN, "%s: Invalid log value\n", argp);
441      res = -1;
442    }
443    argv++;
444  }
445  return res;
446}
447
448int
449log_ShowWho(struct cmdargs const *arg)
450{
451  struct prompt *p;
452
453  for (p = promptlist; p; p = p->next) {
454    prompt_Printf(arg->prompt, "%s (%s)", p->src.type, p->src.from);
455    if (p == arg->prompt)
456      prompt_Printf(arg->prompt, " *");
457    if (!p->active)
458      prompt_Printf(arg->prompt, " ^Z");
459    prompt_Printf(arg->prompt, "\n");
460  }
461
462  return 0;
463}
464