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