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