xref: /openbsd-src/usr.sbin/ospf6ctl/ospf6ctl.c (revision 6c6408334dbede3a2c0dcd9ff9c489157df0c856)
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", 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 }
1364