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

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