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.34 1998/08/09 15:34:11 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 44 static 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 68 static u_long LogMask = MSK(LogPHASE); 69 static u_long LogMaskLocal = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN); 70 static int LogTunno = -1; 71 static struct prompt *promptlist; /* Where to log local stuff */ 72 int log_PromptListChanged; 73 74 struct prompt * 75 log_PromptList() 76 { 77 return promptlist; 78 } 79 80 void 81 log_RegisterPrompt(struct prompt *prompt) 82 { 83 prompt->next = promptlist; 84 promptlist = prompt; 85 prompt->active = 1; 86 log_DiscardAllLocal(&prompt->logmask); 87 } 88 89 void 90 log_ActivatePrompt(struct prompt *prompt) 91 { 92 prompt->active = 1; 93 LogMaskLocal |= prompt->logmask; 94 } 95 96 static void 97 LogSetMaskLocal(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 106 void 107 log_DeactivatePrompt(struct prompt *prompt) 108 { 109 if (prompt->active) { 110 prompt->active = 0; 111 LogSetMaskLocal(); 112 } 113 } 114 115 void 116 log_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 132 void 133 log_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 148 void 149 log_DisplayPrompts() 150 { 151 struct prompt *p; 152 153 for (p = promptlist; p; p = p->next) 154 prompt_Required(p); 155 } 156 157 void 158 log_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 170 void 171 log_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 180 static int 181 syslogLevel(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 197 const char * 198 log_Name(int id) 199 { 200 return id < LogMIN || id > LogMAX ? "Unknown" : LogNames[id - 1]; 201 } 202 203 void 204 log_Keep(int id) 205 { 206 if (id >= LogMIN && id <= LogMAXCONF) 207 LogMask |= MSK(id); 208 } 209 210 void 211 log_KeepLocal(int id, u_long *mask) 212 { 213 if (id >= LogMIN && id <= LogMAXCONF) { 214 LogMaskLocal |= MSK(id); 215 *mask |= MSK(id); 216 } 217 } 218 219 void 220 log_Discard(int id) 221 { 222 if (id >= LogMIN && id <= LogMAXCONF) 223 LogMask &= ~MSK(id); 224 } 225 226 void 227 log_DiscardLocal(int id, u_long *mask) 228 { 229 if (id >= LogMIN && id <= LogMAXCONF) { 230 *mask &= ~MSK(id); 231 LogSetMaskLocal(); 232 } 233 } 234 235 void 236 log_DiscardAll() 237 { 238 LogMask = 0; 239 } 240 241 void 242 log_DiscardAllLocal(u_long *mask) 243 { 244 *mask = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN); 245 LogSetMaskLocal(); 246 } 247 248 int 249 log_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 260 int 261 log_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 272 void 273 log_Open(const char *Name) 274 { 275 openlog(Name, LOG_PID, LOG_DAEMON); 276 } 277 278 void 279 log_SetTun(int tunno) 280 { 281 LogTunno = tunno; 282 } 283 284 void 285 log_Close() 286 { 287 closelog(); 288 LogTunno = -1; 289 } 290 291 void 292 log_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 326 void 327 log_DumpBp(int lev, const char *hdr, const struct mbuf *bp) 328 { 329 if (log_IsKept(lev)) { 330 char buf[50]; 331 char *b; 332 const 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 = CONST_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 360 void 361 log_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 379 int 380 log_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 399 int 400 log_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 452 int 453 log_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