GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/bgpctl/bgpctl.c Lines: 0 895 0.0 %
Date: 2016-12-06 Branches: 0 620 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: bgpctl.c,v 1.188 2016/06/03 17:36:37 benno Exp $ */
2
3
/*
4
 * Copyright (c) 2003 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 <sys/un.h>
22
#include <net/if.h>
23
#include <net/if_media.h>
24
#include <net/if_types.h>
25
26
#include <err.h>
27
#include <errno.h>
28
#include <fcntl.h>
29
#include <netdb.h>
30
#include <stdio.h>
31
#include <stdlib.h>
32
#include <string.h>
33
#include <unistd.h>
34
#include <util.h>
35
36
#include "bgpd.h"
37
#include "session.h"
38
#include "rde.h"
39
#include "log.h"
40
#include "parser.h"
41
#include "irrfilter.h"
42
#include "mrtparser.h"
43
44
enum neighbor_views {
45
	NV_DEFAULT,
46
	NV_TIMERS
47
};
48
49
int		 main(int, char *[]);
50
char		*fmt_peer(const char *, const struct bgpd_addr *, int, int);
51
void		 show_summary_head(void);
52
int		 show_summary_msg(struct imsg *, int);
53
int		 show_summary_terse_msg(struct imsg *, int);
54
int		 show_neighbor_terse(struct imsg *);
55
int		 show_neighbor_msg(struct imsg *, enum neighbor_views);
56
void		 print_neighbor_capa_mp(struct peer *);
57
void		 print_neighbor_capa_restart(struct peer *);
58
void		 print_neighbor_msgstats(struct peer *);
59
void		 print_timer(const char *, time_t);
60
static char	*fmt_timeframe(time_t t);
61
static char	*fmt_timeframe_core(time_t t);
62
void		 show_fib_head(void);
63
void		 show_fib_tables_head(void);
64
void		 show_network_head(void);
65
void		 show_fib_flags(u_int16_t);
66
int		 show_fib_msg(struct imsg *);
67
void		 show_nexthop_head(void);
68
int		 show_nexthop_msg(struct imsg *);
69
void		 show_interface_head(void);
70
uint64_t	 ift2ifm(uint8_t);
71
const char *	 get_media_descr(uint64_t);
72
const char *	 get_linkstate(uint8_t, int);
73
const char *	 get_baudrate(u_int64_t, char *);
74
int		 show_interface_msg(struct imsg *);
75
void		 show_rib_summary_head(void);
76
void		 print_prefix(struct bgpd_addr *, u_int8_t, u_int8_t);
77
const char *	 print_origin(u_int8_t, int);
78
void		 print_flags(u_int8_t, int);
79
int		 show_rib_summary_msg(struct imsg *);
80
int		 show_rib_detail_msg(struct imsg *, int);
81
void		 show_rib_brief(struct ctl_show_rib *, u_char *);
82
void		 show_rib_detail(struct ctl_show_rib *, u_char *, int);
83
void		 show_attr(void *, u_int16_t);
84
void		 show_community(u_char *, u_int16_t);
85
void		 show_ext_community(u_char *, u_int16_t);
86
char		*fmt_mem(int64_t);
87
int		 show_rib_memory_msg(struct imsg *);
88
void		 send_filterset(struct imsgbuf *, struct filter_set_head *);
89
const char	*get_errstr(u_int8_t, u_int8_t);
90
int		 show_result(struct imsg *);
91
void		 show_mrt_dump(struct mrt_rib *, struct mrt_peer *, void *);
92
void		 network_mrt_dump(struct mrt_rib *, struct mrt_peer *, void *);
93
void		 show_mrt_state(struct mrt_bgp_state *, void *);
94
void		 show_mrt_msg(struct mrt_bgp_msg *, void *);
95
void		 mrt_to_bgpd_addr(union mrt_addr *, struct bgpd_addr *);
96
const char	*msg_type(u_int8_t);
97
void		 network_bulk(struct parse_result *);
98
const char	*print_auth_method(enum auth_method);
99
100
struct imsgbuf	*ibuf;
101
struct mrt_parser show_mrt = { show_mrt_dump, show_mrt_state, show_mrt_msg };
102
struct mrt_parser net_mrt = { network_mrt_dump, NULL, NULL };
103
104
__dead void
105
usage(void)
106
{
107
	extern char	*__progname;
108
109
	fprintf(stderr, "usage: %s [-n] [-s socket] command [argument ...]\n",
110
	    __progname);
111
	exit(1);
112
}
113
114
int
115
main(int argc, char *argv[])
116
{
117
	struct sockaddr_un	 sun;
118
	int			 fd, n, done, ch, nodescr = 0, verbose = 0;
119
	struct imsg		 imsg;
120
	struct network_config	 net;
121
	struct parse_result	*res;
122
	struct ctl_neighbor	 neighbor;
123
	struct ctl_show_rib_request	ribreq;
124
	char			*sockname;
125
	enum imsg_type		 type;
126
127
	if (pledge("stdio rpath wpath cpath unix inet dns", NULL) == -1)
128
		err(1, "pledge");
129
130
	sockname = SOCKET_NAME;
131
	while ((ch = getopt(argc, argv, "ns:")) != -1) {
132
		switch (ch) {
133
		case 'n':
134
			if (++nodescr > 1)
135
				usage();
136
			break;
137
		case 's':
138
			sockname = optarg;
139
			break;
140
		default:
141
			usage();
142
			/* NOTREACHED */
143
		}
144
	}
145
	argc -= optind;
146
	argv += optind;
147
148
	if ((res = parse(argc, argv)) == NULL)
149
		exit(1);
150
151
	if (res->action == IRRFILTER) {
152
		if (!(res->flags & (F_IPV4|F_IPV6)))
153
			res->flags |= (F_IPV4|F_IPV6);
154
		irr_main(res->as.as, res->flags, res->irr_outdir);
155
	}
156
157
	if (pledge("stdio rpath wpath unix cpath", NULL) == -1)
158
		err(1, "pledge");
159
160
	memcpy(&neighbor.addr, &res->peeraddr, sizeof(neighbor.addr));
161
	strlcpy(neighbor.descr, res->peerdesc, sizeof(neighbor.descr));
162
163
	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
164
		err(1, "control_init: socket");
165
166
	bzero(&sun, sizeof(sun));
167
	sun.sun_family = AF_UNIX;
168
	if (strlcpy(sun.sun_path, sockname, sizeof(sun.sun_path)) >=
169
	    sizeof(sun.sun_path))
170
		errx(1, "socket name too long");
171
	if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1)
172
		err(1, "connect: %s", sockname);
173
174
	if (pledge("stdio rpath wpath cpath", NULL) == -1)
175
		err(1, "pledge");
176
177
	if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
178
		err(1, NULL);
179
	imsg_init(ibuf, fd);
180
	done = 0;
181
182
	switch (res->action) {
183
	case NONE:
184
	case IRRFILTER:
185
		usage();
186
		/* NOTREACHED */
187
	case SHOW:
188
	case SHOW_SUMMARY:
189
		imsg_compose(ibuf, IMSG_CTL_SHOW_NEIGHBOR, 0, 0, -1, NULL, 0);
190
		show_summary_head();
191
		break;
192
	case SHOW_SUMMARY_TERSE:
193
		imsg_compose(ibuf, IMSG_CTL_SHOW_TERSE, 0, 0, -1, NULL, 0);
194
		break;
195
	case SHOW_FIB:
196
		if (!res->addr.aid) {
197
			struct ibuf	*msg;
198
			sa_family_t	 af;
199
200
			af = aid2af(res->aid);
201
			if ((msg = imsg_create(ibuf, IMSG_CTL_KROUTE,
202
			    res->rtableid, 0, sizeof(res->flags) +
203
			    sizeof(af))) == NULL)
204
				errx(1, "imsg_create failure");
205
			if (imsg_add(msg, &res->flags, sizeof(res->flags)) ==
206
			    -1 ||
207
			    imsg_add(msg, &af, sizeof(af)) == -1)
208
				errx(1, "imsg_add failure");
209
			imsg_close(ibuf, msg);
210
		} else
211
			imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, res->rtableid,
212
			    0, -1, &res->addr, sizeof(res->addr));
213
		show_fib_head();
214
		break;
215
	case SHOW_FIB_TABLES:
216
		imsg_compose(ibuf, IMSG_CTL_SHOW_FIB_TABLES, 0, 0, -1, NULL, 0);
217
		show_fib_tables_head();
218
		break;
219
	case SHOW_NEXTHOP:
220
		imsg_compose(ibuf, IMSG_CTL_SHOW_NEXTHOP, res->rtableid, 0, -1,
221
		    NULL, 0);
222
		show_nexthop_head();
223
		break;
224
	case SHOW_INTERFACE:
225
		imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1, NULL, 0);
226
		show_interface_head();
227
		break;
228
	case SHOW_NEIGHBOR:
229
	case SHOW_NEIGHBOR_TIMERS:
230
	case SHOW_NEIGHBOR_TERSE:
231
		neighbor.show_timers = (res->action == SHOW_NEIGHBOR_TIMERS);
232
		if (res->peeraddr.aid || res->peerdesc[0])
233
			imsg_compose(ibuf, IMSG_CTL_SHOW_NEIGHBOR, 0, 0, -1,
234
			    &neighbor, sizeof(neighbor));
235
		else
236
			imsg_compose(ibuf, IMSG_CTL_SHOW_NEIGHBOR, 0, 0, -1,
237
			    NULL, 0);
238
		break;
239
	case SHOW_RIB:
240
		bzero(&ribreq, sizeof(ribreq));
241
		type = IMSG_CTL_SHOW_RIB;
242
		if (res->as.type != AS_NONE) {
243
			memcpy(&ribreq.as, &res->as, sizeof(res->as));
244
			type = IMSG_CTL_SHOW_RIB_AS;
245
		}
246
		if (res->addr.aid) {
247
			memcpy(&ribreq.prefix, &res->addr, sizeof(res->addr));
248
			ribreq.prefixlen = res->prefixlen;
249
			type = IMSG_CTL_SHOW_RIB_PREFIX;
250
		}
251
		if (res->community.as != COMMUNITY_UNSET &&
252
		    res->community.type != COMMUNITY_UNSET) {
253
			memcpy(&ribreq.community, &res->community,
254
			    sizeof(res->community));
255
			type = IMSG_CTL_SHOW_RIB_COMMUNITY;
256
		}
257
		memcpy(&ribreq.neighbor, &neighbor, sizeof(ribreq.neighbor));
258
		strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib));
259
		ribreq.aid = res->aid;
260
		ribreq.flags = res->flags;
261
		imsg_compose(ibuf, type, 0, 0, -1, &ribreq, sizeof(ribreq));
262
		if (!(res->flags & F_CTL_DETAIL))
263
			show_rib_summary_head();
264
		break;
265
	case SHOW_MRT:
266
		close(fd);
267
		bzero(&ribreq, sizeof(ribreq));
268
		if (res->as.type != AS_NONE)
269
			memcpy(&ribreq.as, &res->as, sizeof(res->as));
270
		if (res->addr.aid) {
271
			memcpy(&ribreq.prefix, &res->addr, sizeof(res->addr));
272
			ribreq.prefixlen = res->prefixlen;
273
		}
274
		if (res->community.as != COMMUNITY_UNSET &&
275
		    res->community.type != COMMUNITY_UNSET)
276
			memcpy(&ribreq.community, &res->community,
277
			    sizeof(res->community));
278
		memcpy(&ribreq.neighbor, &neighbor, sizeof(ribreq.neighbor));
279
		ribreq.aid = res->aid;
280
		ribreq.flags = res->flags;
281
		show_mrt.arg = &ribreq;
282
		if (!(res->flags & F_CTL_DETAIL))
283
			show_rib_summary_head();
284
		mrt_parse(res->mrtfd, &show_mrt, 1);
285
		exit(0);
286
	case SHOW_RIB_MEM:
287
		imsg_compose(ibuf, IMSG_CTL_SHOW_RIB_MEM, 0, 0, -1, NULL, 0);
288
		break;
289
	case RELOAD:
290
		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0);
291
		printf("reload request sent.\n");
292
		break;
293
	case FIB:
294
		errx(1, "action==FIB");
295
		break;
296
	case FIB_COUPLE:
297
		imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, res->rtableid, 0, -1,
298
		    NULL, 0);
299
		printf("couple request sent.\n");
300
		done = 1;
301
		break;
302
	case FIB_DECOUPLE:
303
		imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, res->rtableid, 0, -1,
304
		    NULL, 0);
305
		printf("decouple request sent.\n");
306
		done = 1;
307
		break;
308
	case NEIGHBOR:
309
		errx(1, "action==NEIGHBOR");
310
		break;
311
	case NEIGHBOR_UP:
312
		imsg_compose(ibuf, IMSG_CTL_NEIGHBOR_UP, 0, 0, -1,
313
		    &neighbor, sizeof(neighbor));
314
		break;
315
	case NEIGHBOR_DOWN:
316
		imsg_compose(ibuf, IMSG_CTL_NEIGHBOR_DOWN, 0, 0, -1,
317
		    &neighbor, sizeof(neighbor));
318
		break;
319
	case NEIGHBOR_CLEAR:
320
		imsg_compose(ibuf, IMSG_CTL_NEIGHBOR_CLEAR, 0, 0, -1,
321
		    &neighbor, sizeof(neighbor));
322
		break;
323
	case NEIGHBOR_RREFRESH:
324
		imsg_compose(ibuf, IMSG_CTL_NEIGHBOR_RREFRESH, 0, 0, -1,
325
		    &neighbor, sizeof(neighbor));
326
		break;
327
	case NEIGHBOR_DESTROY:
328
		imsg_compose(ibuf, IMSG_CTL_NEIGHBOR_DESTROY, 0, 0, -1,
329
		    &neighbor, sizeof(neighbor));
330
		break;
331
	case NETWORK_BULK_ADD:
332
	case NETWORK_BULK_REMOVE:
333
		network_bulk(res);
334
		printf("requests sent.\n");
335
		done = 1;
336
		break;
337
	case NETWORK_ADD:
338
	case NETWORK_REMOVE:
339
		bzero(&net, sizeof(net));
340
		memcpy(&net.prefix, &res->addr, sizeof(res->addr));
341
		net.prefixlen = res->prefixlen;
342
		/* attribute sets are not supported */
343
		if (res->action == NETWORK_ADD) {
344
			imsg_compose(ibuf, IMSG_NETWORK_ADD, 0, 0, -1,
345
			    &net, sizeof(net));
346
			send_filterset(ibuf, &res->set);
347
			imsg_compose(ibuf, IMSG_NETWORK_DONE, 0, 0, -1,
348
			    NULL, 0);
349
		} else
350
			imsg_compose(ibuf, IMSG_NETWORK_REMOVE, 0, 0, -1,
351
			    &net, sizeof(net));
352
		printf("request sent.\n");
353
		done = 1;
354
		break;
355
	case NETWORK_FLUSH:
356
		imsg_compose(ibuf, IMSG_NETWORK_FLUSH, 0, 0, -1, NULL, 0);
357
		printf("request sent.\n");
358
		done = 1;
359
		break;
360
	case NETWORK_SHOW:
361
		bzero(&ribreq, sizeof(ribreq));
362
		ribreq.aid = res->aid;
363
		strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib));
364
		imsg_compose(ibuf, IMSG_CTL_SHOW_NETWORK, 0, 0, -1,
365
		    &ribreq, sizeof(ribreq));
366
		show_network_head();
367
		break;
368
	case NETWORK_MRT:
369
		bzero(&ribreq, sizeof(ribreq));
370
		if (res->as.type != AS_NONE)
371
			memcpy(&ribreq.as, &res->as, sizeof(res->as));
372
		if (res->addr.aid) {
373
			memcpy(&ribreq.prefix, &res->addr, sizeof(res->addr));
374
			ribreq.prefixlen = res->prefixlen;
375
		}
376
		if (res->community.as != COMMUNITY_UNSET &&
377
		    res->community.type != COMMUNITY_UNSET)
378
			memcpy(&ribreq.community, &res->community,
379
			    sizeof(res->community));
380
		memcpy(&ribreq.neighbor, &neighbor, sizeof(ribreq.neighbor));
381
		ribreq.aid = res->aid;
382
		ribreq.flags = res->flags;
383
		net_mrt.arg = &ribreq;
384
		mrt_parse(res->mrtfd, &net_mrt, 1);
385
		done = 1;
386
		break;
387
	case LOG_VERBOSE:
388
		verbose = 1;
389
		/* FALLTHROUGH */
390
	case LOG_BRIEF:
391
		imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1,
392
		    &verbose, sizeof(verbose));
393
		printf("logging request sent.\n");
394
		done = 1;
395
		break;
396
	}
397
398
	while (ibuf->w.queued)
399
		if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
400
			err(1, "write error");
401
402
	while (!done) {
403
		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
404
			err(1, "imsg_read error");
405
		if (n == 0)
406
			errx(1, "pipe closed");
407
408
		while (!done) {
409
			if ((n = imsg_get(ibuf, &imsg)) == -1)
410
				err(1, "imsg_get error");
411
			if (n == 0)
412
				break;
413
414
			if (imsg.hdr.type == IMSG_CTL_RESULT) {
415
				done = show_result(&imsg);
416
				imsg_free(&imsg);
417
				continue;
418
			}
419
420
			switch (res->action) {
421
			case SHOW:
422
			case SHOW_SUMMARY:
423
				done = show_summary_msg(&imsg, nodescr);
424
				break;
425
			case SHOW_SUMMARY_TERSE:
426
				done = show_summary_terse_msg(&imsg, nodescr);
427
				break;
428
			case SHOW_FIB:
429
			case SHOW_FIB_TABLES:
430
			case NETWORK_SHOW:
431
				done = show_fib_msg(&imsg);
432
				break;
433
			case SHOW_NEXTHOP:
434
				done = show_nexthop_msg(&imsg);
435
				break;
436
			case SHOW_INTERFACE:
437
				done = show_interface_msg(&imsg);
438
				break;
439
			case SHOW_NEIGHBOR:
440
				done = show_neighbor_msg(&imsg, NV_DEFAULT);
441
				break;
442
			case SHOW_NEIGHBOR_TIMERS:
443
				done = show_neighbor_msg(&imsg, NV_TIMERS);
444
				break;
445
			case SHOW_NEIGHBOR_TERSE:
446
				done = show_neighbor_terse(&imsg);
447
				break;
448
			case SHOW_RIB:
449
				if (res->flags & F_CTL_DETAIL)
450
					done = show_rib_detail_msg(&imsg,
451
					    nodescr);
452
				else
453
					done = show_rib_summary_msg(&imsg);
454
				break;
455
			case SHOW_RIB_MEM:
456
				done = show_rib_memory_msg(&imsg);
457
				break;
458
			case NEIGHBOR:
459
			case NEIGHBOR_UP:
460
			case NEIGHBOR_DOWN:
461
			case NEIGHBOR_CLEAR:
462
			case NEIGHBOR_RREFRESH:
463
			case NEIGHBOR_DESTROY:
464
			case NONE:
465
			case RELOAD:
466
			case FIB:
467
			case FIB_COUPLE:
468
			case FIB_DECOUPLE:
469
			case NETWORK_ADD:
470
			case NETWORK_REMOVE:
471
			case NETWORK_FLUSH:
472
			case NETWORK_BULK_ADD:
473
			case NETWORK_BULK_REMOVE:
474
			case IRRFILTER:
475
			case LOG_VERBOSE:
476
			case LOG_BRIEF:
477
			case SHOW_MRT:
478
			case NETWORK_MRT:
479
				break;
480
			}
481
			imsg_free(&imsg);
482
		}
483
	}
484
	close(fd);
485
	free(ibuf);
486
487
	exit(0);
488
}
489
490
char *
491
fmt_peer(const char *descr, const struct bgpd_addr *remote_addr,
492
    int masklen, int nodescr)
493
{
494
	const char	*ip;
495
	char		*p;
496
497
	if (descr[0] && !nodescr) {
498
		if ((p = strdup(descr)) == NULL)
499
			err(1, NULL);
500
		return (p);
501
	}
502
503
	ip = log_addr(remote_addr);
504
	if (masklen != -1 && ((remote_addr->aid == AID_INET && masklen != 32) ||
505
	    (remote_addr->aid == AID_INET6 && masklen != 128))) {
506
		if (asprintf(&p, "%s/%u", ip, masklen) == -1)
507
			err(1, NULL);
508
	} else {
509
		if ((p = strdup(ip)) == NULL)
510
			err(1, NULL);
511
	}
512
513
	return (p);
514
}
515
516
void
517
show_summary_head(void)
518
{
519
	printf("%-20s %8s %10s %10s %5s %-8s %s\n", "Neighbor", "AS",
520
	    "MsgRcvd", "MsgSent", "OutQ", "Up/Down", "State/PrfRcvd");
521
}
522
523
int
524
show_summary_msg(struct imsg *imsg, int nodescr)
525
{
526
	struct peer		*p;
527
	char			*s;
528
	const char		*a;
529
	size_t			alen;
530
531
	switch (imsg->hdr.type) {
532
	case IMSG_CTL_SHOW_NEIGHBOR:
533
		p = imsg->data;
534
		s = fmt_peer(p->conf.descr, &p->conf.remote_addr,
535
		    p->conf.remote_masklen, nodescr);
536
537
		a = log_as(p->conf.remote_as);
538
		alen = strlen(a);
539
		/* max displayed lenght of the peers name is 28 */
540
		if (alen < 28) {
541
			if (strlen(s) > 28 - alen)
542
				s[28 - alen] = 0;
543
		} else
544
			alen = 0;
545
546
		printf("%-*s %s %10llu %10llu %5u %-8s ",
547
		    (28 - (int)alen), s, a,
548
		    p->stats.msg_rcvd_open + p->stats.msg_rcvd_notification +
549
		    p->stats.msg_rcvd_update + p->stats.msg_rcvd_keepalive +
550
		    p->stats.msg_rcvd_rrefresh,
551
		    p->stats.msg_sent_open + p->stats.msg_sent_notification +
552
		    p->stats.msg_sent_update + p->stats.msg_sent_keepalive +
553
		    p->stats.msg_sent_rrefresh,
554
		    p->wbuf.queued,
555
		    fmt_timeframe(p->stats.last_updown));
556
		if (p->state == STATE_ESTABLISHED) {
557
			printf("%6u", p->stats.prefix_cnt);
558
			if (p->conf.max_prefix != 0)
559
				printf("/%u", p->conf.max_prefix);
560
		} else if (p->conf.template)
561
			printf("Template");
562
		else
563
			printf("%s", statenames[p->state]);
564
		printf("\n");
565
		free(s);
566
		break;
567
	case IMSG_CTL_END:
568
		return (1);
569
	default:
570
		break;
571
	}
572
573
	return (0);
574
}
575
576
int
577
show_summary_terse_msg(struct imsg *imsg, int nodescr)
578
{
579
	struct peer		*p;
580
	char			*s;
581
582
	switch (imsg->hdr.type) {
583
	case IMSG_CTL_SHOW_NEIGHBOR:
584
		p = imsg->data;
585
		s = fmt_peer(p->conf.descr, &p->conf.remote_addr,
586
		    p->conf.remote_masklen, nodescr);
587
		printf("%s %s %s\n", s, log_as(p->conf.remote_as),
588
		    p->conf.template ? "Template" : statenames[p->state]);
589
		free(s);
590
		break;
591
	case IMSG_CTL_END:
592
		return (1);
593
	default:
594
		break;
595
	}
596
597
	return (0);
598
}
599
600
int
601
show_neighbor_terse(struct imsg *imsg)
602
{
603
	struct peer		*p;
604
605
	switch (imsg->hdr.type) {
606
	case IMSG_CTL_SHOW_NEIGHBOR:
607
		p = imsg->data;
608
		printf("%llu %llu %llu %llu %llu %llu %llu "
609
		    "%llu %llu %llu %u %u %llu %llu %llu %llu\n",
610
		    p->stats.msg_sent_open, p->stats.msg_rcvd_open,
611
		    p->stats.msg_sent_notification,
612
		    p->stats.msg_rcvd_notification,
613
		    p->stats.msg_sent_update, p->stats.msg_rcvd_update,
614
		    p->stats.msg_sent_keepalive, p->stats.msg_rcvd_keepalive,
615
		    p->stats.msg_sent_rrefresh, p->stats.msg_rcvd_rrefresh,
616
		    p->stats.prefix_cnt, p->conf.max_prefix,
617
		    p->stats.prefix_sent_update, p->stats.prefix_rcvd_update,
618
		    p->stats.prefix_sent_withdraw,
619
		    p->stats.prefix_rcvd_withdraw);
620
		break;
621
	case IMSG_CTL_END:
622
		return (1);
623
	default:
624
		break;
625
	}
626
627
	return (0);
628
}
629
630
const char *
631
print_auth_method(enum auth_method method)
632
{
633
	switch (method) {
634
	case AUTH_MD5SIG:
635
		return ", using md5sig";
636
	case AUTH_IPSEC_MANUAL_ESP:
637
		return ", using ipsec manual esp";
638
	case AUTH_IPSEC_MANUAL_AH:
639
		return ", using ipsec manual ah";
640
	case AUTH_IPSEC_IKE_ESP:
641
		return ", using ipsec ike esp";
642
	case AUTH_IPSEC_IKE_AH:
643
		return ", using ipsec ike ah";
644
	case AUTH_NONE:	/* FALLTHROUGH */
645
	default:
646
		return "";
647
	}
648
}
649
650
int
651
show_neighbor_msg(struct imsg *imsg, enum neighbor_views nv)
652
{
653
	struct peer		*p;
654
	struct ctl_timer	*t;
655
	struct in_addr		 ina;
656
	char			 buf[NI_MAXHOST], pbuf[NI_MAXSERV], *s;
657
	int			 hascapamp = 0;
658
	u_int8_t		 i;
659
660
	switch (imsg->hdr.type) {
661
	case IMSG_CTL_SHOW_NEIGHBOR:
662
		p = imsg->data;
663
		if ((p->conf.remote_addr.aid == AID_INET &&
664
		    p->conf.remote_masklen != 32) ||
665
		    (p->conf.remote_addr.aid == AID_INET6 &&
666
		    p->conf.remote_masklen != 128)) {
667
			if (asprintf(&s, "%s/%u",
668
			    log_addr(&p->conf.remote_addr),
669
			    p->conf.remote_masklen) == -1)
670
				err(1, NULL);
671
		} else
672
			if ((s = strdup(log_addr(&p->conf.remote_addr))) ==
673
			    NULL)
674
				err(1, "strdup");
675
676
		ina.s_addr = p->remote_bgpid;
677
		printf("BGP neighbor is %s, ", s);
678
		free(s);
679
		if (p->conf.remote_as == 0 && p->conf.template)
680
			printf("remote AS: accept any");
681
		else
682
			printf("remote AS %s", log_as(p->conf.remote_as));
683
		if (p->conf.template)
684
			printf(", Template");
685
		if (p->template)
686
			printf(", Cloned");
687
		if (p->conf.passive)
688
			printf(", Passive");
689
		if (p->conf.ebgp && p->conf.distance > 1)
690
			printf(", Multihop (%u)", (int)p->conf.distance);
691
		printf("\n");
692
		if (p->conf.descr[0])
693
			printf(" Description: %s\n", p->conf.descr);
694
		if (p->conf.max_prefix) {
695
			printf(" Max-prefix: %u", p->conf.max_prefix);
696
			if (p->conf.max_prefix_restart)
697
				printf(" (restart %u)",
698
				    p->conf.max_prefix_restart);
699
			printf("\n");
700
		}
701
		printf("  BGP version 4, remote router-id %s",
702
		    inet_ntoa(ina));
703
		printf("%s\n", print_auth_method(p->auth.method));
704
		printf("  BGP state = %s", statenames[p->state]);
705
		if (p->stats.last_updown != 0)
706
			printf(", %s for %s",
707
			    p->state == STATE_ESTABLISHED ? "up" : "down",
708
			    fmt_timeframe(p->stats.last_updown));
709
		printf("\n");
710
		printf("  Last read %s, holdtime %us, keepalive interval %us\n",
711
		    fmt_timeframe(p->stats.last_read),
712
		    p->holdtime, p->holdtime/3);
713
		for (i = 0; i < AID_MAX; i++)
714
			if (p->capa.peer.mp[i])
715
				hascapamp = 1;
716
		if (hascapamp || p->capa.peer.refresh ||
717
		    p->capa.peer.grestart.restart || p->capa.peer.as4byte) {
718
			printf("  Neighbor capabilities:\n");
719
			if (hascapamp) {
720
				printf("    Multiprotocol extensions: ");
721
				print_neighbor_capa_mp(p);
722
				printf("\n");
723
			}
724
			if (p->capa.peer.refresh)
725
				printf("    Route Refresh\n");
726
			if (p->capa.peer.grestart.restart) {
727
				printf("    Graceful Restart");
728
				print_neighbor_capa_restart(p);
729
				printf("\n");
730
			}
731
			if (p->capa.peer.as4byte)
732
				printf("    4-byte AS numbers\n");
733
		}
734
		printf("\n");
735
		if (nv == NV_TIMERS)
736
			break;
737
		print_neighbor_msgstats(p);
738
		printf("\n");
739
		if (p->state == STATE_IDLE) {
740
			static const char	*errstr;
741
742
			errstr = get_errstr(p->stats.last_sent_errcode,
743
			    p->stats.last_sent_suberr);
744
			if (errstr)
745
				printf("  Last error: %s\n\n", errstr);
746
		} else {
747
			if (getnameinfo((struct sockaddr *)&p->sa_local,
748
			    (socklen_t)p->sa_local.ss_len,
749
			    buf, sizeof(buf), pbuf, sizeof(pbuf),
750
			    NI_NUMERICHOST | NI_NUMERICSERV)) {
751
				strlcpy(buf, "(unknown)", sizeof(buf));
752
				strlcpy(pbuf, "", sizeof(pbuf));
753
			}
754
			printf("  Local host:  %20s, Local port:  %5s\n", buf,
755
			    pbuf);
756
757
			if (getnameinfo((struct sockaddr *)&p->sa_remote,
758
			    (socklen_t)p->sa_remote.ss_len,
759
			    buf, sizeof(buf), pbuf, sizeof(pbuf),
760
			    NI_NUMERICHOST | NI_NUMERICSERV)) {
761
				strlcpy(buf, "(unknown)", sizeof(buf));
762
				strlcpy(pbuf, "", sizeof(pbuf));
763
			}
764
			printf("  Remote host: %20s, Remote port: %5s\n", buf,
765
			    pbuf);
766
			printf("\n");
767
		}
768
		break;
769
	case IMSG_CTL_SHOW_TIMER:
770
		t = imsg->data;
771
		if (t->type > 0 && t->type < Timer_Max)
772
			print_timer(timernames[t->type], t->val);
773
		break;
774
	case IMSG_CTL_END:
775
		return (1);
776
		break;
777
	default:
778
		break;
779
	}
780
781
	return (0);
782
}
783
784
void
785
print_neighbor_capa_mp(struct peer *p)
786
{
787
	int		comma;
788
	u_int8_t	i;
789
790
	for (i = 0, comma = 0; i < AID_MAX; i++)
791
		if (p->capa.peer.mp[i]) {
792
			printf("%s%s", comma ? ", " : "", aid2str(i));
793
			comma = 1;
794
		}
795
}
796
797
void
798
print_neighbor_capa_restart(struct peer *p)
799
{
800
	int		comma;
801
	u_int8_t	i;
802
803
	if (p->capa.peer.grestart.timeout)
804
		printf(": Timeout: %d, ", p->capa.peer.grestart.timeout);
805
	for (i = 0, comma = 0; i < AID_MAX; i++)
806
		if (p->capa.peer.grestart.flags[i] & CAPA_GR_PRESENT) {
807
			if (!comma &&
808
			    p->capa.peer.grestart.flags[i] & CAPA_GR_RESTART)
809
				printf("restarted, ");
810
			if (comma)
811
				printf(", ");
812
			printf("%s", aid2str(i));
813
			if (p->capa.peer.grestart.flags[i] & CAPA_GR_FORWARD)
814
				printf(" (preserved)");
815
			comma = 1;
816
		}
817
}
818
819
void
820
print_neighbor_msgstats(struct peer *p)
821
{
822
	printf("  Message statistics:\n");
823
	printf("  %-15s %-10s %-10s\n", "", "Sent", "Received");
824
	printf("  %-15s %10llu %10llu\n", "Opens",
825
	    p->stats.msg_sent_open, p->stats.msg_rcvd_open);
826
	printf("  %-15s %10llu %10llu\n", "Notifications",
827
	    p->stats.msg_sent_notification, p->stats.msg_rcvd_notification);
828
	printf("  %-15s %10llu %10llu\n", "Updates",
829
	    p->stats.msg_sent_update, p->stats.msg_rcvd_update);
830
	printf("  %-15s %10llu %10llu\n", "Keepalives",
831
	    p->stats.msg_sent_keepalive, p->stats.msg_rcvd_keepalive);
832
	printf("  %-15s %10llu %10llu\n", "Route Refresh",
833
	    p->stats.msg_sent_rrefresh, p->stats.msg_rcvd_rrefresh);
834
	printf("  %-15s %10llu %10llu\n\n", "Total",
835
	    p->stats.msg_sent_open + p->stats.msg_sent_notification +
836
	    p->stats.msg_sent_update + p->stats.msg_sent_keepalive +
837
	    p->stats.msg_sent_rrefresh,
838
	    p->stats.msg_rcvd_open + p->stats.msg_rcvd_notification +
839
	    p->stats.msg_rcvd_update + p->stats.msg_rcvd_keepalive +
840
	    p->stats.msg_rcvd_rrefresh);
841
	printf("  Update statistics:\n");
842
	printf("  %-15s %-10s %-10s\n", "", "Sent", "Received");
843
	printf("  %-15s %10llu %10llu\n", "Updates",
844
	    p->stats.prefix_sent_update, p->stats.prefix_rcvd_update);
845
	printf("  %-15s %10llu %10llu\n", "Withdraws",
846
	    p->stats.prefix_sent_withdraw, p->stats.prefix_rcvd_withdraw);
847
	printf("  %-15s %10llu %10llu\n", "End-of-Rib",
848
	    p->stats.prefix_sent_eor, p->stats.prefix_rcvd_eor);
849
}
850
851
void
852
print_timer(const char *name, time_t d)
853
{
854
	printf("  %-20s ", name);
855
856
	if (d <= 0)
857
		printf("%-20s\n", "due");
858
	else
859
		printf("due in %-13s\n", fmt_timeframe_core(d));
860
}
861
862
#define TF_BUFS	8
863
#define TF_LEN	9
864
865
static char *
866
fmt_timeframe(time_t t)
867
{
868
	if (t == 0)
869
		return ("Never");
870
	else
871
		return (fmt_timeframe_core(time(NULL) - t));
872
}
873
874
static char *
875
fmt_timeframe_core(time_t t)
876
{
877
	char		*buf;
878
	static char	 tfbuf[TF_BUFS][TF_LEN];	/* ring buffer */
879
	static int	 idx = 0;
880
	unsigned int	 sec, min, hrs, day;
881
	unsigned long long	week;
882
883
	buf = tfbuf[idx++];
884
	if (idx == TF_BUFS)
885
		idx = 0;
886
887
	week = t;
888
889
	sec = week % 60;
890
	week /= 60;
891
	min = week % 60;
892
	week /= 60;
893
	hrs = week % 24;
894
	week /= 24;
895
	day = week % 7;
896
	week /= 7;
897
898
	if (week > 0)
899
		snprintf(buf, TF_LEN, "%02lluw%01ud%02uh", week, day, hrs);
900
	else if (day > 0)
901
		snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
902
	else
903
		snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
904
905
	return (buf);
906
}
907
908
void
909
show_fib_head(void)
910
{
911
	printf("flags: "
912
	    "* = valid, B = BGP, C = Connected, S = Static, D = Dynamic\n");
913
	printf("       "
914
	    "N = BGP Nexthop reachable via this route R = redistributed\n");
915
	printf("       r = reject route, b = blackhole route\n\n");
916
	printf("flags prio destination          gateway\n");
917
}
918
919
void
920
show_fib_tables_head(void)
921
{
922
	printf("%-5s %-20s %-8s\n", "Table", "Description", "State");
923
}
924
925
void
926
show_network_head(void)
927
{
928
	printf("flags: S = Static\n");
929
	printf("flags destination\n");
930
}
931
932
void
933
show_fib_flags(u_int16_t flags)
934
{
935
	if (flags & F_DOWN)
936
		printf(" ");
937
	else
938
		printf("*");
939
940
	if (flags & F_BGPD_INSERTED)
941
		printf("B");
942
	else if (flags & F_CONNECTED)
943
		printf("C");
944
	else if (flags & F_STATIC)
945
		printf("S");
946
	else if (flags & F_DYNAMIC)
947
		printf("D");
948
	else
949
		printf(" ");
950
951
	if (flags & F_NEXTHOP)
952
		printf("N");
953
	else
954
		printf(" ");
955
956
	if (flags & F_REDISTRIBUTED)
957
		printf("R");
958
	else
959
		printf(" ");
960
961
	if (flags & F_REJECT && flags & F_BLACKHOLE)
962
		printf("f");
963
	else if (flags & F_REJECT)
964
		printf("r");
965
	else if (flags & F_BLACKHOLE)
966
		printf("b");
967
	else
968
		printf(" ");
969
970
	printf(" ");
971
}
972
973
int
974
show_fib_msg(struct imsg *imsg)
975
{
976
	struct kroute_full	*kf;
977
	struct ktable		*kt;
978
	char			*p;
979
980
	switch (imsg->hdr.type) {
981
	case IMSG_CTL_KROUTE:
982
	case IMSG_CTL_SHOW_NETWORK:
983
		if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(*kf))
984
			errx(1, "wrong imsg len");
985
		kf = imsg->data;
986
987
		show_fib_flags(kf->flags);
988
989
		if (asprintf(&p, "%s/%u", log_addr(&kf->prefix),
990
		    kf->prefixlen) == -1)
991
			err(1, NULL);
992
		printf("%4i %-20s ", kf->priority, p);
993
		free(p);
994
995
		if (kf->flags & F_CONNECTED)
996
			printf("link#%u", kf->ifindex);
997
		else
998
			printf("%s", log_addr(&kf->nexthop));
999
		printf("\n");
1000
1001
		break;
1002
	case IMSG_CTL_SHOW_FIB_TABLES:
1003
		if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(*kt))
1004
			errx(1, "wrong imsg len");
1005
		kt = imsg->data;
1006
1007
		printf("%5i %-20s %-8s%s\n", kt->rtableid, kt->descr,
1008
		    kt->fib_sync ? "coupled" : "decoupled",
1009
		    kt->fib_sync != kt->fib_conf ? "*" : "");
1010
1011
		break;
1012
	case IMSG_CTL_END:
1013
		return (1);
1014
	default:
1015
		break;
1016
	}
1017
1018
	return (0);
1019
}
1020
1021
void
1022
show_nexthop_head(void)
1023
{
1024
	printf("Flags: * = nexthop valid\n");
1025
	printf("\n  %-15s %-19s%-4s %-15s %-20s\n", "Nexthop", "Route",
1026
	     "Prio", "Gateway", "Iface");
1027
}
1028
1029
int
1030
show_nexthop_msg(struct imsg *imsg)
1031
{
1032
	struct ctl_show_nexthop	*p;
1033
	struct kroute		*k;
1034
	struct kroute6		*k6;
1035
	char			*s;
1036
1037
	switch (imsg->hdr.type) {
1038
	case IMSG_CTL_SHOW_NEXTHOP:
1039
		p = imsg->data;
1040
		printf("%s %-15s ", p->valid ? "*" : " ", log_addr(&p->addr));
1041
		if (!p->krvalid) {
1042
			printf("\n");
1043
			return (0);
1044
		}
1045
		switch (p->addr.aid) {
1046
		case AID_INET:
1047
			k = &p->kr.kr4;
1048
			if (asprintf(&s, "%s/%u", inet_ntoa(k->prefix),
1049
			    k->prefixlen) == -1)
1050
				err(1, NULL);
1051
			printf("%-20s", s);
1052
			free(s);
1053
			printf("%3i %-15s ", k->priority,
1054
			    k->flags & F_CONNECTED ? "connected" :
1055
			    inet_ntoa(k->nexthop));
1056
			break;
1057
		case AID_INET6:
1058
			k6 = &p->kr.kr6;
1059
			if (asprintf(&s, "%s/%u", log_in6addr(&k6->prefix),
1060
			    k6->prefixlen) == -1)
1061
				err(1, NULL);
1062
			printf("%-20s", s);
1063
			free(s);
1064
			printf("%3i %-15s ", k6->priority,
1065
			    k6->flags & F_CONNECTED ? "connected" :
1066
			    log_in6addr(&k6->nexthop));
1067
			break;
1068
		default:
1069
			printf("unknown address family\n");
1070
			return (0);
1071
		}
1072
		if (p->kif.ifname[0]) {
1073
			char *s1;
1074
			if (p->kif.baudrate) {
1075
				if (asprintf(&s1, ", %s",
1076
				    get_baudrate(p->kif.baudrate,
1077
				    "bps")) == -1)
1078
					err(1, NULL);
1079
			} else if (asprintf(&s1, ", %s", get_linkstate(
1080
			    p->kif.if_type, p->kif.link_state)) == -1)
1081
					err(1, NULL);
1082
			if (asprintf(&s, "%s (%s%s)", p->kif.ifname,
1083
			    p->kif.flags & IFF_UP ? "UP" : "DOWN", s1) == -1)
1084
				err(1, NULL);
1085
			printf("%-15s", s);
1086
			free(s1);
1087
			free(s);
1088
		}
1089
		printf("\n");
1090
		break;
1091
	case IMSG_CTL_END:
1092
		return (1);
1093
		break;
1094
	default:
1095
		break;
1096
	}
1097
1098
	return (0);
1099
}
1100
1101
1102
void
1103
show_interface_head(void)
1104
{
1105
	printf("%-15s%-15s%-15s%s\n", "Interface", "Nexthop state", "Flags",
1106
	    "Link state");
1107
}
1108
1109
const struct if_status_description
1110
		if_status_descriptions[] = LINK_STATE_DESCRIPTIONS;
1111
const struct ifmedia_description
1112
		ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS;
1113
1114
uint64_t
1115
ift2ifm(uint8_t if_type)
1116
{
1117
	switch (if_type) {
1118
	case IFT_ETHER:
1119
		return (IFM_ETHER);
1120
	case IFT_FDDI:
1121
		return (IFM_FDDI);
1122
	case IFT_CARP:
1123
		return (IFM_CARP);
1124
	case IFT_IEEE80211:
1125
		return (IFM_IEEE80211);
1126
	default:
1127
		return (0);
1128
	}
1129
}
1130
1131
const char *
1132
get_media_descr(uint64_t media_type)
1133
{
1134
	const struct ifmedia_description	*p;
1135
1136
	for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++)
1137
		if (media_type == p->ifmt_word)
1138
			return (p->ifmt_string);
1139
1140
	return ("unknown media");
1141
}
1142
1143
const char *
1144
get_linkstate(uint8_t if_type, int link_state)
1145
{
1146
	const struct if_status_description *p;
1147
	static char buf[8];
1148
1149
	for (p = if_status_descriptions; p->ifs_string != NULL; p++) {
1150
		if (LINK_STATE_DESC_MATCH(p, if_type, link_state))
1151
			return (p->ifs_string);
1152
	}
1153
	snprintf(buf, sizeof(buf), "[#%d]", link_state);
1154
	return (buf);
1155
}
1156
1157
const char *
1158
get_baudrate(u_int64_t baudrate, char *unit)
1159
{
1160
	static char bbuf[16];
1161
1162
	if (baudrate > IF_Gbps(1))
1163
		snprintf(bbuf, sizeof(bbuf), "%llu G%s",
1164
		    baudrate / IF_Gbps(1), unit);
1165
	else if (baudrate > IF_Mbps(1))
1166
		snprintf(bbuf, sizeof(bbuf), "%llu M%s",
1167
		    baudrate / IF_Mbps(1), unit);
1168
	else if (baudrate > IF_Kbps(1))
1169
		snprintf(bbuf, sizeof(bbuf), "%llu K%s",
1170
		    baudrate / IF_Kbps(1), unit);
1171
	else
1172
		snprintf(bbuf, sizeof(bbuf), "%llu %s",
1173
		    baudrate, unit);
1174
1175
	return (bbuf);
1176
}
1177
1178
int
1179
show_interface_msg(struct imsg *imsg)
1180
{
1181
	struct kif	*k;
1182
	uint64_t	 ifms_type;
1183
1184
	switch (imsg->hdr.type) {
1185
	case IMSG_CTL_SHOW_INTERFACE:
1186
		k = imsg->data;
1187
		printf("%-15s", k->ifname);
1188
		printf("%-15s", k->nh_reachable ? "ok" : "invalid");
1189
		printf("%-15s", k->flags & IFF_UP ? "UP" : "");
1190
1191
		if ((ifms_type = ift2ifm(k->if_type)) != 0)
1192
			printf("%s, ", get_media_descr(ifms_type));
1193
1194
		printf("%s", get_linkstate(k->if_type, k->link_state));
1195
1196
		if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0)
1197
			printf(", %s", get_baudrate(k->baudrate, "Bit/s"));
1198
		printf("\n");
1199
		break;
1200
	case IMSG_CTL_END:
1201
		return (1);
1202
		break;
1203
	default:
1204
		break;
1205
	}
1206
1207
	return (0);
1208
}
1209
1210
void
1211
show_rib_summary_head(void)
1212
{
1213
	printf("flags: * = Valid, > = Selected, I = via IBGP, A = Announced, "
1214
	    "S = Stale\n");
1215
	printf("origin: i = IGP, e = EGP, ? = Incomplete\n\n");
1216
	printf("%-5s %-20s %-15s  %5s %5s %s\n", "flags", "destination",
1217
	    "gateway", "lpref", "med", "aspath origin");
1218
}
1219
1220
void
1221
print_prefix(struct bgpd_addr *prefix, u_int8_t prefixlen, u_int8_t flags)
1222
{
1223
	char			*p;
1224
1225
	print_flags(flags, 1);
1226
	if (asprintf(&p, "%s/%u", log_addr(prefix), prefixlen) == -1)
1227
		err(1, NULL);
1228
	printf("%-20s", p);
1229
	free(p);
1230
}
1231
1232
const char *
1233
print_origin(u_int8_t origin, int sum)
1234
{
1235
	switch (origin) {
1236
	case ORIGIN_IGP:
1237
		return (sum ? "i" : "IGP");
1238
	case ORIGIN_EGP:
1239
		return (sum ? "e" : "EGP");
1240
	case ORIGIN_INCOMPLETE:
1241
		return (sum ? "?" : "incomplete");
1242
	default:
1243
		return (sum ? "X" : "bad origin");
1244
	}
1245
}
1246
1247
void
1248
print_flags(u_int8_t flags, int sum)
1249
{
1250
	char	 flagstr[5];
1251
	char	*p = flagstr;
1252
1253
	if (sum) {
1254
		if (flags & F_PREF_ANNOUNCE)
1255
			*p++ = 'A';
1256
		if (flags & F_PREF_INTERNAL)
1257
			*p++ = 'I';
1258
		if (flags & F_PREF_STALE)
1259
			*p++ = 'S';
1260
		if (flags & F_PREF_ELIGIBLE)
1261
			*p++ = '*';
1262
		if (flags & F_PREF_ACTIVE)
1263
			*p++ = '>';
1264
		*p = '\0';
1265
		printf("%-5s ", flagstr);
1266
	} else {
1267
		if (flags & F_PREF_INTERNAL)
1268
			printf("internal");
1269
		else
1270
			printf("external");
1271
		if (flags & F_PREF_STALE)
1272
			printf(", stale");
1273
		if (flags & F_PREF_ELIGIBLE)
1274
			printf(", valid");
1275
		if (flags & F_PREF_ACTIVE)
1276
			printf(", best");
1277
		if (flags & F_PREF_ANNOUNCE)
1278
			printf(", announced");
1279
	}
1280
}
1281
1282
int
1283
show_rib_summary_msg(struct imsg *imsg)
1284
{
1285
	struct ctl_show_rib	 rib;
1286
	u_char			*asdata;
1287
1288
	switch (imsg->hdr.type) {
1289
	case IMSG_CTL_SHOW_RIB:
1290
		memcpy(&rib, imsg->data, sizeof(rib));
1291
		asdata = imsg->data;
1292
		asdata += sizeof(struct ctl_show_rib);
1293
		show_rib_brief(&rib, asdata);
1294
		break;
1295
	case IMSG_CTL_END:
1296
		return (1);
1297
	default:
1298
		break;
1299
	}
1300
1301
	return (0);
1302
}
1303
1304
int
1305
show_rib_detail_msg(struct imsg *imsg, int nodescr)
1306
{
1307
	struct ctl_show_rib	 rib;
1308
	u_char			*asdata;
1309
	u_int16_t		 ilen;
1310
1311
	switch (imsg->hdr.type) {
1312
	case IMSG_CTL_SHOW_RIB:
1313
		memcpy(&rib, imsg->data, sizeof(rib));
1314
		asdata = imsg->data;
1315
		asdata += sizeof(struct ctl_show_rib);
1316
		show_rib_detail(&rib, asdata, nodescr);
1317
		break;
1318
	case IMSG_CTL_SHOW_RIB_ATTR:
1319
		ilen = imsg->hdr.len - IMSG_HEADER_SIZE;
1320
		if (ilen < 3)
1321
			errx(1, "bad IMSG_CTL_SHOW_RIB_ATTR received");
1322
		show_attr(imsg->data, ilen);
1323
		break;
1324
	case IMSG_CTL_END:
1325
		printf("\n");
1326
		return (1);
1327
	default:
1328
		break;
1329
	}
1330
1331
	return (0);
1332
}
1333
1334
void
1335
show_rib_brief(struct ctl_show_rib *r, u_char *asdata)
1336
{
1337
	char			*aspath;
1338
1339
	print_prefix(&r->prefix, r->prefixlen, r->flags);
1340
	printf(" %-15s ", log_addr(&r->exit_nexthop));
1341
	printf(" %5u %5u ", r->local_pref, r->med);
1342
1343
	if (aspath_asprint(&aspath, asdata, r->aspath_len) == -1)
1344
		err(1, NULL);
1345
	if (strlen(aspath) > 0)
1346
		printf("%s ", aspath);
1347
	free(aspath);
1348
1349
	printf("%s\n", print_origin(r->origin, 1));
1350
}
1351
1352
void
1353
show_rib_detail(struct ctl_show_rib *r, u_char *asdata, int nodescr)
1354
{
1355
	struct in_addr		 id;
1356
	char			*aspath, *s;
1357
	time_t			 now;
1358
1359
	printf("\nBGP routing table entry for %s/%u\n",
1360
	    log_addr(&r->prefix), r->prefixlen);
1361
1362
	if (aspath_asprint(&aspath, asdata, r->aspath_len) == -1)
1363
		err(1, NULL);
1364
	if (strlen(aspath) > 0)
1365
		printf("    %s\n", aspath);
1366
	free(aspath);
1367
1368
	s = fmt_peer(r->descr, &r->remote_addr, -1, nodescr);
1369
	printf("    Nexthop %s ", log_addr(&r->exit_nexthop));
1370
	printf("(via %s) from %s (", log_addr(&r->true_nexthop), s);
1371
	free(s);
1372
	id.s_addr = htonl(r->remote_id);
1373
	printf("%s)\n", inet_ntoa(id));
1374
1375
	printf("    Origin %s, metric %u, localpref %u, weight %u, ",
1376
	    print_origin(r->origin, 0), r->med, r->local_pref, r->weight);
1377
	print_flags(r->flags, 0);
1378
1379
	now = time(NULL);
1380
	if (now > r->lastchange)
1381
		now -= r->lastchange;
1382
	else
1383
		now = 0;
1384
1385
	printf("\n    Last update: %s ago\n", fmt_timeframe_core(now));
1386
}
1387
1388
void
1389
show_attr(void *b, u_int16_t len)
1390
{
1391
	char		*data = b;
1392
	struct in_addr	 id;
1393
	u_int32_t	 as;
1394
	u_int16_t	 alen, ioff;
1395
	u_int8_t	 flags, type;
1396
1397
	if (len < 3)
1398
		errx(1, "show_attr: too short bgp attr");
1399
1400
	flags = data[0];
1401
	type = data[1];
1402
1403
	/* get the attribute length */
1404
	if (flags & ATTR_EXTLEN) {
1405
		if (len < 4)
1406
			errx(1, "show_attr: too short bgp attr");
1407
		memcpy(&alen, data+2, sizeof(u_int16_t));
1408
		alen = ntohs(alen);
1409
		data += 4;
1410
		len -= 4;
1411
	} else {
1412
		alen = (u_char)data[2];
1413
		data += 3;
1414
		len -= 3;
1415
	}
1416
1417
	/* bad imsg len how can that happen!? */
1418
	if (alen > len)
1419
		errx(1, "show_attr: bad length");
1420
1421
	switch (type) {
1422
	case ATTR_COMMUNITIES:
1423
		printf("    Communities: ");
1424
		show_community(data, alen);
1425
		printf("\n");
1426
		break;
1427
	case ATTR_AGGREGATOR:
1428
		memcpy(&as, data, sizeof(as));
1429
		memcpy(&id, data + sizeof(as), sizeof(id));
1430
		printf("    Aggregator: %s [%s]\n",
1431
		    log_as(ntohl(as)), inet_ntoa(id));
1432
		break;
1433
	case ATTR_ORIGINATOR_ID:
1434
		memcpy(&id, data, sizeof(id));
1435
		printf("    Originator Id: %s\n", inet_ntoa(id));
1436
		break;
1437
	case ATTR_CLUSTER_LIST:
1438
		printf("    Cluster ID List:");
1439
		for (ioff = 0; ioff + sizeof(id) <= alen;
1440
		    ioff += sizeof(id)) {
1441
			memcpy(&id, data + ioff, sizeof(id));
1442
			printf(" %s", inet_ntoa(id));
1443
		}
1444
		printf("\n");
1445
		break;
1446
	case ATTR_EXT_COMMUNITIES:
1447
		printf("    Ext. communities: ");
1448
		show_ext_community(data, alen);
1449
		printf("\n");
1450
		break;
1451
	default:
1452
		/* ignore unknown attributes */
1453
		break;
1454
	}
1455
}
1456
1457
void
1458
show_community(u_char *data, u_int16_t len)
1459
{
1460
	u_int16_t	a, v;
1461
	u_int16_t	i;
1462
1463
	if (len & 0x3)
1464
		return;
1465
1466
	for (i = 0; i < len; i += 4) {
1467
		memcpy(&a, data + i, sizeof(a));
1468
		memcpy(&v, data + i + 2, sizeof(v));
1469
		a = ntohs(a);
1470
		v = ntohs(v);
1471
		if (a == COMMUNITY_WELLKNOWN)
1472
			switch (v) {
1473
			case COMMUNITY_NO_EXPORT:
1474
				printf("NO_EXPORT");
1475
				break;
1476
			case COMMUNITY_NO_ADVERTISE:
1477
				printf("NO_ADVERTISE");
1478
				break;
1479
			case COMMUNITY_NO_EXPSUBCONFED:
1480
				printf("NO_EXPORT_SUBCONFED");
1481
				break;
1482
			case COMMUNITY_NO_PEER:
1483
				printf("NO_PEER");
1484
				break;
1485
			case COMMUNITY_BLACKHOLE:
1486
				printf("BLACKHOLE");
1487
				break;
1488
			default:
1489
				printf("WELLKNOWN:%hu", v);
1490
				break;
1491
			}
1492
		else
1493
			printf("%hu:%hu", a, v);
1494
1495
		if (i + 4 < len)
1496
			printf(" ");
1497
	}
1498
}
1499
1500
void
1501
show_ext_community(u_char *data, u_int16_t len)
1502
{
1503
	u_int64_t	ext;
1504
	struct in_addr	ip;
1505
	u_int32_t	as4, u32;
1506
	u_int16_t	i, as2, u16;
1507
	u_int8_t	type, subtype;
1508
1509
	if (len & 0x7)
1510
		return;
1511
1512
	for (i = 0; i < len; i += 8) {
1513
		type = data[i];
1514
		subtype = data[i + 1];
1515
1516
		switch (type & EXT_COMMUNITY_VALUE) {
1517
		case EXT_COMMUNITY_TWO_AS:
1518
			memcpy(&as2, data + i + 2, sizeof(as2));
1519
			memcpy(&u32, data + i + 4, sizeof(u32));
1520
			printf("%s %s:%u", log_ext_subtype(subtype),
1521
			    log_as(ntohs(as2)), ntohl(u32));
1522
			break;
1523
		case EXT_COMMUNITY_IPV4:
1524
			memcpy(&ip, data + i + 2, sizeof(ip));
1525
			memcpy(&u16, data + i + 6, sizeof(u16));
1526
			printf("%s %s:%hu", log_ext_subtype(subtype),
1527
			    inet_ntoa(ip), ntohs(u16));
1528
			break;
1529
		case EXT_COMMUNITY_FOUR_AS:
1530
			memcpy(&as4, data + i + 2, sizeof(as4));
1531
			memcpy(&u16, data + i + 6, sizeof(u16));
1532
			printf("%s %s:%hu", log_ext_subtype(subtype),
1533
			    log_as(ntohl(as4)), ntohs(u16));
1534
			break;
1535
		case EXT_COMMUNITY_OPAQUE:
1536
			memcpy(&ext, data + i, sizeof(ext));
1537
			ext = betoh64(ext) & 0xffffffffffffLL;
1538
			printf("%s 0x%llx", log_ext_subtype(subtype), ext);
1539
			break;
1540
		default:
1541
			memcpy(&ext, data + i, sizeof(ext));
1542
			printf("0x%llx", betoh64(ext));
1543
		}
1544
		if (i + 8 < len)
1545
			printf(", ");
1546
	}
1547
}
1548
1549
char *
1550
fmt_mem(int64_t num)
1551
{
1552
	static char	buf[16];
1553
1554
	if (fmt_scaled(num, buf) == -1)
1555
		snprintf(buf, sizeof(buf), "%lldB", (long long)num);
1556
1557
	return (buf);
1558
}
1559
1560
size_t  pt_sizes[AID_MAX] = AID_PTSIZE;
1561
1562
int
1563
show_rib_memory_msg(struct imsg *imsg)
1564
{
1565
	struct rde_memstats	stats;
1566
	size_t			pts = 0;
1567
	int			i;
1568
1569
	switch (imsg->hdr.type) {
1570
	case IMSG_CTL_SHOW_RIB_MEM:
1571
		memcpy(&stats, imsg->data, sizeof(stats));
1572
		printf("RDE memory statistics\n");
1573
		for (i = 0; i < AID_MAX; i++) {
1574
			if (stats.pt_cnt[i] == 0)
1575
				continue;
1576
			pts += stats.pt_cnt[i] * pt_sizes[i];
1577
			printf("%10lld %s network entries using %s of memory\n",
1578
			    (long long)stats.pt_cnt[i], aid_vals[i].name,
1579
			    fmt_mem(stats.pt_cnt[i] * pt_sizes[i]));
1580
		}
1581
		printf("%10lld rib entries using %s of memory\n",
1582
		    (long long)stats.rib_cnt, fmt_mem(stats.rib_cnt *
1583
		    sizeof(struct rib_entry)));
1584
		printf("%10lld prefix entries using %s of memory\n",
1585
		    (long long)stats.prefix_cnt, fmt_mem(stats.prefix_cnt *
1586
		    sizeof(struct prefix)));
1587
		printf("%10lld BGP path attribute entries using %s of memory\n",
1588
		    (long long)stats.path_cnt, fmt_mem(stats.path_cnt *
1589
		    sizeof(struct rde_aspath)));
1590
		printf("%10lld BGP AS-PATH attribute entries using "
1591
		    "%s of memory,\n\t   and holding %lld references\n",
1592
		    (long long)stats.aspath_cnt, fmt_mem(stats.aspath_size),
1593
		    (long long)stats.aspath_refs);
1594
		printf("%10lld BGP attributes entries using %s of memory\n",
1595
		    (long long)stats.attr_cnt, fmt_mem(stats.attr_cnt *
1596
		    sizeof(struct attr)));
1597
		printf("\t   and holding %lld references\n",
1598
		    (long long)stats.attr_refs);
1599
		printf("%10lld BGP attributes using %s of memory\n",
1600
		    (long long)stats.attr_dcnt, fmt_mem(stats.attr_data));
1601
		printf("RIB using %s of memory\n", fmt_mem(pts +
1602
		    stats.prefix_cnt * sizeof(struct prefix) +
1603
		    stats.rib_cnt * sizeof(struct rib_entry) +
1604
		    stats.path_cnt * sizeof(struct rde_aspath) +
1605
		    stats.aspath_size + stats.attr_cnt * sizeof(struct attr) +
1606
		    stats.attr_data));
1607
		break;
1608
	default:
1609
		break;
1610
	}
1611
1612
	return (1);
1613
}
1614
1615
void
1616
send_filterset(struct imsgbuf *i, struct filter_set_head *set)
1617
{
1618
	struct filter_set	*s;
1619
1620
	while ((s = TAILQ_FIRST(set)) != NULL) {
1621
		imsg_compose(i, IMSG_FILTER_SET, 0, 0, -1, s,
1622
		    sizeof(struct filter_set));
1623
		TAILQ_REMOVE(set, s, entry);
1624
		free(s);
1625
	}
1626
}
1627
1628
const char *
1629
get_errstr(u_int8_t errcode, u_int8_t subcode)
1630
{
1631
	static const char	*errstr = NULL;
1632
1633
	if (errcode && errcode < sizeof(errnames)/sizeof(char *))
1634
		errstr = errnames[errcode];
1635
1636
	switch (errcode) {
1637
	case ERR_HEADER:
1638
		if (subcode &&
1639
		    subcode < sizeof(suberr_header_names)/sizeof(char *))
1640
			errstr = suberr_header_names[subcode];
1641
		break;
1642
	case ERR_OPEN:
1643
		if (subcode &&
1644
		    subcode < sizeof(suberr_open_names)/sizeof(char *))
1645
			errstr = suberr_open_names[subcode];
1646
		break;
1647
	case ERR_UPDATE:
1648
		if (subcode &&
1649
		    subcode < sizeof(suberr_update_names)/sizeof(char *))
1650
			errstr = suberr_update_names[subcode];
1651
		break;
1652
	case ERR_HOLDTIMEREXPIRED:
1653
	case ERR_FSM:
1654
	case ERR_CEASE:
1655
		break;
1656
	default:
1657
		return ("unknown error code");
1658
	}
1659
1660
	return (errstr);
1661
}
1662
1663
int
1664
show_result(struct imsg *imsg)
1665
{
1666
	u_int	rescode;
1667
1668
	if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(rescode))
1669
		errx(1, "got IMSG_CTL_RESULT with wrong len");
1670
	memcpy(&rescode, imsg->data, sizeof(rescode));
1671
1672
	if (rescode == 0)
1673
		printf("request processed\n");
1674
	else {
1675
		if (rescode >
1676
		    sizeof(ctl_res_strerror)/sizeof(ctl_res_strerror[0]))
1677
			printf("unknown result error code %u\n", rescode);
1678
		else
1679
			printf("%s\n", ctl_res_strerror[rescode]);
1680
	}
1681
1682
	return (1);
1683
}
1684
1685
void
1686
network_bulk(struct parse_result *res)
1687
{
1688
	struct network_config net;
1689
	struct filter_set *s = NULL;
1690
	struct bgpd_addr h;
1691
	char *b, *buf, *lbuf;
1692
	size_t slen;
1693
	u_int8_t len;
1694
	FILE *f;
1695
1696
	if ((f = fdopen(STDIN_FILENO, "r")) != NULL) {
1697
		while ((buf = fgetln(f, &slen))) {
1698
			lbuf = NULL;
1699
			if (buf[slen - 1] == '\n')
1700
				buf[slen - 1] = '\0';
1701
			else {
1702
				if ((lbuf = malloc(slen + 1)) == NULL)
1703
					err(1, NULL);
1704
				memcpy(lbuf, buf, slen);
1705
				lbuf[slen] = '\0';
1706
				buf = lbuf;
1707
			}
1708
1709
			while ((b = strsep(&buf, " \t")) != NULL) {
1710
				/* Don't process commented entries */
1711
				if (strchr(b, '#') != NULL)
1712
					break;
1713
				bzero(&net, sizeof(net));
1714
				parse_prefix(b, strlen(b), &h, &len);
1715
				memcpy(&net.prefix, &h, sizeof(h));
1716
				net.prefixlen = len;
1717
1718
				if (res->action == NETWORK_BULK_ADD) {
1719
					imsg_compose(ibuf, IMSG_NETWORK_ADD,
1720
					    0, 0, -1, &net, sizeof(net));
1721
					TAILQ_FOREACH(s, &res->set, entry) {
1722
						imsg_compose(ibuf,
1723
						    IMSG_FILTER_SET,
1724
						    0, 0, -1, s, sizeof(*s));
1725
					}
1726
					imsg_compose(ibuf, IMSG_NETWORK_DONE,
1727
					    0, 0, -1, NULL, 0);
1728
				} else
1729
					imsg_compose(ibuf, IMSG_NETWORK_REMOVE,
1730
					     0, 0, -1, &net, sizeof(net));
1731
			}
1732
			free(lbuf);
1733
		}
1734
		fclose(f);
1735
	} else {
1736
		err(1, "Failed to open stdin\n");
1737
	}
1738
}
1739
1740
void
1741
show_mrt_dump(struct mrt_rib *mr, struct mrt_peer *mp, void *arg)
1742
{
1743
	struct ctl_show_rib		 ctl;
1744
	struct ctl_show_rib_request	*req = arg;
1745
	struct mrt_rib_entry		*mre;
1746
	u_int16_t			 i, j;
1747
1748
	for (i = 0; i < mr->nentries; i++) {
1749
		mre = &mr->entries[i];
1750
		bzero(&ctl, sizeof(ctl));
1751
		mrt_to_bgpd_addr(&mr->prefix, &ctl.prefix);
1752
		ctl.prefixlen = mr->prefixlen;
1753
		ctl.lastchange = mre->originated;
1754
		mrt_to_bgpd_addr(&mre->nexthop, &ctl.true_nexthop);
1755
		mrt_to_bgpd_addr(&mre->nexthop, &ctl.exit_nexthop);
1756
		ctl.origin = mre->origin;
1757
		ctl.local_pref = mre->local_pref;
1758
		ctl.med = mre->med;
1759
		/* weight is not part of the mrt dump so it can't be set */
1760
		ctl.aspath_len = mre->aspath_len;
1761
1762
		if (mre->peer_idx < mp->npeers) {
1763
			mrt_to_bgpd_addr(&mp->peers[mre->peer_idx].addr,
1764
			    &ctl.remote_addr);
1765
			ctl.remote_id = mp->peers[mre->peer_idx].bgp_id;
1766
		}
1767
1768
		/* filter by neighbor */
1769
		if (req->neighbor.addr.aid != AID_UNSPEC &&
1770
		    memcmp(&req->neighbor.addr, &ctl.remote_addr,
1771
		    sizeof(ctl.remote_addr)) != 0)
1772
			continue;
1773
		/* filter by AF */
1774
		if (req->aid && req->aid != ctl.prefix.aid)
1775
			return;
1776
		/* filter by prefix */
1777
		if (req->prefix.aid != AID_UNSPEC) {
1778
			if (!prefix_compare(&req->prefix, &ctl.prefix,
1779
			    req->prefixlen)) {
1780
				if (req->flags & F_LONGER) {
1781
					if (req->prefixlen > ctl.prefixlen)
1782
						return;
1783
				} else if (req->prefixlen != ctl.prefixlen)
1784
					return;
1785
			} else
1786
				return;
1787
		}
1788
		/* filter by AS */
1789
		if (req->as.type != AS_NONE &&
1790
		   !aspath_match(mre->aspath, mre->aspath_len,
1791
		   &req->as, req->as.as))
1792
			continue;
1793
1794
		if (req->flags & F_CTL_DETAIL) {
1795
			show_rib_detail(&ctl, mre->aspath, 1);
1796
			for (j = 0; j < mre->nattrs; j++)
1797
				show_attr(mre->attrs[j].attr,
1798
					mre->attrs[j].attr_len);
1799
		} else
1800
			show_rib_brief(&ctl, mre->aspath);
1801
	}
1802
}
1803
1804
void
1805
network_mrt_dump(struct mrt_rib *mr, struct mrt_peer *mp, void *arg)
1806
{
1807
	struct ctl_show_rib		 ctl;
1808
	struct network_config		 net;
1809
	struct ctl_show_rib_request	*req = arg;
1810
	struct mrt_rib_entry		*mre;
1811
	struct ibuf			*msg;
1812
	u_int16_t			 i, j;
1813
1814
	for (i = 0; i < mr->nentries; i++) {
1815
		mre = &mr->entries[i];
1816
		bzero(&ctl, sizeof(ctl));
1817
		mrt_to_bgpd_addr(&mr->prefix, &ctl.prefix);
1818
		ctl.prefixlen = mr->prefixlen;
1819
		ctl.lastchange = mre->originated;
1820
		mrt_to_bgpd_addr(&mre->nexthop, &ctl.true_nexthop);
1821
		mrt_to_bgpd_addr(&mre->nexthop, &ctl.exit_nexthop);
1822
		ctl.origin = mre->origin;
1823
		ctl.local_pref = mre->local_pref;
1824
		ctl.med = mre->med;
1825
		ctl.aspath_len = mre->aspath_len;
1826
1827
		if (mre->peer_idx < mp->npeers) {
1828
			mrt_to_bgpd_addr(&mp->peers[mre->peer_idx].addr,
1829
			    &ctl.remote_addr);
1830
			ctl.remote_id = mp->peers[mre->peer_idx].bgp_id;
1831
		}
1832
1833
		/* filter by neighbor */
1834
		if (req->neighbor.addr.aid != AID_UNSPEC &&
1835
		    memcmp(&req->neighbor.addr, &ctl.remote_addr,
1836
		    sizeof(ctl.remote_addr)) != 0)
1837
			continue;
1838
		/* filter by AF */
1839
		if (req->aid && req->aid != ctl.prefix.aid)
1840
			return;
1841
		/* filter by prefix */
1842
		if (req->prefix.aid != AID_UNSPEC) {
1843
			if (!prefix_compare(&req->prefix, &ctl.prefix,
1844
			    req->prefixlen)) {
1845
				if (req->flags & F_LONGER) {
1846
					if (req->prefixlen > ctl.prefixlen)
1847
						return;
1848
				} else if (req->prefixlen != ctl.prefixlen)
1849
					return;
1850
			} else
1851
				return;
1852
		}
1853
		/* filter by AS */
1854
		if (req->as.type != AS_NONE &&
1855
		   !aspath_match(mre->aspath, mre->aspath_len,
1856
		   &req->as, req->as.as))
1857
			continue;
1858
1859
		bzero(&net, sizeof(net));
1860
		memcpy(&net.prefix, &ctl.prefix, sizeof(net.prefix));
1861
		net.prefixlen = ctl.prefixlen;
1862
		net.type = NETWORK_MRTCLONE;
1863
		/* XXX rtableid */
1864
1865
		imsg_compose(ibuf, IMSG_NETWORK_ADD, 0, 0, -1,
1866
		    &net, sizeof(net));
1867
		if ((msg = imsg_create(ibuf, IMSG_NETWORK_ASPATH,
1868
		    0, 0, sizeof(ctl) + mre->aspath_len)) == NULL)
1869
			errx(1, "imsg_create failure");
1870
		if (imsg_add(msg, &ctl, sizeof(ctl)) == -1 ||
1871
		    imsg_add(msg, mre->aspath, mre->aspath_len) == -1)
1872
			errx(1, "imsg_add failure");
1873
		imsg_close(ibuf, msg);
1874
		for (j = 0; j < mre->nattrs; j++)
1875
			imsg_compose(ibuf, IMSG_NETWORK_ATTR, 0, 0, -1,
1876
			    mre->attrs[j].attr, mre->attrs[j].attr_len);
1877
		imsg_compose(ibuf, IMSG_NETWORK_DONE, 0, 0, -1, NULL, 0);
1878
1879
		while (ibuf->w.queued) {
1880
			if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
1881
				err(1, "write error");
1882
		}
1883
	}
1884
}
1885
1886
void
1887
show_mrt_state(struct mrt_bgp_state *ms, void *arg)
1888
{
1889
	struct bgpd_addr src, dst;
1890
1891
	mrt_to_bgpd_addr(&ms->src, &src);
1892
	mrt_to_bgpd_addr(&ms->dst, &dst);
1893
	printf("%s[%u] -> ", log_addr(&src), ms->src_as);
1894
	printf("%s[%u]: %s -> %s\n", log_addr(&dst), ms->dst_as,
1895
	    statenames[ms->old_state], statenames[ms->new_state]);
1896
}
1897
1898
void
1899
show_mrt_msg(struct mrt_bgp_msg *mm, void *arg)
1900
{
1901
	struct bgpd_addr src, dst;
1902
1903
	mrt_to_bgpd_addr(&mm->src, &src);
1904
	mrt_to_bgpd_addr(&mm->dst, &dst);
1905
	printf("%s[%u] -> ", log_addr(&src), mm->src_as);
1906
	printf("%s[%u]: size %u\n", log_addr(&dst), mm->dst_as, mm->msg_len);
1907
}
1908
1909
void
1910
mrt_to_bgpd_addr(union mrt_addr *ma, struct bgpd_addr *ba)
1911
{
1912
	switch (ma->sa.sa_family) {
1913
	case AF_INET:
1914
	case AF_INET6:
1915
		sa2addr(&ma->sa, ba);
1916
		break;
1917
	case AF_VPNv4:
1918
		bzero(ba, sizeof(*ba));
1919
		ba->aid = AID_VPN_IPv4;
1920
		ba->vpn4.rd = ma->svpn4.sv_rd;
1921
		ba->vpn4.addr.s_addr = ma->svpn4.sv_addr.s_addr;
1922
		memcpy(ba->vpn4.labelstack, ma->svpn4.sv_label,
1923
		    sizeof(ba->vpn4.labelstack));
1924
		break;
1925
	}
1926
}
1927
1928
const char *
1929
msg_type(u_int8_t type)
1930
{
1931
	if (type >= sizeof(msgtypenames)/sizeof(msgtypenames[0]))
1932
		return "BAD";
1933
	return (msgtypenames[type]);
1934
}
1935
1936
/* following functions are necessary for the imsg framework */
1937
void
1938
log_warnx(const char *emsg, ...)
1939
{
1940
	va_list	 ap;
1941
1942
	va_start(ap, emsg);
1943
	vwarnx(emsg, ap);
1944
	va_end(ap);
1945
}
1946
1947
void
1948
log_warn(const char *emsg, ...)
1949
{
1950
	va_list	 ap;
1951
1952
	va_start(ap, emsg);
1953
	vwarn(emsg, ap);
1954
	va_end(ap);
1955
}
1956
1957
void
1958
fatal(const char *emsg, ...)
1959
{
1960
	va_list	 ap;
1961
1962
	va_start(ap, emsg);
1963
	verr(1, emsg, ap);
1964
	va_end(ap);
1965
}
1966
1967
void
1968
fatalx(const char *emsg)
1969
{
1970
	errx(1, "%s", emsg);
1971
}