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