xref: /openbsd/usr.sbin/ldpd/log.c (revision 60e1e0e7)
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