]> git.proxmox.com Git - mirror_frr.git/blob - ldpd/log.c
ldpd: copy original sources from OpenBSD (14/09/2016)
[mirror_frr.git] / ldpd / log.c
1 /* $OpenBSD$ */
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 }