log.c revision 58033
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: head/usr.sbin/ppp/log.c 58033 2000-03-14 01:46:49Z brian $ 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 45static 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 72static u_long LogMask = MSK(LogPHASE); 73static u_long LogMaskLocal = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN); 74static int LogTunno = -1; 75static struct prompt *promptlist; /* Where to log local stuff */ 76struct prompt *log_PromptContext; 77int log_PromptListChanged; 78 79struct prompt * 80log_PromptList() 81{ 82 return promptlist; 83} 84 85void 86log_RegisterPrompt(struct prompt *prompt) 87{ 88 prompt->next = promptlist; 89 promptlist = prompt; 90 prompt->active = 1; 91 log_DiscardAllLocal(&prompt->logmask); 92} 93 94void 95log_ActivatePrompt(struct prompt *prompt) 96{ 97 prompt->active = 1; 98 LogMaskLocal |= prompt->logmask; 99} 100 101static void 102LogSetMaskLocal(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 111void 112log_DeactivatePrompt(struct prompt *prompt) 113{ 114 if (prompt->active) { 115 prompt->active = 0; 116 LogSetMaskLocal(); 117 } 118} 119 120void 121log_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 137void 138log_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 159void 160log_DisplayPrompts() 161{ 162 struct prompt *p; 163 164 for (p = promptlist; p; p = p->next) 165 prompt_Required(p); 166} 167 168void 169log_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 181void 182log_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 191static int 192syslogLevel(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 208const char * 209log_Name(int id) 210{ 211 return id < LogMIN || id > LogMAX ? "Unknown" : LogNames[id - 1]; 212} 213 214void 215log_Keep(int id) 216{ 217 if (id >= LogMIN && id <= LogMAXCONF) 218 LogMask |= MSK(id); 219} 220 221void 222log_KeepLocal(int id, u_long *mask) 223{ 224 if (id >= LogMIN && id <= LogMAXCONF) { 225 LogMaskLocal |= MSK(id); 226 *mask |= MSK(id); 227 } 228} 229 230void 231log_Discard(int id) 232{ 233 if (id >= LogMIN && id <= LogMAXCONF) 234 LogMask &= ~MSK(id); 235} 236 237void 238log_DiscardLocal(int id, u_long *mask) 239{ 240 if (id >= LogMIN && id <= LogMAXCONF) { 241 *mask &= ~MSK(id); 242 LogSetMaskLocal(); 243 } 244} 245 246void 247log_DiscardAll() 248{ 249 LogMask = 0; 250} 251 252void 253log_DiscardAllLocal(u_long *mask) 254{ 255 *mask = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN); 256 LogSetMaskLocal(); 257} 258 259int 260log_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 271int 272log_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 283void 284log_Open(const char *Name) 285{ 286 openlog(Name, LOG_PID, LOG_DAEMON); 287} 288 289void 290log_SetTun(int tunno) 291{ 292 LogTunno = tunno; 293} 294 295void 296log_Close() 297{ 298 closelog(); 299 LogTunno = -1; 300} 301 302void 303log_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 340void 341log_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 380void 381log_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 403int 404log_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 423int 424log_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 476int 477log_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