log.c revision 44544
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.35 1998/08/21 18:10:14 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, *pl; 136 137 p = promptlist; 138 pl = NULL; 139 while (p) { 140 pn = p->next; 141 if (s && p->owner == s) { 142 if (pl) 143 pl->next = p->next; 144 else 145 promptlist = p->next; 146 p->next = NULL; 147 prompt_Destroy(p, 1); 148 } else 149 pl = p; 150 p = pn; 151 } 152} 153 154void 155log_DisplayPrompts() 156{ 157 struct prompt *p; 158 159 for (p = promptlist; p; p = p->next) 160 prompt_Required(p); 161} 162 163void 164log_WritePrompts(struct datalink *dl, const char *fmt,...) 165{ 166 va_list ap; 167 struct prompt *p; 168 169 va_start(ap, fmt); 170 for (p = promptlist; p; p = p->next) 171 if (prompt_IsTermMode(p, dl)) 172 prompt_vPrintf(p, fmt, ap); 173 va_end(ap); 174} 175 176void 177log_SetTtyCommandMode(struct datalink *dl) 178{ 179 struct prompt *p; 180 181 for (p = promptlist; p; p = p->next) 182 if (prompt_IsTermMode(p, dl)) 183 prompt_TtyCommandMode(p); 184} 185 186static int 187syslogLevel(int lev) 188{ 189 switch (lev) { 190 case LogDEBUG: 191 case LogTIMER: 192 return LOG_DEBUG; 193 case LogWARN: 194 return LOG_WARNING; 195 case LogERROR: 196 return LOG_ERR; 197 case LogALERT: 198 return LOG_ALERT; 199 } 200 return lev >= LogMIN && lev <= LogMAX ? LOG_INFO : 0; 201} 202 203const char * 204log_Name(int id) 205{ 206 return id < LogMIN || id > LogMAX ? "Unknown" : LogNames[id - 1]; 207} 208 209void 210log_Keep(int id) 211{ 212 if (id >= LogMIN && id <= LogMAXCONF) 213 LogMask |= MSK(id); 214} 215 216void 217log_KeepLocal(int id, u_long *mask) 218{ 219 if (id >= LogMIN && id <= LogMAXCONF) { 220 LogMaskLocal |= MSK(id); 221 *mask |= MSK(id); 222 } 223} 224 225void 226log_Discard(int id) 227{ 228 if (id >= LogMIN && id <= LogMAXCONF) 229 LogMask &= ~MSK(id); 230} 231 232void 233log_DiscardLocal(int id, u_long *mask) 234{ 235 if (id >= LogMIN && id <= LogMAXCONF) { 236 *mask &= ~MSK(id); 237 LogSetMaskLocal(); 238 } 239} 240 241void 242log_DiscardAll() 243{ 244 LogMask = 0; 245} 246 247void 248log_DiscardAllLocal(u_long *mask) 249{ 250 *mask = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN); 251 LogSetMaskLocal(); 252} 253 254int 255log_IsKept(int id) 256{ 257 if (id < LogMIN || id > LogMAX) 258 return 0; 259 if (id > LogMAXCONF) 260 return LOG_KEPT_LOCAL | LOG_KEPT_SYSLOG; 261 262 return ((LogMaskLocal & MSK(id)) ? LOG_KEPT_LOCAL : 0) | 263 ((LogMask & MSK(id)) ? LOG_KEPT_SYSLOG : 0); 264} 265 266int 267log_IsKeptLocal(int id, u_long mask) 268{ 269 if (id < LogMIN || id > LogMAX) 270 return 0; 271 if (id > LogMAXCONF) 272 return LOG_KEPT_LOCAL | LOG_KEPT_SYSLOG; 273 274 return ((mask & MSK(id)) ? LOG_KEPT_LOCAL : 0) | 275 ((LogMask & MSK(id)) ? LOG_KEPT_SYSLOG : 0); 276} 277 278void 279log_Open(const char *Name) 280{ 281 openlog(Name, LOG_PID, LOG_DAEMON); 282} 283 284void 285log_SetTun(int tunno) 286{ 287 LogTunno = tunno; 288} 289 290void 291log_Close() 292{ 293 closelog(); 294 LogTunno = -1; 295} 296 297void 298log_Printf(int lev, const char *fmt,...) 299{ 300 va_list ap; 301 struct prompt *prompt; 302 303 va_start(ap, fmt); 304 if (log_IsKept(lev)) { 305 char nfmt[200]; 306 307 if ((log_IsKept(lev) & LOG_KEPT_LOCAL) && promptlist) { 308 if ((log_IsKept(LogTUN) & LOG_KEPT_LOCAL) && LogTunno != -1) 309 snprintf(nfmt, sizeof nfmt, "%s%d: %s: %s", TUN_NAME, 310 LogTunno, log_Name(lev), fmt); 311 else 312 snprintf(nfmt, sizeof nfmt, "%s: %s", log_Name(lev), fmt); 313 314 for (prompt = promptlist; prompt; prompt = prompt->next) 315 if (lev > LogMAXCONF || (prompt->logmask & MSK(lev))) 316 prompt_vPrintf(prompt, nfmt, ap); 317 } 318 319 if ((log_IsKept(lev) & LOG_KEPT_SYSLOG) && 320 (lev != LogWARN || !promptlist)) { 321 if ((log_IsKept(LogTUN) & LOG_KEPT_SYSLOG) && LogTunno != -1) 322 snprintf(nfmt, sizeof nfmt, "%s%d: %s: %s", TUN_NAME, 323 LogTunno, log_Name(lev), fmt); 324 else 325 snprintf(nfmt, sizeof nfmt, "%s: %s", log_Name(lev), fmt); 326 vsyslog(syslogLevel(lev), nfmt, ap); 327 } 328 } 329 va_end(ap); 330} 331 332void 333log_DumpBp(int lev, const char *hdr, const struct mbuf *bp) 334{ 335 if (log_IsKept(lev)) { 336 char buf[50]; 337 char *b; 338 const u_char *ptr; 339 int f; 340 341 if (hdr && *hdr) 342 log_Printf(lev, "%s\n", hdr); 343 344 b = buf; 345 do { 346 f = bp->cnt; 347 ptr = CONST_MBUF_CTOP(bp); 348 while (f--) { 349 sprintf(b, " %02x", (int) *ptr++); 350 b += 3; 351 if (b == buf + sizeof buf - 2) { 352 strcpy(b, "\n"); 353 log_Printf(lev, buf); 354 b = buf; 355 } 356 } 357 } while ((bp = bp->next) != NULL); 358 359 if (b > buf) { 360 strcpy(b, "\n"); 361 log_Printf(lev, buf); 362 } 363 } 364} 365 366void 367log_DumpBuff(int lev, const char *hdr, const u_char * ptr, int n) 368{ 369 if (log_IsKept(lev)) { 370 char buf[50]; 371 char *b; 372 373 if (hdr && *hdr) 374 log_Printf(lev, "%s\n", hdr); 375 while (n > 0) { 376 b = buf; 377 for (b = buf; b != buf + sizeof buf - 2 && n--; b += 3) 378 sprintf(b, " %02x", (int) *ptr++); 379 strcpy(b, "\n"); 380 log_Printf(lev, buf); 381 } 382 } 383} 384 385int 386log_ShowLevel(struct cmdargs const *arg) 387{ 388 int i; 389 390 prompt_Printf(arg->prompt, "Log: "); 391 for (i = LogMIN; i <= LogMAX; i++) 392 if (log_IsKept(i) & LOG_KEPT_SYSLOG) 393 prompt_Printf(arg->prompt, " %s", log_Name(i)); 394 395 prompt_Printf(arg->prompt, "\nLocal:"); 396 for (i = LogMIN; i <= LogMAX; i++) 397 if (log_IsKeptLocal(i, arg->prompt->logmask) & LOG_KEPT_LOCAL) 398 prompt_Printf(arg->prompt, " %s", log_Name(i)); 399 400 prompt_Printf(arg->prompt, "\n"); 401 402 return 0; 403} 404 405int 406log_SetLevel(struct cmdargs const *arg) 407{ 408 int i, res, argc, local; 409 char const *const *argv, *argp; 410 411 argc = arg->argc - arg->argn; 412 argv = arg->argv + arg->argn; 413 res = 0; 414 415 if (argc == 0 || strcasecmp(argv[0], "local")) 416 local = 0; 417 else { 418 if (arg->prompt == NULL) { 419 log_Printf(LogWARN, "set log local: Only available on the command line\n"); 420 return 1; 421 } 422 argc--; 423 argv++; 424 local = 1; 425 } 426 427 if (argc == 0 || (argv[0][0] != '+' && argv[0][0] != '-')) { 428 if (local) 429 log_DiscardAllLocal(&arg->prompt->logmask); 430 else 431 log_DiscardAll(); 432 } 433 434 while (argc--) { 435 argp = **argv == '+' || **argv == '-' ? *argv + 1 : *argv; 436 for (i = LogMIN; i <= LogMAX; i++) 437 if (strcasecmp(argp, log_Name(i)) == 0) { 438 if (**argv == '-') { 439 if (local) 440 log_DiscardLocal(i, &arg->prompt->logmask); 441 else 442 log_Discard(i); 443 } else if (local) 444 log_KeepLocal(i, &arg->prompt->logmask); 445 else 446 log_Keep(i); 447 break; 448 } 449 if (i > LogMAX) { 450 log_Printf(LogWARN, "%s: Invalid log value\n", argp); 451 res = -1; 452 } 453 argv++; 454 } 455 return res; 456} 457 458int 459log_ShowWho(struct cmdargs const *arg) 460{ 461 struct prompt *p; 462 463 for (p = promptlist; p; p = p->next) { 464 prompt_Printf(arg->prompt, "%s (%s)", p->src.type, p->src.from); 465 if (p == arg->prompt) 466 prompt_Printf(arg->prompt, " *"); 467 if (!p->active) 468 prompt_Printf(arg->prompt, " ^Z"); 469 prompt_Printf(arg->prompt, "\n"); 470 } 471 472 return 0; 473} 474