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