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