xref: /openbsd-src/usr.sbin/ospf6d/log.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: log.c,v 1.4 2009/03/29 19:07:56 stsp 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 
45 void	 logit(int, const char *, ...);
46 
47 void
48 log_init(int n_debug)
49 {
50 	extern char	*__progname;
51 
52 	debug = n_debug;
53 
54 	if (!debug)
55 		openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
56 
57 	tzset();
58 }
59 
60 void
61 logit(int pri, const char *fmt, ...)
62 {
63 	va_list	ap;
64 
65 	va_start(ap, fmt);
66 	vlog(pri, fmt, ap);
67 	va_end(ap);
68 }
69 
70 void
71 vlog(int pri, const char *fmt, va_list ap)
72 {
73 	char	*nfmt;
74 
75 	if (debug) {
76 		/* best effort in out of mem situations */
77 		if (asprintf(&nfmt, "%s\n", fmt) == -1) {
78 			vfprintf(stderr, fmt, ap);
79 			fprintf(stderr, "\n");
80 		} else {
81 			vfprintf(stderr, nfmt, ap);
82 			free(nfmt);
83 		}
84 		fflush(stderr);
85 	} else
86 		vsyslog(pri, fmt, ap);
87 }
88 
89 void
90 log_warn(const char *emsg, ...)
91 {
92 	char	*nfmt;
93 	va_list	 ap;
94 
95 	/* best effort to even work in out of memory situations */
96 	if (emsg == NULL)
97 		logit(LOG_CRIT, "%s", strerror(errno));
98 	else {
99 		va_start(ap, emsg);
100 
101 		if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) {
102 			/* we tried it... */
103 			vlog(LOG_CRIT, emsg, ap);
104 			logit(LOG_CRIT, "%s", strerror(errno));
105 		} else {
106 			vlog(LOG_CRIT, nfmt, ap);
107 			free(nfmt);
108 		}
109 		va_end(ap);
110 	}
111 }
112 
113 void
114 log_warnx(const char *emsg, ...)
115 {
116 	va_list	 ap;
117 
118 	va_start(ap, emsg);
119 	vlog(LOG_CRIT, emsg, ap);
120 	va_end(ap);
121 }
122 
123 void
124 log_info(const char *emsg, ...)
125 {
126 	va_list	 ap;
127 
128 	va_start(ap, emsg);
129 	vlog(LOG_INFO, emsg, ap);
130 	va_end(ap);
131 }
132 
133 void
134 log_debug(const char *emsg, ...)
135 {
136 	va_list	 ap;
137 
138 	if (debug) {
139 		va_start(ap, emsg);
140 		vlog(LOG_DEBUG, emsg, ap);
141 		va_end(ap);
142 	}
143 }
144 
145 void
146 fatal(const char *emsg)
147 {
148 	if (emsg == NULL)
149 		logit(LOG_CRIT, "fatal in %s: %s", procnames[ospfd_process],
150 		    strerror(errno));
151 	else
152 		if (errno)
153 			logit(LOG_CRIT, "fatal in %s: %s: %s",
154 			    procnames[ospfd_process], emsg, strerror(errno));
155 		else
156 			logit(LOG_CRIT, "fatal in %s: %s",
157 			    procnames[ospfd_process], emsg);
158 
159 	if (ospfd_process == PROC_MAIN)
160 		exit(1);
161 	else				/* parent copes via SIGCHLD */
162 		_exit(1);
163 }
164 
165 void
166 fatalx(const char *emsg)
167 {
168 	errno = 0;
169 	fatal(emsg);
170 }
171 
172 const char *
173 log_in6addr(const struct in6_addr *addr)
174 {
175 	struct sockaddr_in6	sa_in6;
176 	u_int16_t		tmp16;
177 
178 	bzero(&sa_in6, sizeof(sa_in6));
179 	sa_in6.sin6_len = sizeof(sa_in6);
180 	sa_in6.sin6_family = AF_INET6;
181 	memcpy(&sa_in6.sin6_addr, addr, sizeof(sa_in6.sin6_addr));
182 
183 	/* XXX thanks, KAME, for this ugliness... adopted from route/show.c */
184 	if (IN6_IS_ADDR_LINKLOCAL(&sa_in6.sin6_addr) ||
185 	    IN6_IS_ADDR_MC_LINKLOCAL(&sa_in6.sin6_addr)) {
186 		memcpy(&tmp16, &sa_in6.sin6_addr.s6_addr[2], sizeof(tmp16));
187 		sa_in6.sin6_scope_id = ntohs(tmp16);
188 		sa_in6.sin6_addr.s6_addr[2] = 0;
189 		sa_in6.sin6_addr.s6_addr[3] = 0;
190 	}
191 
192 	return (log_sockaddr(&sa_in6));
193 }
194 
195 #define NUM_LOGS	4
196 const char *
197 log_rtr_id(u_int32_t id)
198 {
199 	static char	buf[NUM_LOGS][16];
200 	static int	round = 0;
201 	struct in_addr	addr;
202 
203 	round = (round + 1) % NUM_LOGS;
204 
205 	addr.s_addr = id;
206 	if (inet_ntop(AF_INET, &addr, buf[round], 16) == NULL)
207 		return ("?");
208 	else
209 		return buf[round];
210 }
211 
212 const char *
213 log_sockaddr(void *vp)
214 {
215 	static char	buf[NUM_LOGS][NI_MAXHOST];
216 	static int	round = 0;
217 	struct sockaddr	*sa = vp;
218 
219 	round = (round + 1) % NUM_LOGS;
220 
221 	if (getnameinfo(sa, sa->sa_len, buf[round], NI_MAXHOST, NULL, 0,
222 	    NI_NUMERICHOST))
223 		return ("(unknown)");
224 	else
225 		return (buf[round]);
226 }
227 
228 /* names */
229 const char *
230 nbr_state_name(int state)
231 {
232 	switch (state) {
233 	case NBR_STA_DOWN:
234 		return ("DOWN");
235 	case NBR_STA_ATTEMPT:
236 		return ("ATTMP");
237 	case NBR_STA_INIT:
238 		return ("INIT");
239 	case NBR_STA_2_WAY:
240 		return ("2-WAY");
241 	case NBR_STA_XSTRT:
242 		return ("EXSTA");
243 	case NBR_STA_SNAP:
244 		return ("SNAP");
245 	case NBR_STA_XCHNG:
246 		return ("EXCHG");
247 	case NBR_STA_LOAD:
248 		return ("LOAD");
249 	case NBR_STA_FULL:
250 		return ("FULL");
251 	default:
252 		return ("UNKNW");
253 	}
254 }
255 
256 const char *
257 if_state_name(int state)
258 {
259 	switch (state) {
260 	case IF_STA_DOWN:
261 		return ("DOWN");
262 	case IF_STA_LOOPBACK:
263 		return ("LOOP");
264 	case IF_STA_WAITING:
265 		return ("WAIT");
266 	case IF_STA_POINTTOPOINT:
267 		return ("P2P");
268 	case IF_STA_DROTHER:
269 		return ("OTHER");
270 	case IF_STA_BACKUP:
271 		return ("BCKUP");
272 	case IF_STA_DR:
273 		return ("DR");
274 	default:
275 		return ("UNKNW");
276 	}
277 }
278 
279 const char *
280 if_type_name(enum iface_type type)
281 {
282 	switch (type) {
283 	case IF_TYPE_POINTOPOINT:
284 		return ("POINTOPOINT");
285 	case IF_TYPE_BROADCAST:
286 		return ("BROADCAST");
287 	case IF_TYPE_NBMA:
288 		return ("NBMA");
289 	case IF_TYPE_POINTOMULTIPOINT:
290 		return ("POINTOMULTIPOINT");
291 	case IF_TYPE_VIRTUALLINK:
292 		return ("VIRTUALLINK");
293 	}
294 	/* NOTREACHED */
295 	return ("UNKNOWN");
296 }
297 
298 const char *
299 dst_type_name(enum dst_type type)
300 {
301 	switch (type) {
302 	case DT_NET:
303 		return ("Network");
304 	case DT_RTR:
305 		return ("Router");
306 	}
307 	/* NOTREACHED */
308 	return ("unknown");
309 }
310 
311 const char *
312 path_type_name(enum path_type type)
313 {
314 	switch (type) {
315 	case PT_INTRA_AREA:
316 		return ("Intra-Area");
317 	case PT_INTER_AREA:
318 		return ("Inter-Area");
319 	case PT_TYPE1_EXT:
320 		return ("Type 1 ext");
321 	case PT_TYPE2_EXT:
322 		return ("Type 2 ext");
323 	}
324 	/* NOTREACHED */
325 	return ("unknown");
326 }
327