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