xref: /openbsd/usr.sbin/ospf6d/log.c (revision 17df1aa7)
1 /*	$OpenBSD: log.c,v 1.6 2009/12/22 17:45:47 claudio Exp $ */
2 
3 /*
4  * Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
5  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
24 
25 #include <netdb.h>
26 #include <errno.h>
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <syslog.h>
32 #include <unistd.h>
33 
34 #include "ospf6d.h"
35 #include "log.h"
36 
37 static const char * const procnames[] = {
38 	"parent",
39 	"ospfe",
40 	"rde"
41 };
42 
43 int	debug;
44 int	verbose;
45 
46 void	 logit(int, const char *, ...);
47 
48 void
49 log_init(int n_debug)
50 {
51 	extern char	*__progname;
52 
53 	debug = n_debug;
54 	verbose = n_debug;
55 
56 	if (!debug)
57 		openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
58 
59 	tzset();
60 }
61 
62 void
63 log_verbose(int v)
64 {
65 	verbose = v;
66 }
67 
68 void
69 logit(int pri, const char *fmt, ...)
70 {
71 	va_list	ap;
72 
73 	va_start(ap, fmt);
74 	vlog(pri, fmt, ap);
75 	va_end(ap);
76 }
77 
78 void
79 vlog(int pri, const char *fmt, va_list ap)
80 {
81 	char	*nfmt;
82 
83 	if (debug) {
84 		/* best effort in out of mem situations */
85 		if (asprintf(&nfmt, "%s\n", fmt) == -1) {
86 			vfprintf(stderr, fmt, ap);
87 			fprintf(stderr, "\n");
88 		} else {
89 			vfprintf(stderr, nfmt, ap);
90 			free(nfmt);
91 		}
92 		fflush(stderr);
93 	} else
94 		vsyslog(pri, fmt, ap);
95 }
96 
97 void
98 log_warn(const char *emsg, ...)
99 {
100 	char	*nfmt;
101 	va_list	 ap;
102 
103 	/* best effort to even work in out of memory situations */
104 	if (emsg == NULL)
105 		logit(LOG_CRIT, "%s", strerror(errno));
106 	else {
107 		va_start(ap, emsg);
108 
109 		if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) {
110 			/* we tried it... */
111 			vlog(LOG_CRIT, emsg, ap);
112 			logit(LOG_CRIT, "%s", strerror(errno));
113 		} else {
114 			vlog(LOG_CRIT, nfmt, ap);
115 			free(nfmt);
116 		}
117 		va_end(ap);
118 	}
119 }
120 
121 void
122 log_warnx(const char *emsg, ...)
123 {
124 	va_list	 ap;
125 
126 	va_start(ap, emsg);
127 	vlog(LOG_CRIT, emsg, ap);
128 	va_end(ap);
129 }
130 
131 void
132 log_info(const char *emsg, ...)
133 {
134 	va_list	 ap;
135 
136 	va_start(ap, emsg);
137 	vlog(LOG_INFO, emsg, ap);
138 	va_end(ap);
139 }
140 
141 void
142 log_debug(const char *emsg, ...)
143 {
144 	va_list	 ap;
145 
146 	if (verbose) {
147 		va_start(ap, emsg);
148 		vlog(LOG_DEBUG, emsg, ap);
149 		va_end(ap);
150 	}
151 }
152 
153 void
154 fatal(const char *emsg)
155 {
156 	if (emsg == NULL)
157 		logit(LOG_CRIT, "fatal in %s: %s", procnames[ospfd_process],
158 		    strerror(errno));
159 	else
160 		if (errno)
161 			logit(LOG_CRIT, "fatal in %s: %s: %s",
162 			    procnames[ospfd_process], emsg, strerror(errno));
163 		else
164 			logit(LOG_CRIT, "fatal in %s: %s",
165 			    procnames[ospfd_process], emsg);
166 
167 	if (ospfd_process == PROC_MAIN)
168 		exit(1);
169 	else				/* parent copes via SIGCHLD */
170 		_exit(1);
171 }
172 
173 void
174 fatalx(const char *emsg)
175 {
176 	errno = 0;
177 	fatal(emsg);
178 }
179 
180 const char *
181 log_in6addr(const struct in6_addr *addr)
182 {
183 	struct sockaddr_in6	sa_in6;
184 	u_int16_t		tmp16;
185 
186 	bzero(&sa_in6, sizeof(sa_in6));
187 	sa_in6.sin6_len = sizeof(sa_in6);
188 	sa_in6.sin6_family = AF_INET6;
189 	memcpy(&sa_in6.sin6_addr, addr, sizeof(sa_in6.sin6_addr));
190 
191 	/* XXX thanks, KAME, for this ugliness... adopted from route/show.c */
192 	if (IN6_IS_ADDR_LINKLOCAL(&sa_in6.sin6_addr) ||
193 	    IN6_IS_ADDR_MC_LINKLOCAL(&sa_in6.sin6_addr)) {
194 		memcpy(&tmp16, &sa_in6.sin6_addr.s6_addr[2], sizeof(tmp16));
195 		sa_in6.sin6_scope_id = ntohs(tmp16);
196 		sa_in6.sin6_addr.s6_addr[2] = 0;
197 		sa_in6.sin6_addr.s6_addr[3] = 0;
198 	}
199 
200 	return (log_sockaddr(&sa_in6));
201 }
202 
203 const char *
204 log_in6addr_scope(const struct in6_addr *addr, unsigned int ifindex)
205 {
206 	struct sockaddr_in6	sa_in6;
207 
208 	bzero(&sa_in6, sizeof(sa_in6));
209 	sa_in6.sin6_len = sizeof(sa_in6);
210 	sa_in6.sin6_family = AF_INET6;
211 	memcpy(&sa_in6.sin6_addr, addr, sizeof(sa_in6.sin6_addr));
212 
213 	/* XXX thanks, IPv6 & KAME, for this ugliness... */
214 	if (IN6_IS_ADDR_LINKLOCAL(&sa_in6.sin6_addr) ||
215 	    IN6_IS_ADDR_MC_LINKLOCAL(&sa_in6.sin6_addr)) {
216 		sa_in6.sin6_scope_id = ifindex;
217 	}
218 
219 	return (log_sockaddr(&sa_in6));
220 }
221 
222 #define NUM_LOGS	4
223 const char *
224 log_rtr_id(u_int32_t id)
225 {
226 	static char	buf[NUM_LOGS][16];
227 	static int	round = 0;
228 	struct in_addr	addr;
229 
230 	round = (round + 1) % NUM_LOGS;
231 
232 	addr.s_addr = id;
233 	if (inet_ntop(AF_INET, &addr, buf[round], 16) == NULL)
234 		return ("?");
235 	else
236 		return buf[round];
237 }
238 
239 const char *
240 log_sockaddr(void *vp)
241 {
242 	static char	buf[NUM_LOGS][NI_MAXHOST];
243 	static int	round = 0;
244 	struct sockaddr	*sa = vp;
245 
246 	round = (round + 1) % NUM_LOGS;
247 
248 	if (getnameinfo(sa, sa->sa_len, buf[round], NI_MAXHOST, NULL, 0,
249 	    NI_NUMERICHOST))
250 		return ("(unknown)");
251 	else
252 		return (buf[round]);
253 }
254 
255 /* names */
256 const char *
257 nbr_state_name(int state)
258 {
259 	switch (state) {
260 	case NBR_STA_DOWN:
261 		return ("DOWN");
262 	case NBR_STA_ATTEMPT:
263 		return ("ATTMP");
264 	case NBR_STA_INIT:
265 		return ("INIT");
266 	case NBR_STA_2_WAY:
267 		return ("2-WAY");
268 	case NBR_STA_XSTRT:
269 		return ("EXSTA");
270 	case NBR_STA_SNAP:
271 		return ("SNAP");
272 	case NBR_STA_XCHNG:
273 		return ("EXCHG");
274 	case NBR_STA_LOAD:
275 		return ("LOAD");
276 	case NBR_STA_FULL:
277 		return ("FULL");
278 	default:
279 		return ("UNKNW");
280 	}
281 }
282 
283 const char *
284 if_state_name(int state)
285 {
286 	switch (state) {
287 	case IF_STA_DOWN:
288 		return ("DOWN");
289 	case IF_STA_LOOPBACK:
290 		return ("LOOP");
291 	case IF_STA_WAITING:
292 		return ("WAIT");
293 	case IF_STA_POINTTOPOINT:
294 		return ("P2P");
295 	case IF_STA_DROTHER:
296 		return ("OTHER");
297 	case IF_STA_BACKUP:
298 		return ("BCKUP");
299 	case IF_STA_DR:
300 		return ("DR");
301 	default:
302 		return ("UNKNW");
303 	}
304 }
305 
306 const char *
307 if_type_name(enum iface_type type)
308 {
309 	switch (type) {
310 	case IF_TYPE_POINTOPOINT:
311 		return ("POINTOPOINT");
312 	case IF_TYPE_BROADCAST:
313 		return ("BROADCAST");
314 	case IF_TYPE_NBMA:
315 		return ("NBMA");
316 	case IF_TYPE_POINTOMULTIPOINT:
317 		return ("POINTOMULTIPOINT");
318 	case IF_TYPE_VIRTUALLINK:
319 		return ("VIRTUALLINK");
320 	}
321 	/* NOTREACHED */
322 	return ("UNKNOWN");
323 }
324 
325 const char *
326 dst_type_name(enum dst_type type)
327 {
328 	switch (type) {
329 	case DT_NET:
330 		return ("Network");
331 	case DT_RTR:
332 		return ("Router");
333 	}
334 	/* NOTREACHED */
335 	return ("unknown");
336 }
337 
338 const char *
339 path_type_name(enum path_type type)
340 {
341 	switch (type) {
342 	case PT_INTRA_AREA:
343 		return ("Intra-Area");
344 	case PT_INTER_AREA:
345 		return ("Inter-Area");
346 	case PT_TYPE1_EXT:
347 		return ("Type 1 ext");
348 	case PT_TYPE2_EXT:
349 		return ("Type 2 ext");
350 	}
351 	/* NOTREACHED */
352 	return ("unknown");
353 }
354