GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ospf6ctl/ospf6ctl.c Lines: 0 694 0.0 %
Date: 2017-11-07 Branches: 0 339 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: ospf6ctl.c,v 1.46 2017/08/12 22:09:54 benno Exp $ */
2
3
/*
4
 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
5
 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
6
 * Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
7
 *
8
 * Permission to use, copy, modify, and distribute this software for any
9
 * purpose with or without fee is hereby granted, provided that the above
10
 * copyright notice and this permission notice appear in all copies.
11
 *
12
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
 */
20
21
#include <sys/types.h>
22
#include <sys/socket.h>
23
#include <sys/un.h>
24
#include <netinet/in.h>
25
#include <arpa/inet.h>
26
#include <net/if_media.h>
27
#include <net/if_types.h>
28
29
#include <err.h>
30
#include <errno.h>
31
#include <stdio.h>
32
#include <stdlib.h>
33
#include <string.h>
34
#include <unistd.h>
35
36
#include "ospf6.h"
37
#include "ospf6d.h"
38
#include "ospfe.h"
39
#include "parser.h"
40
#include "log.h"
41
42
__dead void	 usage(void);
43
int		 show_summary_msg(struct imsg *);
44
uint64_t	 get_ifms_type(uint8_t);
45
int		 show_interface_msg(struct imsg *);
46
int		 show_interface_detail_msg(struct imsg *);
47
const char	*print_link(int);
48
const char	*fmt_timeframe(time_t t);
49
const char	*fmt_timeframe_core(time_t t);
50
const char	*log_id(u_int32_t );
51
const char	*log_adv_rtr(u_int32_t);
52
void		 show_database_head(struct in_addr, char *, u_int16_t);
53
int		 show_database_msg(struct imsg *);
54
char		*print_ls_type(u_int16_t);
55
void		 show_db_hdr_msg_detail(struct lsa_hdr *);
56
char		*print_rtr_link_type(u_int8_t);
57
const char	*print_ospf_flags(u_int8_t);
58
const char	*print_asext_flags(u_int32_t);
59
const char	*print_prefix_opt(u_int8_t);
60
int		 show_db_msg_detail(struct imsg *imsg);
61
int		 show_nbr_msg(struct imsg *);
62
const char	*print_ospf_options(u_int32_t);
63
int		 show_nbr_detail_msg(struct imsg *);
64
int		 show_rib_msg(struct imsg *);
65
void		 show_rib_head(struct in_addr, u_int8_t, u_int8_t);
66
const char	*print_ospf_rtr_flags(u_int8_t);
67
int		 show_rib_detail_msg(struct imsg *);
68
void		 show_fib_head(void);
69
int		 show_fib_msg(struct imsg *);
70
const char *	 get_media_descr(uint64_t);
71
const char *	 get_linkstate(uint8_t, int);
72
void		 print_baudrate(u_int64_t);
73
74
struct imsgbuf	*ibuf;
75
76
__dead void
77
usage(void)
78
{
79
	extern char *__progname;
80
81
	fprintf(stderr, "usage: %s [-s socket] command [argument ...]\n",
82
	    __progname);
83
	exit(1);
84
}
85
86
int
87
main(int argc, char *argv[])
88
{
89
	struct sockaddr_un	 sun;
90
	struct parse_result	*res;
91
	struct imsg		 imsg;
92
	unsigned int		 ifidx = 0;
93
	int			 ctl_sock;
94
	int			 done = 0, verbose = 0;
95
	int			 n;
96
	int			 ch;
97
	char			*sockname;
98
99
	sockname = OSPF6D_SOCKET;
100
	while ((ch = getopt(argc, argv, "s:")) != -1) {
101
		switch (ch) {
102
		case 's':
103
			sockname = optarg;
104
			break;
105
		default:
106
			usage();
107
			/* NOTREACHED */
108
		}
109
	}
110
	argc -= optind;
111
	argv += optind;
112
113
	/* parse options */
114
	if ((res = parse(argc, argv)) == NULL)
115
		exit(1);
116
117
	/* connect to ospf6d control socket */
118
	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
119
		err(1, "socket");
120
121
	bzero(&sun, sizeof(sun));
122
	sun.sun_family = AF_UNIX;
123
	strlcpy(sun.sun_path, sockname, sizeof(sun.sun_path));
124
	if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1)
125
		err(1, "connect: %s", sockname);
126
127
	if (pledge("stdio flock rpath cpath wpath", NULL) == -1)
128
		err(1, "pledge");
129
130
	if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
131
		err(1, NULL);
132
	imsg_init(ibuf, ctl_sock);
133
	done = 0;
134
135
	/* process user request */
136
	switch (res->action) {
137
	case NONE:
138
		usage();
139
		/* not reached */
140
	case SHOW:
141
	case SHOW_SUM:
142
		imsg_compose(ibuf, IMSG_CTL_SHOW_SUM, 0, 0, -1, NULL, 0);
143
		break;
144
	case SHOW_IFACE:
145
		printf("%-11s %-29s %-6s %-10s %-10s %-8s\n",
146
		    "Interface", "Address", "State", "HelloTimer", "Linkstate",
147
		    "Uptime");
148
		/*FALLTHROUGH*/
149
	case SHOW_IFACE_DTAIL:
150
		if (*res->ifname) {
151
			ifidx = if_nametoindex(res->ifname);
152
			if (ifidx == 0)
153
				errx(1, "no such interface %s", res->ifname);
154
		}
155
		imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1,
156
		    &ifidx, sizeof(ifidx));
157
		break;
158
	case SHOW_NBR:
159
		printf("%-15s %-3s %-12s %-9s %-11s %s\n", "ID", "Pri",
160
		    "State", "DeadTime", "Iface","Uptime");
161
		/*FALLTHROUGH*/
162
	case SHOW_NBR_DTAIL:
163
		imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0);
164
		break;
165
	case SHOW_DB:
166
		imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1, NULL, 0);
167
		break;
168
	case SHOW_DBBYAREA:
169
		imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1,
170
		    &res->addr, sizeof(res->addr));
171
		break;
172
	case SHOW_DBEXT:
173
		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_EXT, 0, 0, -1, NULL, 0);
174
		break;
175
	case SHOW_DBLINK:
176
		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_LINK, 0, 0, -1, NULL, 0);
177
		break;
178
	case SHOW_DBNET:
179
		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_NET, 0, 0, -1, NULL, 0);
180
		break;
181
	case SHOW_DBRTR:
182
		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_RTR, 0, 0, -1, NULL, 0);
183
		break;
184
	case SHOW_DBINTRA:
185
		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_INTRA, 0, 0, -1, NULL, 0);
186
		break;
187
	case SHOW_DBSELF:
188
		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SELF, 0, 0, -1, NULL, 0);
189
		break;
190
	case SHOW_DBSUM:
191
		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SUM, 0, 0, -1, NULL, 0);
192
		break;
193
	case SHOW_DBASBR:
194
		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_ASBR, 0, 0, -1, NULL, 0);
195
		break;
196
	case SHOW_RIB:
197
		printf("%-20s %-17s %-12s %-9s %-7s %-8s\n", "Destination",
198
		    "Nexthop", "Path Type", "Type", "Cost", "Uptime");
199
		/*FALLTHROUGH*/
200
	case SHOW_RIB_DTAIL:
201
		imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, -1, NULL, 0);
202
		break;
203
	case SHOW_FIB:
204
		if (IN6_IS_ADDR_UNSPECIFIED(&res->addr))
205
			imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0, -1,
206
			    &res->flags, sizeof(res->flags));
207
		else
208
			imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1,
209
			    &res->addr, sizeof(res->addr));
210
		show_fib_head();
211
		break;
212
	case FIB:
213
		errx(1, "fib couple|decouple");
214
		break;
215
	case FIB_COUPLE:
216
		imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, -1, NULL, 0);
217
		printf("couple request sent.\n");
218
		done = 1;
219
		break;
220
	case FIB_DECOUPLE:
221
		imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, -1, NULL, 0);
222
		printf("decouple request sent.\n");
223
		done = 1;
224
		break;
225
	case LOG_VERBOSE:
226
		verbose = 1;
227
		/* FALLTHROUGH */
228
	case LOG_BRIEF:
229
		imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1,
230
		    &verbose, sizeof(verbose));
231
		printf("logging request sent.\n");
232
		done = 1;
233
		break;
234
	case RELOAD:
235
		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0);
236
		printf("reload request sent.\n");
237
		done = 1;
238
		break;
239
	}
240
241
	while (ibuf->w.queued)
242
		if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
243
			err(1, "write error");
244
245
	while (!done) {
246
		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
247
			errx(1, "imsg_read error");
248
		if (n == 0)
249
			errx(1, "pipe closed");
250
251
		while (!done) {
252
			if ((n = imsg_get(ibuf, &imsg)) == -1)
253
				errx(1, "imsg_get error");
254
			if (n == 0)
255
				break;
256
			switch (res->action) {
257
			case SHOW:
258
			case SHOW_SUM:
259
				done = show_summary_msg(&imsg);
260
				break;
261
			case SHOW_IFACE:
262
				done = show_interface_msg(&imsg);
263
				break;
264
			case SHOW_IFACE_DTAIL:
265
				done = show_interface_detail_msg(&imsg);
266
				break;
267
			case SHOW_NBR:
268
				done = show_nbr_msg(&imsg);
269
				break;
270
			case SHOW_NBR_DTAIL:
271
				done = show_nbr_detail_msg(&imsg);
272
				break;
273
			case SHOW_DB:
274
			case SHOW_DBBYAREA:
275
			case SHOW_DBSELF:
276
				done = show_database_msg(&imsg);
277
				break;
278
			case SHOW_DBEXT:
279
			case SHOW_DBLINK:
280
			case SHOW_DBNET:
281
			case SHOW_DBRTR:
282
			case SHOW_DBINTRA:
283
			case SHOW_DBSUM:
284
			case SHOW_DBASBR:
285
				done = show_db_msg_detail(&imsg);
286
				break;
287
			case SHOW_RIB:
288
				done = show_rib_msg(&imsg);
289
				break;
290
			case SHOW_RIB_DTAIL:
291
				done = show_rib_detail_msg(&imsg);
292
				break;
293
			case SHOW_FIB:
294
				done = show_fib_msg(&imsg);
295
				break;
296
			case NONE:
297
			case FIB:
298
			case FIB_COUPLE:
299
			case FIB_DECOUPLE:
300
			case LOG_VERBOSE:
301
			case LOG_BRIEF:
302
			case RELOAD:
303
				break;
304
			}
305
			imsg_free(&imsg);
306
		}
307
	}
308
	close(ctl_sock);
309
	free(ibuf);
310
311
	return (0);
312
}
313
314
int
315
show_summary_msg(struct imsg *imsg)
316
{
317
	struct ctl_sum		*sum;
318
	struct ctl_sum_area	*sumarea;
319
320
	switch (imsg->hdr.type) {
321
	case IMSG_CTL_SHOW_SUM:
322
		sum = imsg->data;
323
		printf("Router ID: %s\n", inet_ntoa(sum->rtr_id));
324
		printf("Uptime: %s\n", fmt_timeframe_core(sum->uptime));
325
326
		printf("SPF delay is %d sec(s), hold time between two SPFs "
327
		    "is %d sec(s)\n", sum->spf_delay, sum->spf_hold_time);
328
		printf("Number of external LSA(s) %d\n", sum->num_ext_lsa);
329
		printf("Number of areas attached to this router: %d\n",
330
		    sum->num_area);
331
		break;
332
	case IMSG_CTL_SHOW_SUM_AREA:
333
		sumarea = imsg->data;
334
		printf("\nArea ID: %s\n", inet_ntoa(sumarea->area));
335
		printf("  Number of interfaces in this area: %d\n",
336
		    sumarea->num_iface);
337
		printf("  Number of fully adjacent neighbors in this "
338
		    "area: %d\n", sumarea->num_adj_nbr);
339
		printf("  SPF algorithm executed %d time(s)\n",
340
		    sumarea->num_spf_calc);
341
		printf("  Number LSA(s) %d\n", sumarea->num_lsa);
342
		break;
343
	case IMSG_CTL_END:
344
		printf("\n");
345
		return (1);
346
	default:
347
		break;
348
	}
349
350
	return (0);
351
}
352
353
uint64_t
354
get_ifms_type(uint8_t if_type)
355
{
356
	switch (if_type) {
357
	case IFT_ETHER:
358
		return (IFM_ETHER);
359
	case IFT_FDDI:
360
		return (IFM_FDDI);
361
	case IFT_CARP:
362
		return (IFM_CARP);
363
	case IFT_PPP:
364
		return (IFM_TDM);
365
	default:
366
		return (0);
367
	}
368
}
369
370
int
371
show_interface_msg(struct imsg *imsg)
372
{
373
	struct ctl_iface	*iface;
374
	char			*netid;
375
376
	switch (imsg->hdr.type) {
377
	case IMSG_CTL_SHOW_INTERFACE:
378
		iface = imsg->data;
379
380
		if (asprintf(&netid, "%s", log_in6addr(&iface->addr)) == -1)
381
			err(1, NULL);
382
		printf("%-11s %-29s %-6s %-10s %-10s %s\n",
383
		    iface->name, netid, if_state_name(iface->state),
384
		    fmt_timeframe_core(iface->hello_timer),
385
		    get_linkstate(iface->if_type, iface->linkstate),
386
		    fmt_timeframe_core(iface->uptime));
387
		free(netid);
388
		break;
389
	case IMSG_CTL_END:
390
		printf("\n");
391
		return (1);
392
	default:
393
		break;
394
	}
395
396
	return (0);
397
}
398
399
int
400
show_interface_detail_msg(struct imsg *imsg)
401
{
402
	struct ctl_iface	*iface;
403
404
	switch (imsg->hdr.type) {
405
	case IMSG_CTL_SHOW_INTERFACE:
406
		iface = imsg->data;
407
		printf("\n");
408
		printf("Interface %s, line protocol is %s\n",
409
		    iface->name, print_link(iface->flags));
410
		printf("  Internet address %s Area %s\n",
411
		    log_in6addr(&iface->addr), inet_ntoa(iface->area));
412
		printf("  Link type %s, state %s, mtu %d",
413
		    get_media_descr(get_ifms_type(iface->if_type)),
414
		    get_linkstate(iface->if_type, iface->linkstate),
415
		    iface->mtu);
416
		if (iface->linkstate != LINK_STATE_DOWN &&
417
		    iface->baudrate > 0) {
418
		    printf(", ");
419
		    print_baudrate(iface->baudrate);
420
		}
421
		printf("\n");
422
		printf("  Router ID %s, network type %s, cost: %d\n",
423
		    inet_ntoa(iface->rtr_id),
424
		    if_type_name(iface->type), iface->metric);
425
		printf("  Transmit delay is %d sec(s), state %s, priority %d\n",
426
		    iface->transmit_delay, if_state_name(iface->state),
427
		    iface->priority);
428
		printf("  Designated Router (ID) %s\n",
429
		    inet_ntoa(iface->dr_id));
430
		printf("    Interface address %s\n",
431
		    log_in6addr(&iface->dr_addr));
432
		printf("  Backup Designated Router (ID) %s\n",
433
		    inet_ntoa(iface->bdr_id));
434
		printf("    Interface address %s\n",
435
		    log_in6addr(&iface->bdr_addr));
436
		printf("  Timer intervals configured, "
437
		    "hello %d, dead %d, wait %d, retransmit %d\n",
438
		     iface->hello_interval, iface->dead_interval,
439
		     iface->dead_interval, iface->rxmt_interval);
440
		if (iface->passive)
441
			printf("    Passive interface (No Hellos)\n");
442
		else if (iface->hello_timer < 0)
443
			printf("    Hello timer not running\n");
444
		else
445
			printf("    Hello timer due in %s\n",
446
			    fmt_timeframe_core(iface->hello_timer));
447
		printf("    Uptime %s\n", fmt_timeframe_core(iface->uptime));
448
		printf("  Neighbor count is %d, adjacent neighbor count is "
449
		    "%d\n", iface->nbr_cnt, iface->adj_cnt);
450
		break;
451
	case IMSG_CTL_END:
452
		printf("\n");
453
		return (1);
454
	default:
455
		break;
456
	}
457
458
	return (0);
459
}
460
461
const char *
462
print_link(int state)
463
{
464
	if (state & IFF_UP)
465
		return ("UP");
466
	else
467
		return ("DOWN");
468
}
469
470
#define TF_BUFS	8
471
#define TF_LEN	9
472
473
const char *
474
fmt_timeframe(time_t t)
475
{
476
	if (t == 0)
477
		return ("Never");
478
	else
479
		return (fmt_timeframe_core(time(NULL) - t));
480
}
481
482
const char *
483
fmt_timeframe_core(time_t t)
484
{
485
	char		*buf;
486
	static char	 tfbuf[TF_BUFS][TF_LEN];	/* ring buffer */
487
	static int	 idx = 0;
488
	unsigned int	 sec, min, hrs, day, week;
489
490
	if (t == 0)
491
		return ("00:00:00");
492
493
	buf = tfbuf[idx++];
494
	if (idx == TF_BUFS)
495
		idx = 0;
496
497
	week = t;
498
499
	sec = week % 60;
500
	week /= 60;
501
	min = week % 60;
502
	week /= 60;
503
	hrs = week % 24;
504
	week /= 24;
505
	day = week % 7;
506
	week /= 7;
507
508
	if (week > 0)
509
		snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs);
510
	else if (day > 0)
511
		snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
512
	else
513
		snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
514
515
	return (buf);
516
}
517
518
const char *
519
log_id(u_int32_t id)
520
{
521
	static char	buf[48];
522
	struct in_addr	addr;
523
524
	addr.s_addr = id;
525
526
	if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL)
527
		return ("?");
528
	else
529
		return (buf);
530
}
531
532
const char *
533
log_adv_rtr(u_int32_t adv_rtr)
534
{
535
	static char	buf[48];
536
	struct in_addr	addr;
537
538
	addr.s_addr = adv_rtr;
539
540
	if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL)
541
		return ("?");
542
	else
543
		return (buf);
544
}
545
546
void
547
show_database_head(struct in_addr aid, char *ifname, u_int16_t type)
548
{
549
	char	*header, *format;
550
	int	cleanup = 0;
551
552
	switch (ntohs(type)) {
553
	case LSA_TYPE_LINK:
554
		format = "Link (Type-8) Link States";
555
		break;
556
	case LSA_TYPE_ROUTER:
557
		format = "Router Link States";
558
		break;
559
	case LSA_TYPE_NETWORK:
560
		format = "Net Link States";
561
		break;
562
	case LSA_TYPE_INTER_A_PREFIX:
563
		format = "Inter Area Prefix Link States";
564
		break;
565
	case LSA_TYPE_INTER_A_ROUTER:
566
		format = "Inter Area Router Link States";
567
		break;
568
	case LSA_TYPE_INTRA_A_PREFIX:
569
		format = "Intra Area Prefix Link States";
570
		break;
571
	case LSA_TYPE_EXTERNAL:
572
		printf("\n%-15s %s\n\n", "", "Type-5 AS External Link States");
573
		return;
574
	default:
575
		if (asprintf(&format, "LSA type %x", ntohs(type)) == -1)
576
			err(1, NULL);
577
		cleanup = 1;
578
		break;
579
	}
580
	if (LSA_IS_SCOPE_AREA(ntohs(type))) {
581
		if (asprintf(&header, "%s (Area %s)", format,
582
		    inet_ntoa(aid)) == -1)
583
			err(1, NULL);
584
	} else if (LSA_IS_SCOPE_LLOCAL(ntohs(type))) {
585
		if (asprintf(&header, "%s (Area %s Interface %s)", format,
586
		    inet_ntoa(aid), ifname) == -1)
587
			err(1, NULL);
588
	} else {
589
		if (asprintf(&header, "%s", format) == -1)
590
			err(1, NULL);
591
	}
592
593
	printf("\n%-15s %s\n\n", "", header);
594
	free(header);
595
	if (cleanup)
596
		free(format);
597
}
598
599
int
600
show_database_msg(struct imsg *imsg)
601
{
602
	static struct in_addr	 area_id;
603
	static char		 ifname[IF_NAMESIZE];
604
	static u_int16_t	 lasttype;
605
	struct area		*area;
606
	struct iface		*iface;
607
	struct lsa_hdr		*lsa;
608
609
	switch (imsg->hdr.type) {
610
	case IMSG_CTL_SHOW_DATABASE:
611
	case IMSG_CTL_SHOW_DB_SELF:
612
		lsa = imsg->data;
613
		if (lsa->type != lasttype) {
614
			show_database_head(area_id, ifname, lsa->type);
615
			printf("%-15s %-15s %-4s %-10s %-8s\n", "Link ID",
616
			    "Adv Router", "Age", "Seq#", "Checksum");
617
		}
618
		printf("%-15s %-15s %-4d 0x%08x 0x%04x\n",
619
		    log_id(lsa->ls_id), log_adv_rtr(lsa->adv_rtr),
620
		    ntohs(lsa->age), ntohl(lsa->seq_num),
621
		    ntohs(lsa->ls_chksum));
622
		lasttype = lsa->type;
623
		break;
624
	case IMSG_CTL_AREA:
625
		area = imsg->data;
626
		area_id = area->id;
627
		lasttype = 0;
628
		break;
629
	case IMSG_CTL_IFACE:
630
		iface = imsg->data;
631
		strlcpy(ifname, iface->name, sizeof(ifname));
632
		lasttype = 0;
633
		break;
634
	case IMSG_CTL_END:
635
		printf("\n");
636
		return (1);
637
	default:
638
		break;
639
	}
640
641
	return (0);
642
}
643
644
char *
645
print_ls_type(u_int16_t type)
646
{
647
	switch (ntohs(type)) {
648
	case LSA_TYPE_LINK:
649
		return ("Link");
650
	case LSA_TYPE_ROUTER:
651
		return ("Router");
652
	case LSA_TYPE_NETWORK:
653
		return ("Network");
654
	case LSA_TYPE_INTER_A_PREFIX:
655
		return ("Inter Area (Prefix)");
656
	case LSA_TYPE_INTER_A_ROUTER:
657
		return ("Inter Area (Router)");
658
	case LSA_TYPE_INTRA_A_PREFIX:
659
		return ("Intra Area (Prefix)");
660
	case LSA_TYPE_EXTERNAL:
661
		return ("AS External");
662
	default:
663
		return ("Unknown");
664
	}
665
}
666
667
void
668
show_db_hdr_msg_detail(struct lsa_hdr *lsa)
669
{
670
	printf("LS age: %d\n", ntohs(lsa->age));
671
	printf("LS Type: %s\n", print_ls_type(lsa->type));
672
673
	switch (ntohs(lsa->type)) {
674
	case LSA_TYPE_ROUTER:
675
	case LSA_TYPE_INTER_A_PREFIX:
676
	case LSA_TYPE_INTER_A_ROUTER:
677
	case LSA_TYPE_INTRA_A_PREFIX:
678
	case LSA_TYPE_EXTERNAL:
679
		printf("Link State ID: %s\n", log_id(lsa->ls_id));
680
		break;
681
	case LSA_TYPE_LINK:
682
		printf("Link State ID: %s (Interface ID of Advertising "
683
		    "Router)\n", log_id(lsa->ls_id));
684
		break;
685
	case LSA_TYPE_NETWORK:
686
		printf("Link State ID: %s (Interface ID of Designated "
687
		    "Router)\n", log_id(lsa->ls_id));
688
		break;
689
	}
690
691
	printf("Advertising Router: %s\n", log_adv_rtr(lsa->adv_rtr));
692
	printf("LS Seq Number: 0x%08x\n", ntohl(lsa->seq_num));
693
	printf("Checksum: 0x%04x\n", ntohs(lsa->ls_chksum));
694
	printf("Length: %d\n", ntohs(lsa->len));
695
}
696
697
char *
698
print_rtr_link_type(u_int8_t type)
699
{
700
	switch (type) {
701
	case LINK_TYPE_POINTTOPOINT:
702
		return ("Point-to-Point");
703
	case LINK_TYPE_TRANSIT_NET:
704
		return ("Transit Network");
705
	case LINK_TYPE_RESERVED:
706
		return ("Reserved");
707
	case LINK_TYPE_VIRTUAL:
708
		return ("Virtual Link");
709
	default:
710
		return ("Unknown");
711
	}
712
}
713
714
const char *
715
print_ospf_flags(u_int8_t opts)
716
{
717
	static char	optbuf[32];
718
719
	snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s",
720
	    opts & OSPF_RTR_V ? "V" : "-",
721
	    opts & OSPF_RTR_E ? "E" : "-",
722
	    opts & OSPF_RTR_B ? "B" : "-");
723
	return (optbuf);
724
}
725
726
const char *
727
print_asext_flags(u_int32_t opts)
728
{
729
	static char	optbuf[32];
730
731
	snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s",
732
	    opts & LSA_ASEXT_E_FLAG ? "E" : "-",
733
	    opts & LSA_ASEXT_F_FLAG ? "F" : "-",
734
	    opts & LSA_ASEXT_T_FLAG ? "T" : "-");
735
	return (optbuf);
736
}
737
738
const char *
739
print_prefix_opt(u_int8_t opts)
740
{
741
	static char	optbuf[32];
742
743
	if (opts) {
744
		snprintf(optbuf, sizeof(optbuf),
745
		    " Options: *|*|*|%s|%s|x|%s|%s",
746
		    opts & OSPF_PREFIX_DN ? "DN" : "-",
747
		    opts & OSPF_PREFIX_P ? "P" : "-",
748
		    opts & OSPF_PREFIX_LA ? "LA" : "-",
749
		    opts & OSPF_PREFIX_NU ? "NU" : "-");
750
		return (optbuf);
751
	}
752
	return ("");
753
}
754
755
int
756
show_db_msg_detail(struct imsg *imsg)
757
{
758
	static struct in_addr	 area_id;
759
	static char		 ifname[IF_NAMESIZE];
760
	static u_int16_t	 lasttype;
761
	struct in6_addr		 ia6;
762
	struct in_addr		 addr, data;
763
	struct area		*area;
764
	struct iface		*iface;
765
	struct lsa		*lsa;
766
	struct lsa_rtr_link	*rtr_link;
767
	struct lsa_net_link	*net_link;
768
	struct lsa_prefix	*prefix;
769
	struct lsa_asext	*asext;
770
	u_int32_t		 ext_tag;
771
	u_int16_t		 i, nlinks, off;
772
773
	/* XXX sanity checks! */
774
775
	switch (imsg->hdr.type) {
776
	case IMSG_CTL_SHOW_DB_EXT:
777
		lsa = imsg->data;
778
		if (lsa->hdr.type != lasttype)
779
			show_database_head(area_id, ifname, lsa->hdr.type);
780
		show_db_hdr_msg_detail(&lsa->hdr);
781
782
		asext = (struct lsa_asext *)((char *)lsa + sizeof(lsa->hdr));
783
784
		printf("    Flags: %s\n",
785
		    print_asext_flags(ntohl(lsa->data.asext.metric)));
786
		printf("    Metric: %d Type: ", ntohl(asext->metric)
787
		    & LSA_METRIC_MASK);
788
		if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_E_FLAG)
789
			printf("2\n");
790
		else
791
			printf("1\n");
792
793
		prefix = &asext->prefix;
794
		bzero(&ia6, sizeof(ia6));
795
		bcopy(prefix + 1, &ia6, LSA_PREFIXSIZE(prefix->prefixlen));
796
		printf("    Prefix: %s/%d%s\n", log_in6addr(&ia6),
797
		    prefix->prefixlen, print_prefix_opt(prefix->options));
798
799
		off = sizeof(*asext) + LSA_PREFIXSIZE(prefix->prefixlen);
800
		if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_F_FLAG) {
801
			bcopy((char *)asext + off, &ia6, sizeof(ia6));
802
			printf("    Forwarding Address: %s\n",
803
			    log_in6addr(&ia6));
804
			off += sizeof(ia6);
805
		}
806
		if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_T_FLAG) {
807
			bcopy((char *)asext + off, &ext_tag, sizeof(ext_tag));
808
			printf("    External Route Tag: %d\n", ntohl(ext_tag));
809
		}
810
		printf("\n");
811
		lasttype = lsa->hdr.type;
812
		break;
813
	case IMSG_CTL_SHOW_DB_LINK:
814
		lsa = imsg->data;
815
		if (lsa->hdr.type != lasttype)
816
			show_database_head(area_id, ifname, lsa->hdr.type);
817
		show_db_hdr_msg_detail(&lsa->hdr);
818
		printf("Options: %s\n", print_ospf_options(LSA_24_GETLO(
819
		    ntohl(lsa->data.link.opts))));
820
		printf("Link Local Address: %s\n",
821
		    log_in6addr(&lsa->data.link.lladdr));
822
823
		nlinks = ntohl(lsa->data.link.numprefix);
824
		printf("Number of Prefixes: %d\n", nlinks);
825
		off = sizeof(lsa->hdr) + sizeof(struct lsa_link);
826
827
		for (i = 0; i < nlinks; i++) {
828
			prefix = (struct lsa_prefix *)((char *)lsa + off);
829
			bzero(&ia6, sizeof(ia6));
830
			bcopy(prefix + 1, &ia6,
831
			    LSA_PREFIXSIZE(prefix->prefixlen));
832
833
			printf("    Prefix: %s/%d%s\n", log_in6addr(&ia6),
834
			    prefix->prefixlen,
835
			    print_prefix_opt(prefix->options));
836
837
			off += sizeof(struct lsa_prefix)
838
			    + LSA_PREFIXSIZE(prefix->prefixlen);
839
		}
840
841
		printf("\n");
842
		lasttype = lsa->hdr.type;
843
		break;
844
	case IMSG_CTL_SHOW_DB_NET:
845
		lsa = imsg->data;
846
		if (lsa->hdr.type != lasttype)
847
			show_database_head(area_id, ifname, lsa->hdr.type);
848
		show_db_hdr_msg_detail(&lsa->hdr);
849
		printf("Options: %s\n",
850
		    print_ospf_options(LSA_24_GETLO(ntohl(lsa->data.net.opts))));
851
852
		nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr) -
853
		    sizeof(struct lsa_net)) / sizeof(struct lsa_net_link);
854
		net_link = (struct lsa_net_link *)((char *)lsa +
855
		    sizeof(lsa->hdr) + sizeof(lsa->data.net));
856
		printf("Number of Routers: %d\n", nlinks);
857
858
		for (i = 0; i < nlinks; i++) {
859
			addr.s_addr = net_link->att_rtr;
860
			printf("    Attached Router: %s\n", inet_ntoa(addr));
861
			net_link++;
862
		}
863
864
		printf("\n");
865
		lasttype = lsa->hdr.type;
866
		break;
867
	case IMSG_CTL_SHOW_DB_RTR:
868
		lsa = imsg->data;
869
		if (lsa->hdr.type != lasttype)
870
			show_database_head(area_id, ifname, lsa->hdr.type);
871
		show_db_hdr_msg_detail(&lsa->hdr);
872
		printf("Flags: %s\n",
873
		    print_ospf_flags(LSA_24_GETHI(ntohl(lsa->data.rtr.opts))));
874
		printf("Options: %s\n",
875
		    print_ospf_options(LSA_24_GETLO(ntohl(lsa->data.rtr.opts))));
876
877
		nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr)
878
		    - sizeof(u_int32_t)) / sizeof(struct lsa_rtr_link);
879
		printf("Number of Links: %d\n\n", nlinks);
880
881
		off = sizeof(lsa->hdr) + sizeof(struct lsa_rtr);
882
883
		for (i = 0; i < nlinks; i++) {
884
			rtr_link = (struct lsa_rtr_link *)((char *)lsa + off);
885
886
			printf("    Link (Interface ID %s) connected to: %s\n",
887
			    log_id(rtr_link->iface_id),
888
			    print_rtr_link_type(rtr_link->type));
889
890
			addr.s_addr = rtr_link->nbr_rtr_id;
891
			data.s_addr = rtr_link->nbr_iface_id;
892
893
			switch (rtr_link->type) {
894
			case LINK_TYPE_POINTTOPOINT:
895
			case LINK_TYPE_VIRTUAL:
896
				printf("    Router ID: %s\n", inet_ntoa(addr));
897
				printf("    Interface ID: %s\n",
898
				    inet_ntoa(data));
899
				break;
900
			case LINK_TYPE_TRANSIT_NET:
901
				printf("    Designated Router ID: %s\n",
902
				    inet_ntoa(addr));
903
				printf("    DR Interface ID: %s\n",
904
				    inet_ntoa(data));
905
				break;
906
			default:
907
				printf("    Link ID (Unknown type %d): %s\n",
908
				    rtr_link->type, inet_ntoa(addr));
909
				printf("    Link Data (Unknown): %s\n",
910
				    inet_ntoa(data));
911
				break;
912
			}
913
914
			printf("    Metric: %d\n\n", ntohs(rtr_link->metric));
915
916
			off += sizeof(struct lsa_rtr_link);
917
		}
918
919
		lasttype = lsa->hdr.type;
920
		break;
921
	case IMSG_CTL_SHOW_DB_INTRA:
922
		lsa = imsg->data;
923
		if (lsa->hdr.type != lasttype)
924
			show_database_head(area_id, ifname, lsa->hdr.type);
925
		show_db_hdr_msg_detail(&lsa->hdr);
926
		printf("Referenced LS Type: %s\n",
927
		    print_ls_type(lsa->data.pref_intra.ref_type));
928
		addr.s_addr = lsa->data.pref_intra.ref_ls_id;
929
		printf("Referenced Link State ID: %s\n", inet_ntoa(addr));
930
		addr.s_addr = lsa->data.pref_intra.ref_adv_rtr;
931
		printf("Referenced Advertising Router: %s\n", inet_ntoa(addr));
932
		nlinks = ntohs(lsa->data.pref_intra.numprefix);
933
		printf("Number of Prefixes: %d\n", nlinks);
934
935
		off = sizeof(lsa->hdr) + sizeof(struct lsa_intra_prefix);
936
937
		for (i = 0; i < nlinks; i++) {
938
			prefix = (struct lsa_prefix *)((char *)lsa + off);
939
			bzero(&ia6, sizeof(ia6));
940
			bcopy(prefix + 1, &ia6,
941
			    LSA_PREFIXSIZE(prefix->prefixlen));
942
943
			printf("    Prefix: %s/%d%s\n", log_in6addr(&ia6),
944
			    prefix->prefixlen,
945
			    print_prefix_opt(prefix->options));
946
947
			off += sizeof(struct lsa_prefix)
948
			    + LSA_PREFIXSIZE(prefix->prefixlen);
949
		}
950
951
		printf("\n");
952
		lasttype = lsa->hdr.type;
953
		break;
954
	case IMSG_CTL_SHOW_DB_SUM:
955
		lsa = imsg->data;
956
		if (lsa->hdr.type != lasttype)
957
			show_database_head(area_id, ifname, lsa->hdr.type);
958
		show_db_hdr_msg_detail(&lsa->hdr);
959
		printf("Prefix: XXX\n");
960
		printf("Metric: %d\n", ntohl(lsa->data.pref_sum.metric) &
961
		    LSA_METRIC_MASK);
962
		lasttype = lsa->hdr.type;
963
		break;
964
	case IMSG_CTL_SHOW_DB_ASBR:
965
		lsa = imsg->data;
966
		if (lsa->hdr.type != lasttype)
967
			show_database_head(area_id, ifname, lsa->hdr.type);
968
		show_db_hdr_msg_detail(&lsa->hdr);
969
970
		addr.s_addr = lsa->data.rtr_sum.dest_rtr_id;
971
		printf("Destination Router ID: %s\n", inet_ntoa(addr));
972
		printf("Options: %s\n",
973
		    print_ospf_options(ntohl(lsa->data.rtr_sum.opts)));
974
		printf("Metric: %d\n\n", ntohl(lsa->data.rtr_sum.metric) &
975
		    LSA_METRIC_MASK);
976
	case IMSG_CTL_AREA:
977
		area = imsg->data;
978
		area_id = area->id;
979
		lasttype = 0;
980
		break;
981
	case IMSG_CTL_IFACE:
982
		iface = imsg->data;
983
		strlcpy(ifname, iface->name, sizeof(ifname));
984
		lasttype = 0;
985
		break;
986
	case IMSG_CTL_END:
987
		return (1);
988
	default:
989
		break;
990
	}
991
992
	return (0);
993
}
994
995
int
996
show_nbr_msg(struct imsg *imsg)
997
{
998
	struct ctl_nbr	*nbr;
999
	char		*state;
1000
1001
	switch (imsg->hdr.type) {
1002
	case IMSG_CTL_SHOW_NBR:
1003
		nbr = imsg->data;
1004
		if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state),
1005
		    if_state_name(nbr->iface_state)) == -1)
1006
			err(1, NULL);
1007
		printf("%-15s %-3d %-12s %-10s", inet_ntoa(nbr->id),
1008
		    nbr->priority, state, fmt_timeframe_core(nbr->dead_timer));
1009
		printf("%-11s %s\n", nbr->name,
1010
		    nbr->uptime == 0 ? "-" : fmt_timeframe_core(nbr->uptime));
1011
		free(state);
1012
		break;
1013
	case IMSG_CTL_END:
1014
		printf("\n");
1015
		return (1);
1016
	default:
1017
		break;
1018
	}
1019
1020
	return (0);
1021
}
1022
1023
const char *
1024
print_ospf_options(u_int32_t opts)
1025
{
1026
	static char	optbuf[32];
1027
1028
	snprintf(optbuf, sizeof(optbuf), "*|*|%s|%s|%s|*|%s|%s",
1029
	    opts & OSPF_OPTION_DC ? "DC" : "-",
1030
	    opts & OSPF_OPTION_R ? "R" : "-",
1031
	    opts & OSPF_OPTION_N ? "N" : "-",
1032
	    opts & OSPF_OPTION_E ? "E" : "-",
1033
	    opts & OSPF_OPTION_V6 ? "V6" : "-");
1034
	return (optbuf);
1035
}
1036
1037
int
1038
show_nbr_detail_msg(struct imsg *imsg)
1039
{
1040
	struct ctl_nbr	*nbr;
1041
1042
	switch (imsg->hdr.type) {
1043
	case IMSG_CTL_SHOW_NBR:
1044
		nbr = imsg->data;
1045
		printf("\nNeighbor %s, ", inet_ntoa(nbr->id));
1046
		printf("interface address %s\n", log_in6addr(&nbr->addr));
1047
		printf("  Area %s, interface %s\n", inet_ntoa(nbr->area),
1048
		    nbr->name);
1049
		printf("  Neighbor priority is %d, "
1050
		    "State is %s, %d state changes\n",
1051
		    nbr->priority, nbr_state_name(nbr->nbr_state),
1052
		    nbr->state_chng_cnt);
1053
		printf("  DR is %s, ", inet_ntoa(nbr->dr));
1054
		printf("BDR is %s\n", inet_ntoa(nbr->bdr));
1055
		printf("  Options %s\n", print_ospf_options(nbr->options));
1056
		printf("  Dead timer due in %s\n",
1057
		    fmt_timeframe_core(nbr->dead_timer));
1058
		printf("  Uptime %s\n", fmt_timeframe_core(nbr->uptime));
1059
		printf("  Database Summary List %d\n", nbr->db_sum_lst_cnt);
1060
		printf("  Link State Request List %d\n", nbr->ls_req_lst_cnt);
1061
		printf("  Link State Retransmission List %d\n",
1062
		    nbr->ls_retrans_lst_cnt);
1063
		break;
1064
	case IMSG_CTL_END:
1065
		printf("\n");
1066
		return (1);
1067
	default:
1068
		break;
1069
	}
1070
1071
	return (0);
1072
}
1073
1074
int
1075
show_rib_msg(struct imsg *imsg)
1076
{
1077
	struct ctl_rt	*rt;
1078
	char		*dstnet;
1079
1080
	switch (imsg->hdr.type) {
1081
	case IMSG_CTL_SHOW_RIB:
1082
		rt = imsg->data;
1083
		switch (rt->d_type) {
1084
		case DT_NET:
1085
			if (asprintf(&dstnet, "%s/%d", log_in6addr(&rt->prefix),
1086
			    rt->prefixlen) == -1)
1087
				err(1, NULL);
1088
			break;
1089
		case DT_RTR:
1090
			if (asprintf(&dstnet, "%s",
1091
			    log_in6addr(&rt->prefix)) == -1)
1092
				err(1, NULL);
1093
			break;
1094
		default:
1095
			errx(1, "Invalid route type");
1096
		}
1097
1098
		printf("%-20s %-17s %-12s %-9s %-7d %s\n", dstnet,
1099
		    log_in6addr_scope(&rt->nexthop, rt->ifindex),
1100
		    path_type_name(rt->p_type), dst_type_name(rt->d_type),
1101
		    rt->cost,
1102
		    rt->uptime == 0 ? "-" : fmt_timeframe_core(rt->uptime));
1103
		free(dstnet);
1104
		break;
1105
	case IMSG_CTL_END:
1106
		printf("\n");
1107
		return (1);
1108
	default:
1109
		break;
1110
	}
1111
1112
	return (0);
1113
}
1114
1115
void
1116
show_rib_head(struct in_addr aid, u_int8_t d_type, u_int8_t p_type)
1117
{
1118
	char	*header, *format, *format2;
1119
1120
	switch (p_type) {
1121
	case PT_INTRA_AREA:
1122
	case PT_INTER_AREA:
1123
		switch (d_type) {
1124
		case DT_NET:
1125
			format = "Network Routing Table";
1126
			format2 = "";
1127
			break;
1128
		case DT_RTR:
1129
			format = "Router Routing Table";
1130
			format2 = "Type";
1131
			break;
1132
		default:
1133
			errx(1, "unknown route type");
1134
		}
1135
		break;
1136
	case PT_TYPE1_EXT:
1137
	case PT_TYPE2_EXT:
1138
		format = NULL;
1139
		format2 = "Cost 2";
1140
		if ((header = strdup("External Routing Table")) == NULL)
1141
			err(1, NULL);
1142
		break;
1143
	default:
1144
		errx(1, "unknown route type");
1145
	}
1146
1147
	if (p_type != PT_TYPE1_EXT && p_type != PT_TYPE2_EXT)
1148
		if (asprintf(&header, "%s (Area %s)", format,
1149
		    inet_ntoa(aid)) == -1)
1150
			err(1, NULL);
1151
1152
	printf("\n%-18s %s\n", "", header);
1153
	free(header);
1154
1155
	printf("\n%-18s %-15s %-15s %-12s %-7s %-7s\n", "Destination",
1156
	    "Nexthop", "Adv Router", "Path type", "Cost", format2);
1157
}
1158
1159
const char *
1160
print_ospf_rtr_flags(u_int8_t opts)
1161
{
1162
	static char	optbuf[32];
1163
1164
	snprintf(optbuf, sizeof(optbuf), "%s%s%s",
1165
	    opts & OSPF_RTR_E ? "AS" : "",
1166
	    opts & OSPF_RTR_E && opts & OSPF_RTR_B ? "+" : "",
1167
	    opts & OSPF_RTR_B ? "ABR" : "");
1168
	return (optbuf);
1169
}
1170
1171
int
1172
show_rib_detail_msg(struct imsg *imsg)
1173
{
1174
	static struct in_addr	 area_id;
1175
	struct ctl_rt		*rt;
1176
	struct area		*area;
1177
	char			*dstnet;
1178
	static u_int8_t		 lasttype;
1179
1180
	switch (imsg->hdr.type) {
1181
	case IMSG_CTL_SHOW_RIB:
1182
		rt = imsg->data;
1183
1184
		switch (rt->p_type) {
1185
		case PT_INTRA_AREA:
1186
		case PT_INTER_AREA:
1187
			switch (rt->d_type) {
1188
			case DT_NET:
1189
				if (lasttype != RIB_NET)
1190
					show_rib_head(rt->area, rt->d_type,
1191
					     rt->p_type);
1192
				if (asprintf(&dstnet, "%s/%d",
1193
				    log_in6addr(&rt->prefix),
1194
				    rt->prefixlen) == -1)
1195
					err(1, NULL);
1196
				lasttype = RIB_NET;
1197
				break;
1198
			case DT_RTR:
1199
				if (lasttype != RIB_RTR)
1200
					show_rib_head(rt->area, rt->d_type,
1201
					     rt->p_type);
1202
				if (asprintf(&dstnet, "%s",
1203
				    log_in6addr(&rt->prefix)) == -1)
1204
					err(1, NULL);
1205
				lasttype = RIB_RTR;
1206
				break;
1207
			default:
1208
				errx(1, "unknown route type");
1209
			}
1210
			printf("%-18s %-15s ", dstnet,
1211
			    log_in6addr_scope(&rt->nexthop, rt->ifindex));
1212
			printf("%-15s %-12s %-7d", inet_ntoa(rt->adv_rtr),
1213
			    path_type_name(rt->p_type), rt->cost);
1214
			free(dstnet);
1215
1216
			if (rt->d_type == DT_RTR)
1217
				printf(" %-7s",
1218
				    print_ospf_rtr_flags(rt->flags));
1219
1220
			printf("\n");
1221
			break;
1222
		case PT_TYPE1_EXT:
1223
		case PT_TYPE2_EXT:
1224
			if (lasttype != RIB_EXT)
1225
				show_rib_head(rt->area, rt->d_type, rt->p_type);
1226
1227
			if (asprintf(&dstnet, "%s/%d",
1228
			    log_in6addr(&rt->prefix), rt->prefixlen) == -1)
1229
				err(1, NULL);
1230
1231
			printf("%-18s %-15s ", dstnet,
1232
			    log_in6addr_scope(&rt->nexthop, rt->ifindex));
1233
			printf("%-15s %-12s %-7d %-7d\n",
1234
			    inet_ntoa(rt->adv_rtr), path_type_name(rt->p_type),
1235
			    rt->cost, rt->cost2);
1236
			free(dstnet);
1237
1238
			lasttype = RIB_EXT;
1239
			break;
1240
		default:
1241
			errx(1, "unknown route type");
1242
		}
1243
		break;
1244
	case IMSG_CTL_AREA:
1245
		area = imsg->data;
1246
		area_id = area->id;
1247
		break;
1248
	case IMSG_CTL_END:
1249
		printf("\n");
1250
		return (1);
1251
	default:
1252
		break;
1253
	}
1254
1255
	return (0);
1256
}
1257
1258
void
1259
show_fib_head(void)
1260
{
1261
	printf("flags: * = valid, O = OSPF, C = Connected, S = Static\n");
1262
	printf("%-6s %-4s %-20s %-17s\n",
1263
	    "Flags", "Prio", "Destination", "Nexthop");
1264
}
1265
1266
int
1267
show_fib_msg(struct imsg *imsg)
1268
{
1269
	struct kroute		*k;
1270
	char			*p;
1271
1272
	switch (imsg->hdr.type) {
1273
	case IMSG_CTL_KROUTE:
1274
		if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute))
1275
			errx(1, "wrong imsg len");
1276
		k = imsg->data;
1277
1278
		if (k->flags & F_DOWN)
1279
			printf(" ");
1280
		else
1281
			printf("*");
1282
1283
		if (!(k->flags & F_KERNEL))
1284
			printf("O");
1285
		else if (k->flags & F_CONNECTED)
1286
			printf("C");
1287
		else if (k->flags & F_STATIC)
1288
			printf("S");
1289
		else
1290
			printf(" ");
1291
1292
		printf("     ");
1293
		printf("%4d ", k->priority);
1294
		if (asprintf(&p, "%s/%u", log_in6addr(&k->prefix),
1295
		    k->prefixlen) == -1)
1296
			err(1, NULL);
1297
		printf("%-20s ", p);
1298
		free(p);
1299
1300
		if (!IN6_IS_ADDR_UNSPECIFIED(&k->nexthop))
1301
			printf("%s", log_in6addr_scope(&k->nexthop, k->scope));
1302
		else if (k->flags & F_CONNECTED)
1303
			printf("link#%u", k->ifindex);
1304
		printf("\n");
1305
1306
		break;
1307
	case IMSG_CTL_END:
1308
		printf("\n");
1309
		return (1);
1310
	default:
1311
		break;
1312
	}
1313
1314
	return (0);
1315
}
1316
1317
const struct if_status_description
1318
		if_status_descriptions[] = LINK_STATE_DESCRIPTIONS;
1319
const struct ifmedia_description
1320
		ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS;
1321
1322
const char *
1323
get_media_descr(uint64_t media_type)
1324
{
1325
	const struct ifmedia_description	*p;
1326
1327
	for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++)
1328
		if (media_type == p->ifmt_word)
1329
			return (p->ifmt_string);
1330
1331
	return ("unknown");
1332
}
1333
1334
const char *
1335
get_linkstate(uint8_t if_type, int link_state)
1336
{
1337
	const struct if_status_description *p;
1338
	static char buf[8];
1339
1340
	for (p = if_status_descriptions; p->ifs_string != NULL; p++) {
1341
		if (LINK_STATE_DESC_MATCH(p, if_type, link_state))
1342
			return (p->ifs_string);
1343
	}
1344
	snprintf(buf, sizeof(buf), "[#%d]", link_state);
1345
	return (buf);
1346
}
1347
1348
void
1349
print_baudrate(u_int64_t baudrate)
1350
{
1351
	if (baudrate > IF_Gbps(1))
1352
		printf("%llu GBit/s", baudrate / IF_Gbps(1));
1353
	else if (baudrate > IF_Mbps(1))
1354
		printf("%llu MBit/s", baudrate / IF_Mbps(1));
1355
	else if (baudrate > IF_Kbps(1))
1356
		printf("%llu KBit/s", baudrate / IF_Kbps(1));
1357
	else
1358
		printf("%llu Bit/s", baudrate);
1359
}