GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/bgpd/log.c Lines: 0 126 0.0 %
Date: 2016-12-06 Branches: 0 85 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: log.c,v 1.59 2015/07/18 22:52:39 benno 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 <err.h>
20
#include <errno.h>
21
#include <netdb.h>
22
#include <stdarg.h>
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26
#include <syslog.h>
27
#include <time.h>
28
#include <unistd.h>
29
30
#include "bgpd.h"
31
#include "session.h"
32
#include "log.h"
33
34
int	debug;
35
int	verbose;
36
37
char *
38
log_fmt_peer(const struct peer_config *peer)
39
{
40
	const char	*ip;
41
	char		*pfmt, *p;
42
43
	ip = log_addr(&peer->remote_addr);
44
	if ((peer->remote_addr.aid == AID_INET && peer->remote_masklen != 32) ||
45
	    (peer->remote_addr.aid == AID_INET6 &&
46
	    peer->remote_masklen != 128)) {
47
		if (asprintf(&p, "%s/%u", ip, peer->remote_masklen) == -1)
48
			fatal(NULL);
49
	} else {
50
		if ((p = strdup(ip)) == NULL)
51
			fatal(NULL);
52
	}
53
54
	if (peer->descr[0]) {
55
		if (asprintf(&pfmt, "neighbor %s (%s)", p, peer->descr) ==
56
		    -1)
57
			fatal(NULL);
58
	} else {
59
		if (asprintf(&pfmt, "neighbor %s", p) == -1)
60
			fatal(NULL);
61
	}
62
	free(p);
63
	return (pfmt);
64
}
65
66
void
67
log_init(int n_debug)
68
{
69
	extern char	*__progname;
70
71
	debug = n_debug;
72
73
	if (!debug)
74
		openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
75
76
	tzset();
77
}
78
79
void
80
log_verbose(int v)
81
{
82
	verbose = v;
83
}
84
85
void
86
logit(int pri, const char *fmt, ...)
87
{
88
	va_list	ap;
89
90
	va_start(ap, fmt);
91
	vlog(pri, fmt, ap);
92
	va_end(ap);
93
}
94
95
void
96
vlog(int pri, const char *fmt, va_list ap)
97
{
98
	char	*nfmt;
99
100
	if (debug) {
101
		/* best effort in out of mem situations */
102
		if (asprintf(&nfmt, "%s\n", fmt) == -1) {
103
			vfprintf(stderr, fmt, ap);
104
			fprintf(stderr, "\n");
105
		} else {
106
			vfprintf(stderr, nfmt, ap);
107
			free(nfmt);
108
		}
109
		fflush(stderr);
110
	} else
111
		vsyslog(pri, fmt, ap);
112
}
113
114
115
void
116
log_peer_warn(const struct peer_config *peer, const char *emsg, ...)
117
{
118
	char	*p, *nfmt;
119
	va_list	 ap;
120
121
	p = log_fmt_peer(peer);
122
	if (emsg == NULL) {
123
		if (asprintf(&nfmt, "%s: %s", p, strerror(errno)) == -1)
124
			fatal(NULL);
125
	} else {
126
		if (asprintf(&nfmt, "%s: %s: %s", p, emsg, strerror(errno)) ==
127
		    -1)
128
			fatal(NULL);
129
	}
130
	va_start(ap, emsg);
131
	vlog(LOG_CRIT, nfmt, ap);
132
	va_end(ap);
133
	free(p);
134
	free(nfmt);
135
}
136
137
void
138
log_peer_warnx(const struct peer_config *peer, const char *emsg, ...)
139
{
140
	char	*p, *nfmt;
141
	va_list	 ap;
142
143
	p = log_fmt_peer(peer);
144
	if (asprintf(&nfmt, "%s: %s", p, emsg) == -1)
145
		fatal(NULL);
146
	va_start(ap, emsg);
147
	vlog(LOG_CRIT, nfmt, ap);
148
	va_end(ap);
149
	free(p);
150
	free(nfmt);
151
}
152
153
void
154
log_warn(const char *emsg, ...)
155
{
156
	char	*nfmt;
157
	va_list	 ap;
158
159
	/* best effort to even work in out of memory situations */
160
	if (emsg == NULL)
161
		logit(LOG_CRIT, "%s", strerror(errno));
162
	else {
163
		va_start(ap, emsg);
164
165
		if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) {
166
			/* we tried it... */
167
			vlog(LOG_CRIT, emsg, ap);
168
			logit(LOG_CRIT, "%s", strerror(errno));
169
		} else {
170
			vlog(LOG_CRIT, nfmt, ap);
171
			free(nfmt);
172
		}
173
		va_end(ap);
174
	}
175
}
176
177
void
178
log_warnx(const char *emsg, ...)
179
{
180
	va_list	 ap;
181
182
	va_start(ap, emsg);
183
	vlog(LOG_CRIT, emsg, ap);
184
	va_end(ap);
185
}
186
187
void
188
log_info(const char *emsg, ...)
189
{
190
	va_list	 ap;
191
192
	va_start(ap, emsg);
193
	vlog(LOG_INFO, emsg, ap);
194
	va_end(ap);
195
}
196
197
void
198
log_debug(const char *emsg, ...)
199
{
200
	va_list	 ap;
201
202
	if (verbose) {
203
		va_start(ap, emsg);
204
		vlog(LOG_DEBUG, emsg, ap);
205
		va_end(ap);
206
	}
207
}
208
209
void
210
fatal(const char *emsg, ...)
211
{
212
	char	 s[1024];
213
	va_list  ap;
214
215
	va_start(ap, emsg);
216
	vsnprintf(s, sizeof(s), emsg, ap);
217
	va_end(ap);
218
219
	if (emsg == NULL)
220
		logit(LOG_CRIT, "fatal in %s: %s", procnames[bgpd_process],
221
		    strerror(errno));
222
	else
223
		if (errno)
224
			logit(LOG_CRIT, "fatal in %s: %s: %s",
225
			    procnames[bgpd_process], s, strerror(errno));
226
		else
227
			logit(LOG_CRIT, "fatal in %s: %s",
228
			    procnames[bgpd_process], s);
229
230
	if (bgpd_process == PROC_MAIN)
231
		exit(1);
232
	else				/* parent copes via SIGCHLD */
233
		_exit(1);
234
}
235
236
void
237
fatalx(const char *emsg)
238
{
239
	errno = 0;
240
	fatal(emsg);
241
}
242
243
void
244
log_statechange(struct peer *peer, enum session_state nstate,
245
    enum session_events event)
246
{
247
	char	*p;
248
249
	/* don't clutter the logs with constant Connect -> Active -> Connect */
250
	if (nstate == STATE_CONNECT && peer->state == STATE_ACTIVE &&
251
	    peer->prev_state == STATE_CONNECT)
252
		return;
253
	if (nstate == STATE_ACTIVE && peer->state == STATE_CONNECT &&
254
	    peer->prev_state == STATE_ACTIVE)
255
		return;
256
257
	peer->lasterr = 0;
258
	p = log_fmt_peer(&peer->conf);
259
	logit(LOG_INFO, "%s: state change %s -> %s, reason: %s",
260
	    p, statenames[peer->state], statenames[nstate], eventnames[event]);
261
	free(p);
262
}
263
264
void
265
log_notification(const struct peer *peer, u_int8_t errcode, u_int8_t subcode,
266
    u_char *data, u_int16_t datalen, const char *dir)
267
{
268
	char		*p;
269
	const char	*suberrname = NULL;
270
	int		 uk = 0;
271
272
	p = log_fmt_peer(&peer->conf);
273
	switch (errcode) {
274
	case ERR_HEADER:
275
		if (subcode >= sizeof(suberr_header_names)/sizeof(char *))
276
			uk = 1;
277
		else
278
			suberrname = suberr_header_names[subcode];
279
		break;
280
	case ERR_OPEN:
281
		if (subcode >= sizeof(suberr_open_names)/sizeof(char *))
282
			uk = 1;
283
		else
284
			suberrname = suberr_open_names[subcode];
285
		break;
286
	case ERR_UPDATE:
287
		if (subcode >= sizeof(suberr_update_names)/sizeof(char *))
288
			uk = 1;
289
		else
290
			suberrname = suberr_update_names[subcode];
291
		break;
292
	case ERR_CEASE:
293
		if (subcode >= sizeof(suberr_cease_names)/sizeof(char *))
294
			uk = 1;
295
		else
296
			suberrname = suberr_cease_names[subcode];
297
		break;
298
	case ERR_HOLDTIMEREXPIRED:
299
		if (subcode != 0)
300
			uk = 1;
301
		break;
302
	case ERR_FSM:
303
		if (subcode >= sizeof(suberr_fsm_names)/sizeof(char *))
304
			uk = 1;
305
		else
306
			suberrname = suberr_fsm_names[subcode];
307
		break;
308
	default:
309
		logit(LOG_CRIT, "%s: %s notification, unknown errcode "
310
		    "%u, subcode %u", p, dir, errcode, subcode);
311
		free(p);
312
		return;
313
	}
314
315
	if (uk)
316
		logit(LOG_CRIT, "%s: %s notification: %s, unknown subcode %u",
317
		    p, dir, errnames[errcode], subcode);
318
	else {
319
		if (suberrname == NULL)
320
			logit(LOG_CRIT, "%s: %s notification: %s", p,
321
			    dir, errnames[errcode]);
322
		else
323
			logit(LOG_CRIT, "%s: %s notification: %s, %s",
324
			    p, dir, errnames[errcode], suberrname);
325
	}
326
	free(p);
327
}
328
329
void
330
log_conn_attempt(const struct peer *peer, struct sockaddr *sa)
331
{
332
	char		*p;
333
	const char	*b;
334
335
	if (peer == NULL) {	/* connection from non-peer, drop */
336
		b = log_sockaddr(sa);
337
		logit(LOG_INFO, "connection from non-peer %s refused", b);
338
	} else {
339
		/* only log if there is a chance that the session may come up */
340
		if (peer->conf.down && peer->state == STATE_IDLE)
341
			return;
342
		p = log_fmt_peer(&peer->conf);
343
		logit(LOG_INFO, "Connection attempt from %s while session is "
344
		    "in state %s", p, statenames[peer->state]);
345
		free(p);
346
	}
347
}