xref: /freebsd/usr.sbin/ppp/log.c (revision 41466b50c1d5bfd1cf6adaae547a579a75d7c04e)
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  * $FreeBSD$
27  */
28 
29 #include <sys/types.h>
30 
31 #include <ctype.h>
32 #include <stdarg.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <syslog.h>
36 #include <termios.h>
37 
38 #include "defs.h"
39 #include "command.h"
40 #include "mbuf.h"
41 #include "log.h"
42 #include "descriptor.h"
43 #include "prompt.h"
44 
45 static const char *const LogNames[] = {
46   "Async",
47   "CBCP",
48   "CCP",
49   "Chat",
50   "Command",
51   "Connect",
52   "Debug",
53   "DNS",
54   "Filter",			/* Log discarded packets */
55   "HDLC",
56   "ID0",
57   "IPCP",
58   "IPV6CP",
59   "LCP",
60   "LQM",
61   "Phase",
62   "Physical",
63   "Sync",
64   "TCP/IP",
65   "Timer",
66   "Tun",
67   "Warning",
68   "Error",
69   "Alert"
70 };
71 
72 #define MSK(n) (1<<((n)-1))
73 
74 static u_long LogMask = MSK(LogPHASE);
75 static u_long LogMaskLocal = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
76 static int LogTunno = -1;
77 static struct prompt *promptlist;	/* Where to log local stuff */
78 struct prompt *log_PromptContext;
79 int log_PromptListChanged;
80 
81 struct prompt *
82 log_PromptList()
83 {
84   return promptlist;
85 }
86 
87 void
88 log_RegisterPrompt(struct prompt *prompt)
89 {
90   prompt->next = promptlist;
91   promptlist = prompt;
92   prompt->active = 1;
93   log_DiscardAllLocal(&prompt->logmask);
94 }
95 
96 void
97 log_ActivatePrompt(struct prompt *prompt)
98 {
99   prompt->active = 1;
100   LogMaskLocal |= prompt->logmask;
101 }
102 
103 static void
104 LogSetMaskLocal(void)
105 {
106   struct prompt *p;
107 
108   LogMaskLocal = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
109   for (p = promptlist; p; p = p->next)
110     LogMaskLocal |= p->logmask;
111 }
112 
113 void
114 log_DeactivatePrompt(struct prompt *prompt)
115 {
116   if (prompt->active) {
117     prompt->active = 0;
118     LogSetMaskLocal();
119   }
120 }
121 
122 void
123 log_UnRegisterPrompt(struct prompt *prompt)
124 {
125   if (prompt) {
126     struct prompt **p;
127 
128     for (p = &promptlist; *p; p = &(*p)->next)
129       if (*p == prompt) {
130         *p = prompt->next;
131         prompt->next = NULL;
132         break;
133       }
134     LogSetMaskLocal();
135     log_PromptListChanged++;
136   }
137 }
138 
139 void
140 log_DestroyPrompts(struct server *s)
141 {
142   struct prompt *p, *pn, *pl;
143 
144   p = promptlist;
145   pl = NULL;
146   while (p) {
147     pn = p->next;
148     if (s && p->owner == s) {
149       if (pl)
150         pl->next = p->next;
151       else
152         promptlist = p->next;
153       p->next = NULL;
154       prompt_Destroy(p, 1);
155     } else
156       pl = p;
157     p = pn;
158   }
159 }
160 
161 void
162 log_DisplayPrompts()
163 {
164   struct prompt *p;
165 
166   for (p = promptlist; p; p = p->next)
167     prompt_Required(p);
168 }
169 
170 void
171 log_WritePrompts(struct datalink *dl, const char *fmt,...)
172 {
173   va_list ap;
174   struct prompt *p;
175 
176   va_start(ap, fmt);
177   for (p = promptlist; p; p = p->next)
178     if (prompt_IsTermMode(p, dl))
179       prompt_vPrintf(p, fmt, ap);
180   va_end(ap);
181 }
182 
183 void
184 log_SetTtyCommandMode(struct datalink *dl)
185 {
186   struct prompt *p;
187 
188   for (p = promptlist; p; p = p->next)
189     if (prompt_IsTermMode(p, dl))
190       prompt_TtyCommandMode(p);
191 }
192 
193 static int
194 syslogLevel(int lev)
195 {
196   switch (lev) {
197   case LogDEBUG:
198   case LogTIMER:
199     return LOG_DEBUG;
200   case LogWARN:
201     return LOG_WARNING;
202   case LogERROR:
203     return LOG_ERR;
204   case LogALERT:
205     return LOG_ALERT;
206   }
207   return lev >= LogMIN && lev <= LogMAX ? LOG_INFO : 0;
208 }
209 
210 const char *
211 log_Name(int id)
212 {
213   return id < LogMIN || id > LogMAX ? "Unknown" : LogNames[id - 1];
214 }
215 
216 void
217 log_Keep(int id)
218 {
219   if (id >= LogMIN && id <= LogMAXCONF)
220     LogMask |= MSK(id);
221 }
222 
223 void
224 log_KeepLocal(int id, u_long *mask)
225 {
226   if (id >= LogMIN && id <= LogMAXCONF) {
227     LogMaskLocal |= MSK(id);
228     *mask |= MSK(id);
229   }
230 }
231 
232 void
233 log_Discard(int id)
234 {
235   if (id >= LogMIN && id <= LogMAXCONF)
236     LogMask &= ~MSK(id);
237 }
238 
239 void
240 log_DiscardLocal(int id, u_long *mask)
241 {
242   if (id >= LogMIN && id <= LogMAXCONF) {
243     *mask &= ~MSK(id);
244     LogSetMaskLocal();
245   }
246 }
247 
248 void
249 log_DiscardAll()
250 {
251   LogMask = 0;
252 }
253 
254 void
255 log_DiscardAllLocal(u_long *mask)
256 {
257   *mask = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
258   LogSetMaskLocal();
259 }
260 
261 int
262 log_IsKept(int id)
263 {
264   if (id < LogMIN || id > LogMAX)
265     return 0;
266   if (id > LogMAXCONF)
267     return LOG_KEPT_LOCAL | LOG_KEPT_SYSLOG;
268 
269   return ((LogMaskLocal & MSK(id)) ? LOG_KEPT_LOCAL : 0) |
270     ((LogMask & MSK(id)) ? LOG_KEPT_SYSLOG : 0);
271 }
272 
273 int
274 log_IsKeptLocal(int id, u_long mask)
275 {
276   if (id < LogMIN || id > LogMAX)
277     return 0;
278   if (id > LogMAXCONF)
279     return LOG_KEPT_LOCAL | LOG_KEPT_SYSLOG;
280 
281   return ((mask & MSK(id)) ? LOG_KEPT_LOCAL : 0) |
282     ((LogMask & MSK(id)) ? LOG_KEPT_SYSLOG : 0);
283 }
284 
285 void
286 log_Open(const char *Name)
287 {
288   openlog(Name, LOG_PID, LOG_DAEMON);
289 }
290 
291 void
292 log_SetTun(int tunno)
293 {
294   LogTunno = tunno;
295 }
296 
297 void
298 log_Close()
299 {
300   closelog();
301   LogTunno = -1;
302 }
303 
304 void
305 log_Printf(int lev, const char *fmt,...)
306 {
307   va_list ap;
308   struct prompt *prompt;
309 
310   if (log_IsKept(lev)) {
311     char nfmt[200];
312 
313     va_start(ap, fmt);
314     if (promptlist && (log_IsKept(lev) & LOG_KEPT_LOCAL)) {
315       if ((log_IsKept(LogTUN) & LOG_KEPT_LOCAL) && LogTunno != -1)
316         snprintf(nfmt, sizeof nfmt, "%s%d: %s: %s", TUN_NAME,
317 	         LogTunno, log_Name(lev), fmt);
318       else
319         snprintf(nfmt, sizeof nfmt, "%s: %s", log_Name(lev), fmt);
320 
321       if (log_PromptContext && lev == LogWARN)
322         /* Warnings just go to the current prompt */
323         prompt_vPrintf(log_PromptContext, nfmt, ap);
324       else for (prompt = promptlist; prompt; prompt = prompt->next)
325         if (lev > LogMAXCONF || (prompt->logmask & MSK(lev)))
326           prompt_vPrintf(prompt, nfmt, ap);
327     }
328     va_end(ap);
329 
330     va_start(ap, fmt);
331     if ((log_IsKept(lev) & LOG_KEPT_SYSLOG) &&
332         (lev != LogWARN || !log_PromptContext)) {
333       if ((log_IsKept(LogTUN) & LOG_KEPT_SYSLOG) && LogTunno != -1)
334         snprintf(nfmt, sizeof nfmt, "%s%d: %s: %s", TUN_NAME,
335 	         LogTunno, log_Name(lev), fmt);
336       else
337         snprintf(nfmt, sizeof nfmt, "%s: %s", log_Name(lev), fmt);
338       vsyslog(syslogLevel(lev), nfmt, ap);
339     }
340     va_end(ap);
341   }
342 }
343 
344 void
345 log_DumpBp(int lev, const char *hdr, const struct mbuf *bp)
346 {
347   if (log_IsKept(lev)) {
348     char buf[68];
349     char *b, *c;
350     const u_char *ptr;
351     int f;
352 
353     if (hdr && *hdr)
354       log_Printf(lev, "%s\n", hdr);
355 
356     b = buf;
357     c = b + 50;
358     do {
359       f = bp->m_len;
360       ptr = CONST_MBUF_CTOP(bp);
361       while (f--) {
362 	sprintf(b, " %02x", (int) *ptr);
363         *c++ = isprint(*ptr) ? *ptr : '.';
364         ptr++;
365         b += 3;
366         if (b == buf + 48) {
367           memset(b, ' ', 2);
368           *c = '\0';
369           log_Printf(lev, "%s\n", buf);
370           b = buf;
371           c = b + 50;
372         }
373       }
374     } while ((bp = bp->m_next) != NULL);
375 
376     if (b > buf) {
377       memset(b, ' ', 50 - (b - buf));
378       *c = '\0';
379       log_Printf(lev, "%s\n", buf);
380     }
381   }
382 }
383 
384 void
385 log_DumpBuff(int lev, const char *hdr, const u_char *ptr, int n)
386 {
387   if (log_IsKept(lev)) {
388     char buf[68];
389     char *b, *c;
390 
391     if (hdr && *hdr)
392       log_Printf(lev, "%s\n", hdr);
393     while (n > 0) {
394       b = buf;
395       c = b + 50;
396       for (b = buf; b != buf + 48 && n--; b += 3, ptr++) {
397 	sprintf(b, " %02x", (int) *ptr);
398         *c++ = isprint(*ptr) ? *ptr : '.';
399       }
400       memset(b, ' ', 50 - (b - buf));
401       *c = '\0';
402       log_Printf(lev, "%s\n", buf);
403     }
404   }
405 }
406 
407 int
408 log_ShowLevel(struct cmdargs const *arg)
409 {
410   int i;
411 
412   prompt_Printf(arg->prompt, "Log:  ");
413   for (i = LogMIN; i <= LogMAX; i++)
414     if (log_IsKept(i) & LOG_KEPT_SYSLOG)
415       prompt_Printf(arg->prompt, " %s", log_Name(i));
416 
417   prompt_Printf(arg->prompt, "\nLocal:");
418   for (i = LogMIN; i <= LogMAX; i++)
419     if (log_IsKeptLocal(i, arg->prompt->logmask) & LOG_KEPT_LOCAL)
420       prompt_Printf(arg->prompt, " %s", log_Name(i));
421 
422   prompt_Printf(arg->prompt, "\n");
423 
424   return 0;
425 }
426 
427 int
428 log_SetLevel(struct cmdargs const *arg)
429 {
430   int i, res, argc, local;
431   char const *const *argv, *argp;
432 
433   argc = arg->argc - arg->argn;
434   argv = arg->argv + arg->argn;
435   res = 0;
436 
437   if (argc == 0 || strcasecmp(argv[0], "local"))
438     local = 0;
439   else {
440     if (arg->prompt == NULL) {
441       log_Printf(LogWARN, "set log local: Only available on the"
442                  " command line\n");
443       return 1;
444     }
445     argc--;
446     argv++;
447     local = 1;
448   }
449 
450   if (argc == 0 || (argv[0][0] != '+' && argv[0][0] != '-')) {
451     if (local)
452       log_DiscardAllLocal(&arg->prompt->logmask);
453     else
454       log_DiscardAll();
455   }
456 
457   while (argc--) {
458     argp = **argv == '+' || **argv == '-' ? *argv + 1 : *argv;
459     /* Special case 'all' */
460     if (strcasecmp(argp, "all") == 0) {
461         if (**argv == '-') {
462           if (local)
463             for (i = LogMIN; i <= LogMAX; i++)
464               log_DiscardLocal(i, &arg->prompt->logmask);
465           else
466             for (i = LogMIN; i <= LogMAX; i++)
467               log_Discard(i);
468         } else if (local)
469           for (i = LogMIN; i <= LogMAX; i++)
470             log_KeepLocal(i, &arg->prompt->logmask);
471         else
472           for (i = LogMIN; i <= LogMAX; i++)
473             log_Keep(i);
474         argv++;
475         continue;
476     }
477     for (i = LogMIN; i <= LogMAX; i++)
478       if (strcasecmp(argp, log_Name(i)) == 0) {
479 	if (**argv == '-') {
480           if (local)
481             log_DiscardLocal(i, &arg->prompt->logmask);
482           else
483 	    log_Discard(i);
484 	} else if (local)
485           log_KeepLocal(i, &arg->prompt->logmask);
486         else
487           log_Keep(i);
488 	break;
489       }
490     if (i > LogMAX) {
491       log_Printf(LogWARN, "%s: Invalid log value\n", argp);
492       res = -1;
493     }
494     argv++;
495   }
496   return res;
497 }
498 
499 int
500 log_ShowWho(struct cmdargs const *arg)
501 {
502   struct prompt *p;
503 
504   for (p = promptlist; p; p = p->next) {
505     prompt_Printf(arg->prompt, "%s (%s)", p->src.type, p->src.from);
506     if (p == arg->prompt)
507       prompt_Printf(arg->prompt, " *");
508     if (!p->active)
509       prompt_Printf(arg->prompt, " ^Z");
510     prompt_Printf(arg->prompt, "\n");
511   }
512 
513   return 0;
514 }
515