1 /* $OpenBSD: log.c,v 1.28 2016/07/01 23:36:38 renato Exp $ */ 2 3 /* 4 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <arpa/inet.h> 20 #include <errno.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include <syslog.h> 25 #include <unistd.h> 26 #include <netdb.h> 27 28 #include "ldpd.h" 29 #include "ldpe.h" 30 #include "lde.h" 31 #include "log.h" 32 33 static const char * const procnames[] = { 34 "parent", 35 "ldpe", 36 "lde" 37 }; 38 39 static void vlog(int, const char *, va_list); 40 41 static int debug; 42 static int verbose; 43 44 void 45 log_init(int n_debug) 46 { 47 extern char *__progname; 48 49 debug = n_debug; 50 51 if (!debug) 52 openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON); 53 54 tzset(); 55 } 56 57 void 58 log_verbose(int v) 59 { 60 verbose = v; 61 } 62 63 void 64 logit(int pri, const char *fmt, ...) 65 { 66 va_list ap; 67 68 va_start(ap, fmt); 69 vlog(pri, fmt, ap); 70 va_end(ap); 71 } 72 73 static void 74 vlog(int pri, const char *fmt, va_list ap) 75 { 76 char *nfmt; 77 78 if (debug) { 79 /* best effort in out of mem situations */ 80 if (asprintf(&nfmt, "%s\n", fmt) == -1) { 81 vfprintf(stderr, fmt, ap); 82 fprintf(stderr, "\n"); 83 } else { 84 vfprintf(stderr, nfmt, ap); 85 free(nfmt); 86 } 87 fflush(stderr); 88 } else 89 vsyslog(pri, fmt, ap); 90 } 91 92 void 93 log_warn(const char *emsg, ...) 94 { 95 char *nfmt; 96 va_list ap; 97 98 /* best effort to even work in out of memory situations */ 99 if (emsg == NULL) 100 logit(LOG_CRIT, "%s", strerror(errno)); 101 else { 102 va_start(ap, emsg); 103 104 if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) { 105 /* we tried it... */ 106 vlog(LOG_CRIT, emsg, ap); 107 logit(LOG_CRIT, "%s", strerror(errno)); 108 } else { 109 vlog(LOG_CRIT, nfmt, ap); 110 free(nfmt); 111 } 112 va_end(ap); 113 } 114 } 115 116 void 117 log_warnx(const char *emsg, ...) 118 { 119 va_list ap; 120 121 va_start(ap, emsg); 122 vlog(LOG_CRIT, emsg, ap); 123 va_end(ap); 124 } 125 126 void 127 log_info(const char *emsg, ...) 128 { 129 va_list ap; 130 131 va_start(ap, emsg); 132 vlog(LOG_INFO, emsg, ap); 133 va_end(ap); 134 } 135 136 void 137 log_debug(const char *emsg, ...) 138 { 139 va_list ap; 140 141 if (verbose & LDPD_OPT_VERBOSE) { 142 va_start(ap, emsg); 143 vlog(LOG_DEBUG, emsg, ap); 144 va_end(ap); 145 } 146 } 147 148 void 149 fatal(const char *emsg) 150 { 151 if (emsg == NULL) 152 logit(LOG_CRIT, "fatal in %s: %s", procnames[ldpd_process], 153 strerror(errno)); 154 else 155 if (errno) 156 logit(LOG_CRIT, "fatal in %s: %s: %s", 157 procnames[ldpd_process], emsg, strerror(errno)); 158 else 159 logit(LOG_CRIT, "fatal in %s: %s", 160 procnames[ldpd_process], emsg); 161 162 if (ldpd_process == PROC_MAIN) 163 exit(1); 164 else /* parent copes via SIGCHLD */ 165 _exit(1); 166 } 167 168 void 169 fatalx(const char *emsg) 170 { 171 errno = 0; 172 fatal(emsg); 173 } 174 175 #define NUM_LOGS 4 176 const char * 177 log_sockaddr(void *vp) 178 { 179 static char buf[NUM_LOGS][NI_MAXHOST]; 180 static int round = 0; 181 struct sockaddr *sa = vp; 182 183 round = (round + 1) % NUM_LOGS; 184 185 if (getnameinfo(sa, sa->sa_len, buf[round], NI_MAXHOST, NULL, 0, 186 NI_NUMERICHOST)) 187 return ("(unknown)"); 188 else 189 return (buf[round]); 190 } 191 192 const char * 193 log_in6addr(const struct in6_addr *addr) 194 { 195 struct sockaddr_in6 sa_in6; 196 197 memset(&sa_in6, 0, sizeof(sa_in6)); 198 sa_in6.sin6_len = sizeof(sa_in6); 199 sa_in6.sin6_family = AF_INET6; 200 sa_in6.sin6_addr = *addr; 201 202 recoverscope(&sa_in6); 203 204 return (log_sockaddr(&sa_in6)); 205 } 206 207 const char * 208 log_in6addr_scope(const struct in6_addr *addr, unsigned int ifindex) 209 { 210 struct sockaddr_in6 sa_in6; 211 212 memset(&sa_in6, 0, sizeof(sa_in6)); 213 sa_in6.sin6_len = sizeof(sa_in6); 214 sa_in6.sin6_family = AF_INET6; 215 sa_in6.sin6_addr = *addr; 216 217 addscope(&sa_in6, ifindex); 218 219 return (log_sockaddr(&sa_in6)); 220 } 221 222 const char * 223 log_addr(int af, const union ldpd_addr *addr) 224 { 225 static char buf[NUM_LOGS][INET6_ADDRSTRLEN]; 226 static int round = 0; 227 228 switch (af) { 229 case AF_INET: 230 round = (round + 1) % NUM_LOGS; 231 if (inet_ntop(AF_INET, &addr->v4, buf[round], 232 sizeof(buf[round])) == NULL) 233 return ("???"); 234 return (buf[round]); 235 case AF_INET6: 236 return (log_in6addr(&addr->v6)); 237 default: 238 break; 239 } 240 241 return ("???"); 242 } 243 244 /* names */ 245 const char * 246 af_name(int af) 247 { 248 switch (af) { 249 case AF_INET: 250 return ("ipv4"); 251 case AF_INET6: 252 return ("ipv6"); 253 case AF_MPLS: 254 return ("mpls"); 255 default: 256 return ("UNKNOWN"); 257 } 258 } 259 260 const char * 261 socket_name(int type) 262 { 263 switch (type) { 264 case LDP_SOCKET_DISC: 265 return ("discovery"); 266 case LDP_SOCKET_EDISC: 267 return ("extended discovery"); 268 case LDP_SOCKET_SESSION: 269 return ("session"); 270 default: 271 return ("UNKNOWN"); 272 } 273 } 274 275 const char * 276 nbr_state_name(int state) 277 { 278 switch (state) { 279 case NBR_STA_PRESENT: 280 return ("PRESENT"); 281 case NBR_STA_INITIAL: 282 return ("INITIALIZED"); 283 case NBR_STA_OPENREC: 284 return ("OPENREC"); 285 case NBR_STA_OPENSENT: 286 return ("OPENSENT"); 287 case NBR_STA_OPER: 288 return ("OPERATIONAL"); 289 default: 290 return ("UNKNOWN"); 291 } 292 } 293 294 const char * 295 if_state_name(int state) 296 { 297 switch (state) { 298 case IF_STA_DOWN: 299 return ("DOWN"); 300 case IF_STA_ACTIVE: 301 return ("ACTIVE"); 302 default: 303 return ("UNKNOWN"); 304 } 305 } 306 307 const char * 308 if_type_name(enum iface_type type) 309 { 310 switch (type) { 311 case IF_TYPE_POINTOPOINT: 312 return ("POINTOPOINT"); 313 case IF_TYPE_BROADCAST: 314 return ("BROADCAST"); 315 } 316 /* NOTREACHED */ 317 return ("UNKNOWN"); 318 } 319 320 const char * 321 status_code_name(uint32_t status) 322 { 323 static char buf[16]; 324 325 switch (status) { 326 case S_SUCCESS: 327 return ("Success"); 328 case S_BAD_LDP_ID: 329 return ("Bad LDP Identifier"); 330 case S_BAD_PROTO_VER: 331 return ("Bad Protocol Version"); 332 case S_BAD_PDU_LEN: 333 return ("Bad PDU Length"); 334 case S_UNKNOWN_MSG: 335 return ("Unknown Message Type"); 336 case S_BAD_MSG_LEN: 337 return ("Bad Message Length"); 338 case S_UNKNOWN_TLV: 339 return ("Unknown TLV"); 340 case S_BAD_TLV_LEN: 341 return ("Bad TLV Length"); 342 case S_BAD_TLV_VAL: 343 return ("Malformed TLV Value"); 344 case S_HOLDTIME_EXP: 345 return ("Hold Timer Expired"); 346 case S_SHUTDOWN: 347 return ("Shutdown"); 348 case S_LOOP_DETECTED: 349 return ("Loop Detected"); 350 case S_UNKNOWN_FEC: 351 return ("Unknown FEC"); 352 case S_NO_ROUTE: 353 return ("No Route"); 354 case S_NO_LABEL_RES: 355 return ("No Label Resources"); 356 case S_AVAILABLE: 357 return ("Label Resources Available"); 358 case S_NO_HELLO: 359 return ("Session Rejected, No Hello"); 360 case S_PARM_ADV_MODE: 361 return ("Rejected Advertisement Mode Parameter"); 362 case S_MAX_PDU_LEN: 363 return ("Rejected Max PDU Length Parameter"); 364 case S_PARM_L_RANGE: 365 return ("Rejected Label Range Parameter"); 366 case S_KEEPALIVE_TMR: 367 return ("KeepAlive Timer Expired"); 368 case S_LAB_REQ_ABRT: 369 return ("Label Request Aborted"); 370 case S_MISS_MSG: 371 return ("Missing Message Parameters"); 372 case S_UNSUP_ADDR: 373 return ("Unsupported Address Family"); 374 case S_KEEPALIVE_BAD: 375 return ("Bad KeepAlive Time"); 376 case S_INTERN_ERR: 377 return ("Internal Error"); 378 case S_ILLEGAL_CBIT: 379 return ("Illegal C-Bit"); 380 case S_WRONG_CBIT: 381 return ("Wrong C-Bit"); 382 case S_INCPT_BITRATE: 383 return ("Incompatible bit-rate"); 384 case S_CEP_MISCONF: 385 return ("CEP-TDM mis-configuration"); 386 case S_PW_STATUS: 387 return ("PW Status"); 388 case S_UNASSIGN_TAI: 389 return ("Unassigned/Unrecognized TAI"); 390 case S_MISCONF_ERR: 391 return ("Generic Misconfiguration Error"); 392 case S_WITHDRAW_MTHD: 393 return ("Label Withdraw PW Status Method"); 394 case S_TRANS_MISMTCH: 395 return ("Transport Connection Mismatch"); 396 case S_DS_NONCMPLNCE: 397 return ("Dual-Stack Noncompliance"); 398 default: 399 snprintf(buf, sizeof(buf), "[%08x]", status); 400 return (buf); 401 } 402 } 403 404 const char * 405 pw_type_name(uint16_t pw_type) 406 { 407 static char buf[64]; 408 409 switch (pw_type) { 410 case PW_TYPE_ETHERNET_TAGGED: 411 return ("Eth Tagged"); 412 case PW_TYPE_ETHERNET: 413 return ("Ethernet"); 414 default: 415 snprintf(buf, sizeof(buf), "[%0x]", pw_type); 416 return (buf); 417 } 418 } 419 420 char * 421 log_hello_src(const struct hello_source *src) 422 { 423 static char buffer[64]; 424 425 switch (src->type) { 426 case HELLO_LINK: 427 snprintf(buffer, sizeof(buffer), "iface %s", 428 src->link.ia->iface->name); 429 break; 430 case HELLO_TARGETED: 431 snprintf(buffer, sizeof(buffer), "source %s", 432 log_addr(src->target->af, &src->target->addr)); 433 break; 434 } 435 436 return (buffer); 437 } 438 439 const char * 440 log_map(const struct map *map) 441 { 442 static char buf[64]; 443 int af; 444 445 switch (map->type) { 446 case MAP_TYPE_WILDCARD: 447 if (snprintf(buf, sizeof(buf), "wildcard") < 0) 448 return ("???"); 449 break; 450 case MAP_TYPE_PREFIX: 451 switch (map->fec.prefix.af) { 452 case AF_IPV4: 453 af = AF_INET; 454 break; 455 case AF_IPV6: 456 af = AF_INET6; 457 break; 458 default: 459 return ("???"); 460 } 461 462 if (snprintf(buf, sizeof(buf), "%s/%u", 463 log_addr(af, &map->fec.prefix.prefix), 464 map->fec.prefix.prefixlen) == -1) 465 return ("???"); 466 break; 467 case MAP_TYPE_PWID: 468 if (snprintf(buf, sizeof(buf), "pwid %u (%s)", 469 map->fec.pwid.pwid, 470 pw_type_name(map->fec.pwid.type)) == -1) 471 return ("???"); 472 break; 473 default: 474 return ("???"); 475 } 476 477 return (buf); 478 } 479 480 const char * 481 log_fec(const struct fec *fec) 482 { 483 static char buf[64]; 484 union ldpd_addr addr; 485 486 switch (fec->type) { 487 case FEC_TYPE_IPV4: 488 addr.v4 = fec->u.ipv4.prefix; 489 if (snprintf(buf, sizeof(buf), "ipv4 %s/%u", 490 log_addr(AF_INET, &addr), fec->u.ipv4.prefixlen) == -1) 491 return ("???"); 492 break; 493 case FEC_TYPE_IPV6: 494 addr.v6 = fec->u.ipv6.prefix; 495 if (snprintf(buf, sizeof(buf), "ipv6 %s/%u", 496 log_addr(AF_INET6, &addr), fec->u.ipv6.prefixlen) == -1) 497 return ("???"); 498 break; 499 case FEC_TYPE_PWID: 500 if (snprintf(buf, sizeof(buf), 501 "pwid %u (%s) - %s", 502 fec->u.pwid.pwid, pw_type_name(fec->u.pwid.type), 503 inet_ntoa(fec->u.pwid.lsr_id)) == -1) 504 return ("???"); 505 break; 506 default: 507 return ("???"); 508 } 509 510 return (buf); 511 } 512 513 static char *msgtypes[] = { 514 "", 515 "RTM_ADD: Add Route", 516 "RTM_DELETE: Delete Route", 517 "RTM_CHANGE: Change Metrics or flags", 518 "RTM_GET: Report Metrics", 519 "RTM_LOSING: Kernel Suspects Partitioning", 520 "RTM_REDIRECT: Told to use different route", 521 "RTM_MISS: Lookup failed on this address", 522 "RTM_LOCK: fix specified metrics", 523 "RTM_OLDADD: caused by SIOCADDRT", 524 "RTM_OLDDEL: caused by SIOCDELRT", 525 "RTM_RESOLVE: Route created by cloning", 526 "RTM_NEWADDR: address being added to iface", 527 "RTM_DELADDR: address being removed from iface", 528 "RTM_IFINFO: iface status change", 529 "RTM_IFANNOUNCE: iface arrival/departure", 530 "RTM_DESYNC: route socket overflow", 531 }; 532 533 void 534 log_rtmsg(unsigned char rtm_type) 535 { 536 if (!(verbose & LDPD_OPT_VERBOSE2)) 537 return; 538 539 if (rtm_type > 0 && 540 rtm_type < sizeof(msgtypes)/sizeof(msgtypes[0])) 541 log_debug("kernel message: %s", msgtypes[rtm_type]); 542 else 543 log_debug("kernel message: rtm_type %d out of range", 544 rtm_type); 545 } 546