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