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