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