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