xref: /openbsd/usr.sbin/ldpd/log.c (revision 19fce358)
1 /*	$OpenBSD: log.c,v 1.24 2016/05/23 18:55:21 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 <netinet/in.h>
22 #include <arpa/inet.h>
23 
24 #include <errno.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <syslog.h>
30 #include <unistd.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 int	debug;
44 int	verbose;
45 
46 void
47 log_init(int n_debug)
48 {
49 	extern char	*__progname;
50 
51 	debug = n_debug;
52 
53 	if (!debug)
54 		openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
55 
56 	tzset();
57 }
58 
59 void
60 log_verbose(int v)
61 {
62 	verbose = v;
63 }
64 
65 void
66 logit(int pri, const char *fmt, ...)
67 {
68 	va_list	ap;
69 
70 	va_start(ap, fmt);
71 	vlog(pri, fmt, ap);
72 	va_end(ap);
73 }
74 
75 void
76 vlog(int pri, const char *fmt, va_list ap)
77 {
78 	char	*nfmt;
79 
80 	if (debug) {
81 		/* best effort in out of mem situations */
82 		if (asprintf(&nfmt, "%s\n", fmt) == -1) {
83 			vfprintf(stderr, fmt, ap);
84 			fprintf(stderr, "\n");
85 		} else {
86 			vfprintf(stderr, nfmt, ap);
87 			free(nfmt);
88 		}
89 		fflush(stderr);
90 	} else
91 		vsyslog(pri, fmt, ap);
92 }
93 
94 void
95 log_warn(const char *emsg, ...)
96 {
97 	char	*nfmt;
98 	va_list	 ap;
99 
100 	/* best effort to even work in out of memory situations */
101 	if (emsg == NULL)
102 		logit(LOG_CRIT, "%s", strerror(errno));
103 	else {
104 		va_start(ap, emsg);
105 
106 		if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) {
107 			/* we tried it... */
108 			vlog(LOG_CRIT, emsg, ap);
109 			logit(LOG_CRIT, "%s", strerror(errno));
110 		} else {
111 			vlog(LOG_CRIT, nfmt, ap);
112 			free(nfmt);
113 		}
114 		va_end(ap);
115 	}
116 }
117 
118 void
119 log_warnx(const char *emsg, ...)
120 {
121 	va_list	 ap;
122 
123 	va_start(ap, emsg);
124 	vlog(LOG_CRIT, emsg, ap);
125 	va_end(ap);
126 }
127 
128 void
129 log_info(const char *emsg, ...)
130 {
131 	va_list	 ap;
132 
133 	va_start(ap, emsg);
134 	vlog(LOG_INFO, emsg, ap);
135 	va_end(ap);
136 }
137 
138 void
139 log_debug(const char *emsg, ...)
140 {
141 	va_list	 ap;
142 
143 	if (verbose & LDPD_OPT_VERBOSE) {
144 		va_start(ap, emsg);
145 		vlog(LOG_DEBUG, emsg, ap);
146 		va_end(ap);
147 	}
148 }
149 
150 void
151 fatal(const char *emsg)
152 {
153 	if (emsg == NULL)
154 		logit(LOG_CRIT, "fatal in %s: %s", procnames[ldpd_process],
155 		    strerror(errno));
156 	else
157 		if (errno)
158 			logit(LOG_CRIT, "fatal in %s: %s: %s",
159 			    procnames[ldpd_process], emsg, strerror(errno));
160 		else
161 			logit(LOG_CRIT, "fatal in %s: %s",
162 			    procnames[ldpd_process], emsg);
163 
164 	if (ldpd_process == PROC_MAIN)
165 		exit(1);
166 	else				/* parent copes via SIGCHLD */
167 		_exit(1);
168 }
169 
170 void
171 fatalx(const char *emsg)
172 {
173 	errno = 0;
174 	fatal(emsg);
175 }
176 
177 /* names */
178 const char *
179 socket_name(int type)
180 {
181 	switch (type) {
182 	case LDP_SOCKET_DISC:
183 		return ("discovery");
184 	case LDP_SOCKET_EDISC:
185 		return ("extended discovery");
186 	case LDP_SOCKET_SESSION:
187 		return ("session");
188 	default:
189 		return ("UNKNOWN");
190 	}
191 }
192 
193 const char *
194 nbr_state_name(int state)
195 {
196 	switch (state) {
197 	case NBR_STA_PRESENT:
198 		return ("PRESENT");
199 	case NBR_STA_INITIAL:
200 		return ("INITIALIZED");
201 	case NBR_STA_OPENREC:
202 		return ("OPENREC");
203 	case NBR_STA_OPENSENT:
204 		return ("OPENSENT");
205 	case NBR_STA_OPER:
206 		return ("OPERATIONAL");
207 	default:
208 		return ("UNKNOWN");
209 	}
210 }
211 
212 const char *
213 if_state_name(int state)
214 {
215 	switch (state) {
216 	case IF_STA_DOWN:
217 		return ("DOWN");
218 	case IF_STA_ACTIVE:
219 		return ("ACTIVE");
220 	default:
221 		return ("UNKNOWN");
222 	}
223 }
224 
225 const char *
226 if_type_name(enum iface_type type)
227 {
228 	switch (type) {
229 	case IF_TYPE_POINTOPOINT:
230 		return ("POINTOPOINT");
231 	case IF_TYPE_BROADCAST:
232 		return ("BROADCAST");
233 	}
234 	/* NOTREACHED */
235 	return ("UNKNOWN");
236 }
237 
238 const char *
239 notification_name(uint32_t status)
240 {
241 	static char buf[16];
242 
243 	switch (status) {
244 	case S_SUCCESS:
245 		return ("Success");
246 	case S_BAD_LDP_ID:
247 		return ("Bad LDP Identifier");
248 	case S_BAD_PROTO_VER:
249 		return ("Bad Protocol Version");
250 	case S_BAD_PDU_LEN:
251 		return ("Bad PDU Length");
252 	case S_UNKNOWN_MSG:
253 		return ("Unknown Message Type");
254 	case S_BAD_MSG_LEN:
255 		return ("Bad Message Length");
256 	case S_UNKNOWN_TLV:
257 		return ("Unknown TLV");
258 	case S_BAD_TLV_LEN:
259 		return ("Bad TLV Length");
260 	case S_BAD_TLV_VAL:
261 		return ("Malformed TLV Value");
262 	case S_HOLDTIME_EXP:
263 		return ("Hold Timer Expired");
264 	case S_SHUTDOWN:
265 		return ("Shutdown");
266 	case S_LOOP_DETECTED:
267 		return ("Loop Detected");
268 	case S_UNKNOWN_FEC:
269 		return ("Unknown FEC");
270 	case S_NO_ROUTE:
271 		return ("No Route");
272 	case S_NO_LABEL_RES:
273 		return ("No Label Resources");
274 	case S_AVAILABLE:
275 		return ("Label Resources Available");
276 	case S_NO_HELLO:
277 		return ("Session Rejected, No Hello");
278 	case S_PARM_ADV_MODE:
279 		return ("Rejected Advertisement Mode Parameter");
280 	case S_MAX_PDU_LEN:
281 		return ("Rejected Max PDU Length Parameter");
282 	case S_PARM_L_RANGE:
283 		return ("Rejected Label Range Parameter");
284 	case S_KEEPALIVE_TMR:
285 		return ("KeepAlive Timer Expired");
286 	case S_LAB_REQ_ABRT:
287 		return ("Label Request Aborted");
288 	case S_MISS_MSG:
289 		return ("Missing Message Parameters");
290 	case S_UNSUP_ADDR:
291 		return ("Unsupported Address Family");
292 	case S_KEEPALIVE_BAD:
293 		return ("Bad KeepAlive Time");
294 	case S_INTERN_ERR:
295 		return ("Internal Error");
296 	case S_ILLEGAL_CBIT:
297 		return ("Illegal C-Bit");
298 	case S_WRONG_CBIT:
299 		return ("Wrong C-Bit");
300 	case S_INCPT_BITRATE:
301 		return ("Incompatible bit-rate");
302 	case S_CEP_MISCONF:
303 		return ("CEP-TDM mis-configuration");
304 	case S_PW_STATUS:
305 		return ("PW Status");
306 	case S_UNASSIGN_TAI:
307 		return ("Unassigned/Unrecognized TAI");
308 	case S_MISCONF_ERR:
309 		return ("Generic Misconfiguration Error");
310 	case S_WITHDRAW_MTHD:
311 		return ("Label Withdraw PW Status Method");
312 	default:
313 		snprintf(buf, sizeof(buf), "[%08x]", status);
314 		return (buf);
315 	}
316 }
317 
318 const char *
319 pw_type_name(uint16_t pw_type)
320 {
321 	static char buf[64];
322 
323 	switch (pw_type) {
324 	case PW_TYPE_ETHERNET_TAGGED:
325 		return ("Eth Tagged");
326 	case PW_TYPE_ETHERNET:
327 		return ("Ethernet");
328 	default:
329 		snprintf(buf, sizeof(buf), "[%0x]", pw_type);
330 		return (buf);
331 	}
332 }
333 
334 char *
335 log_hello_src(const struct hello_source *src)
336 {
337 	static char buffer[64];
338 
339 	switch (src->type) {
340 	case HELLO_LINK:
341 		snprintf(buffer, sizeof(buffer), "iface %s",
342 		    src->link.iface->name);
343 		break;
344 	case HELLO_TARGETED:
345 		snprintf(buffer, sizeof(buffer), "source %s",
346 		    inet_ntoa(src->target->addr));
347 		break;
348 	}
349 
350 	return (buffer);
351 }
352 
353 const char *
354 log_map(const struct map *map)
355 {
356 	static char	buf[64];
357 	char		pstr[64];
358 
359 	switch (map->type) {
360 	case MAP_TYPE_WILDCARD:
361 		if (snprintf(buf, sizeof(buf), "wildcard") < 0)
362 			return ("???");
363 		break;
364 	case MAP_TYPE_PREFIX:
365 		if (snprintf(buf, sizeof(buf), "%s/%u",
366 		    inet_ntop(AF_INET, &map->fec.ipv4.prefix, pstr,
367 		    sizeof(pstr)), map->fec.ipv4.prefixlen) == -1)
368 			return ("???");
369 		break;
370 	case MAP_TYPE_PWID:
371 		if (snprintf(buf, sizeof(buf), "pwid %u (%s)",
372 		    map->fec.pwid.pwid,
373 		    pw_type_name(map->fec.pwid.type)) == -1)
374 			return ("???");
375 		break;
376 	default:
377 		return ("???");
378 	}
379 
380 	return (buf);
381 }
382 
383 const char *
384 log_fec(const struct fec *fec)
385 {
386 	static char	buf[64];
387 	char		pstr[32];
388 
389 	switch (fec->type) {
390 	case FEC_TYPE_IPV4:
391 		if (snprintf(buf, sizeof(buf), "%s/%u",
392 		    inet_ntop(AF_INET, &fec->u.ipv4.prefix, pstr,
393 		    sizeof(pstr)), fec->u.ipv4.prefixlen) == -1)
394 			return ("???");
395 		break;
396 	case FEC_TYPE_PWID:
397 		if (snprintf(buf, sizeof(buf),
398 		    "pwid %u (%s) - %s",
399 		    fec->u.pwid.pwid, pw_type_name(fec->u.pwid.type),
400 		    inet_ntoa(fec->u.pwid.lsr_id)) == -1)
401 			return ("???");
402 		break;
403 	default:
404 		return ("???");
405 	}
406 
407 	return (buf);
408 }
409 
410 static char *msgtypes[] = {
411 	"",
412 	"RTM_ADD: Add Route",
413 	"RTM_DELETE: Delete Route",
414 	"RTM_CHANGE: Change Metrics or flags",
415 	"RTM_GET: Report Metrics",
416 	"RTM_LOSING: Kernel Suspects Partitioning",
417 	"RTM_REDIRECT: Told to use different route",
418 	"RTM_MISS: Lookup failed on this address",
419 	"RTM_LOCK: fix specified metrics",
420 	"RTM_OLDADD: caused by SIOCADDRT",
421 	"RTM_OLDDEL: caused by SIOCDELRT",
422 	"RTM_RESOLVE: Route created by cloning",
423 	"RTM_NEWADDR: address being added to iface",
424 	"RTM_DELADDR: address being removed from iface",
425 	"RTM_IFINFO: iface status change",
426 	"RTM_IFANNOUNCE: iface arrival/departure",
427 	"RTM_DESYNC: route socket overflow",
428 };
429 
430 void
431 log_rtmsg(unsigned char rtm_type)
432 {
433 	if (!(verbose & LDPD_OPT_VERBOSE2))
434 		return;
435 
436 	if (rtm_type > 0 &&
437 	    rtm_type < sizeof(msgtypes)/sizeof(msgtypes[0]))
438 		log_debug("kernel message: %s", msgtypes[rtm_type]);
439 	else
440 		log_debug("kernel message: rtm_type %d out of range",
441 		    rtm_type);
442 }
443