xref: /openbsd/usr.sbin/ospf6ctl/ospf6ctl.c (revision 1aff836d)
1*1aff836dSclaudio /*	$OpenBSD: ospf6ctl.c,v 1.34 2010/02/25 16:40:23 claudio Exp $ */
28e709cbdSnorby 
38e709cbdSnorby /*
48e709cbdSnorby  * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
58e709cbdSnorby  * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
68e709cbdSnorby  * Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
78e709cbdSnorby  *
88e709cbdSnorby  * Permission to use, copy, modify, and distribute this software for any
98e709cbdSnorby  * purpose with or without fee is hereby granted, provided that the above
108e709cbdSnorby  * copyright notice and this permission notice appear in all copies.
118e709cbdSnorby  *
128e709cbdSnorby  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
138e709cbdSnorby  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
148e709cbdSnorby  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
158e709cbdSnorby  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
168e709cbdSnorby  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
178e709cbdSnorby  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
188e709cbdSnorby  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
198e709cbdSnorby  */
208e709cbdSnorby 
218e709cbdSnorby #include <sys/types.h>
228e709cbdSnorby #include <sys/socket.h>
238e709cbdSnorby #include <sys/un.h>
248e709cbdSnorby #include <netinet/in.h>
258e709cbdSnorby #include <arpa/inet.h>
268e709cbdSnorby #include <net/if_media.h>
278e709cbdSnorby #include <net/if_types.h>
288e709cbdSnorby 
298e709cbdSnorby #include <err.h>
308e709cbdSnorby #include <stdio.h>
318e709cbdSnorby #include <stdlib.h>
328e709cbdSnorby #include <string.h>
338e709cbdSnorby #include <unistd.h>
348e709cbdSnorby 
358e709cbdSnorby #include "ospf6.h"
368e709cbdSnorby #include "ospf6d.h"
378e709cbdSnorby #include "ospfe.h"
388e709cbdSnorby #include "parser.h"
398e709cbdSnorby #include "log.h"
408e709cbdSnorby 
418e709cbdSnorby __dead void	 usage(void);
428e709cbdSnorby int		 show_summary_msg(struct imsg *);
438e709cbdSnorby int		 get_ifms_type(int);
448e709cbdSnorby int		 show_interface_msg(struct imsg *);
458e709cbdSnorby int		 show_interface_detail_msg(struct imsg *);
468e709cbdSnorby const char	*print_link(int);
478e709cbdSnorby const char	*fmt_timeframe(time_t t);
488e709cbdSnorby const char	*fmt_timeframe_core(time_t t);
498e709cbdSnorby const char	*log_id(u_int32_t );
508e709cbdSnorby const char	*log_adv_rtr(u_int32_t);
51cb01fa27Sclaudio void		 show_database_head(struct in_addr, char *, u_int16_t);
528e709cbdSnorby int		 show_database_msg(struct imsg *);
534fabe8f9Snorby char		*print_ls_type(u_int16_t);
548e709cbdSnorby void		 show_db_hdr_msg_detail(struct lsa_hdr *);
558e709cbdSnorby char		*print_rtr_link_type(u_int8_t);
568e709cbdSnorby const char	*print_ospf_flags(u_int8_t);
57*1aff836dSclaudio const char	*print_asext_flags(u_int32_t);
58*1aff836dSclaudio const char	*print_prefix_opt(u_int8_t);
598e709cbdSnorby int		 show_db_msg_detail(struct imsg *imsg);
608e709cbdSnorby int		 show_nbr_msg(struct imsg *);
61aff6ccb8Sclaudio const char	*print_ospf_options(u_int32_t);
628e709cbdSnorby int		 show_nbr_detail_msg(struct imsg *);
638e709cbdSnorby int		 show_rib_msg(struct imsg *);
648e709cbdSnorby void		 show_rib_head(struct in_addr, u_int8_t, u_int8_t);
658e709cbdSnorby const char	*print_ospf_rtr_flags(u_int8_t);
668e709cbdSnorby int		 show_rib_detail_msg(struct imsg *);
678e709cbdSnorby void		 show_fib_head(void);
688e709cbdSnorby int		 show_fib_msg(struct imsg *);
698e709cbdSnorby const char *	 get_media_descr(int);
708e709cbdSnorby const char *	 get_linkstate(int, int);
718e709cbdSnorby void		 print_baudrate(u_int64_t);
728e709cbdSnorby 
738e709cbdSnorby struct imsgbuf	*ibuf;
748e709cbdSnorby 
758e709cbdSnorby __dead void
768e709cbdSnorby usage(void)
778e709cbdSnorby {
788e709cbdSnorby 	extern char *__progname;
798e709cbdSnorby 
805ff7227cSsobrado 	fprintf(stderr, "usage: %s command [argument ...]\n", __progname);
818e709cbdSnorby 	exit(1);
828e709cbdSnorby }
838e709cbdSnorby 
848e709cbdSnorby int
858e709cbdSnorby main(int argc, char *argv[])
868e709cbdSnorby {
878e709cbdSnorby 	struct sockaddr_un	 sun;
888e709cbdSnorby 	struct parse_result	*res;
898e709cbdSnorby 	struct imsg		 imsg;
908e709cbdSnorby 	unsigned int		 ifidx = 0;
918e709cbdSnorby 	int			 ctl_sock;
92c3319070Sclaudio 	int			 done = 0, verbose = 0;
938e709cbdSnorby 	int			 n;
948e709cbdSnorby 
958e709cbdSnorby 	/* parse options */
968e709cbdSnorby 	if ((res = parse(argc - 1, argv + 1)) == NULL)
978e709cbdSnorby 		exit(1);
988e709cbdSnorby 
998e709cbdSnorby 	/* connect to ospf6d control socket */
1008e709cbdSnorby 	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
1018e709cbdSnorby 		err(1, "socket");
1028e709cbdSnorby 
1038e709cbdSnorby 	bzero(&sun, sizeof(sun));
1048e709cbdSnorby 	sun.sun_family = AF_UNIX;
1058e709cbdSnorby 	strlcpy(sun.sun_path, OSPF6D_SOCKET, sizeof(sun.sun_path));
1068e709cbdSnorby 	if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1)
1078e709cbdSnorby 		err(1, "connect: %s", OSPF6D_SOCKET);
1088e709cbdSnorby 
1098e709cbdSnorby 	if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
1108e709cbdSnorby 		err(1, NULL);
111f78850efSeric 	imsg_init(ibuf, ctl_sock);
1128e709cbdSnorby 	done = 0;
1138e709cbdSnorby 
1148e709cbdSnorby 	/* process user request */
1158e709cbdSnorby 	switch (res->action) {
1168e709cbdSnorby 	case NONE:
1178e709cbdSnorby 		usage();
1188e709cbdSnorby 		/* not reached */
1198e709cbdSnorby 	case SHOW:
1208e709cbdSnorby 	case SHOW_SUM:
121f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_SUM, 0, 0, -1, NULL, 0);
1228e709cbdSnorby 		break;
1238e709cbdSnorby 	case SHOW_IFACE:
1241fed8bffSnorby 		printf("%-11s %-29s %-6s %-10s %-10s %-8s\n",
1258e709cbdSnorby 		    "Interface", "Address", "State", "HelloTimer", "Linkstate",
1261fed8bffSnorby 		    "Uptime");
127c5ba8b41Sderaadt 		/*FALLTHROUGH*/
1288e709cbdSnorby 	case SHOW_IFACE_DTAIL:
1298e709cbdSnorby 		if (*res->ifname) {
1308e709cbdSnorby 			ifidx = if_nametoindex(res->ifname);
1318e709cbdSnorby 			if (ifidx == 0)
1328e709cbdSnorby 				errx(1, "no such interface %s", res->ifname);
1338e709cbdSnorby 		}
134f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1,
1358e709cbdSnorby 		    &ifidx, sizeof(ifidx));
1368e709cbdSnorby 		break;
1378e709cbdSnorby 	case SHOW_NBR:
138558ada41Snorby 		printf("%-15s %-3s %-12s %-9s %-11s %s\n", "ID", "Pri",
139558ada41Snorby 		    "State", "DeadTime", "Iface","Uptime");
140c5ba8b41Sderaadt 		/*FALLTHROUGH*/
1418e709cbdSnorby 	case SHOW_NBR_DTAIL:
142f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0);
1438e709cbdSnorby 		break;
1448e709cbdSnorby 	case SHOW_DB:
145f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1, NULL, 0);
1468e709cbdSnorby 		break;
1478e709cbdSnorby 	case SHOW_DBBYAREA:
148f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1,
1498e709cbdSnorby 		    &res->addr, sizeof(res->addr));
1508e709cbdSnorby 		break;
1518e709cbdSnorby 	case SHOW_DBEXT:
152f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_EXT, 0, 0, -1, NULL, 0);
1538e709cbdSnorby 		break;
154aeb06b08Sclaudio 	case SHOW_DBLINK:
155f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_LINK, 0, 0, -1, NULL, 0);
156aeb06b08Sclaudio 		break;
1578e709cbdSnorby 	case SHOW_DBNET:
158f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_NET, 0, 0, -1, NULL, 0);
1598e709cbdSnorby 		break;
1608e709cbdSnorby 	case SHOW_DBRTR:
161f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_RTR, 0, 0, -1, NULL, 0);
1628e709cbdSnorby 		break;
16341bcac6bSstsp 	case SHOW_DBINTRA:
164f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_INTRA, 0, 0, -1, NULL, 0);
16541bcac6bSstsp 		break;
1668e709cbdSnorby 	case SHOW_DBSELF:
167f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SELF, 0, 0, -1, NULL, 0);
1688e709cbdSnorby 		break;
1698e709cbdSnorby 	case SHOW_DBSUM:
170f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SUM, 0, 0, -1, NULL, 0);
1718e709cbdSnorby 		break;
1728e709cbdSnorby 	case SHOW_DBASBR:
173f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_ASBR, 0, 0, -1, NULL, 0);
1748e709cbdSnorby 		break;
1758e709cbdSnorby 	case SHOW_RIB:
1768e709cbdSnorby 		printf("%-20s %-17s %-12s %-9s %-7s %-8s\n", "Destination",
1778e709cbdSnorby 		    "Nexthop", "Path Type", "Type", "Cost", "Uptime");
178c5ba8b41Sderaadt 		/*FALLTHROUGH*/
1798e709cbdSnorby 	case SHOW_RIB_DTAIL:
180f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, -1, NULL, 0);
1818e709cbdSnorby 		break;
1828e709cbdSnorby 	case SHOW_FIB:
1830104e403Sclaudio 		if (IN6_IS_ADDR_UNSPECIFIED(&res->addr))
184f78850efSeric 			imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0, -1,
1858e709cbdSnorby 			    &res->flags, sizeof(res->flags));
1868e709cbdSnorby 		else
187f78850efSeric 			imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1,
1888e709cbdSnorby 			    &res->addr, sizeof(res->addr));
1898e709cbdSnorby 		show_fib_head();
1908e709cbdSnorby 		break;
1918e709cbdSnorby 	case FIB:
1928e709cbdSnorby 		errx(1, "fib couple|decouple");
1938e709cbdSnorby 		break;
1948e709cbdSnorby 	case FIB_COUPLE:
195f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, -1, NULL, 0);
1968e709cbdSnorby 		printf("couple request sent.\n");
1978e709cbdSnorby 		done = 1;
1988e709cbdSnorby 		break;
1998e709cbdSnorby 	case FIB_DECOUPLE:
200f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, -1, NULL, 0);
2018e709cbdSnorby 		printf("decouple request sent.\n");
2028e709cbdSnorby 		done = 1;
2038e709cbdSnorby 		break;
204c3319070Sclaudio 	case LOG_VERBOSE:
205c3319070Sclaudio 		verbose = 1;
206c3319070Sclaudio 		/* FALLTHROUGH */
207c3319070Sclaudio 	case LOG_BRIEF:
208c3319070Sclaudio 		imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1,
209c3319070Sclaudio 		    &verbose, sizeof(verbose));
210c3319070Sclaudio 		printf("logging request sent.\n");
211c3319070Sclaudio 		done = 1;
212c3319070Sclaudio 		break;
2138e709cbdSnorby 	case RELOAD:
214f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0);
2158e709cbdSnorby 		printf("reload request sent.\n");
2168e709cbdSnorby 		done = 1;
2178e709cbdSnorby 		break;
2188e709cbdSnorby 	}
2198e709cbdSnorby 
2208e709cbdSnorby 	while (ibuf->w.queued)
2218e709cbdSnorby 		if (msgbuf_write(&ibuf->w) < 0)
2228e709cbdSnorby 			err(1, "write error");
2238e709cbdSnorby 
2248e709cbdSnorby 	while (!done) {
2258e709cbdSnorby 		if ((n = imsg_read(ibuf)) == -1)
2268e709cbdSnorby 			errx(1, "imsg_read error");
2278e709cbdSnorby 		if (n == 0)
2288e709cbdSnorby 			errx(1, "pipe closed");
2298e709cbdSnorby 
2308e709cbdSnorby 		while (!done) {
2318e709cbdSnorby 			if ((n = imsg_get(ibuf, &imsg)) == -1)
2328e709cbdSnorby 				errx(1, "imsg_get error");
2338e709cbdSnorby 			if (n == 0)
2348e709cbdSnorby 				break;
2358e709cbdSnorby 			switch (res->action) {
2368e709cbdSnorby 			case SHOW:
2378e709cbdSnorby 			case SHOW_SUM:
2388e709cbdSnorby 				done = show_summary_msg(&imsg);
2398e709cbdSnorby 				break;
2408e709cbdSnorby 			case SHOW_IFACE:
2418e709cbdSnorby 				done = show_interface_msg(&imsg);
2428e709cbdSnorby 				break;
2438e709cbdSnorby 			case SHOW_IFACE_DTAIL:
2448e709cbdSnorby 				done = show_interface_detail_msg(&imsg);
2458e709cbdSnorby 				break;
2468e709cbdSnorby 			case SHOW_NBR:
2478e709cbdSnorby 				done = show_nbr_msg(&imsg);
2488e709cbdSnorby 				break;
2498e709cbdSnorby 			case SHOW_NBR_DTAIL:
2508e709cbdSnorby 				done = show_nbr_detail_msg(&imsg);
2518e709cbdSnorby 				break;
2528e709cbdSnorby 			case SHOW_DB:
2538e709cbdSnorby 			case SHOW_DBBYAREA:
2548e709cbdSnorby 			case SHOW_DBSELF:
2558e709cbdSnorby 				done = show_database_msg(&imsg);
2568e709cbdSnorby 				break;
2578e709cbdSnorby 			case SHOW_DBEXT:
258aeb06b08Sclaudio 			case SHOW_DBLINK:
2598e709cbdSnorby 			case SHOW_DBNET:
2608e709cbdSnorby 			case SHOW_DBRTR:
26141bcac6bSstsp 			case SHOW_DBINTRA:
2628e709cbdSnorby 			case SHOW_DBSUM:
2638e709cbdSnorby 			case SHOW_DBASBR:
2648e709cbdSnorby 				done = show_db_msg_detail(&imsg);
2658e709cbdSnorby 				break;
2668e709cbdSnorby 			case SHOW_RIB:
2678e709cbdSnorby 				done = show_rib_msg(&imsg);
2688e709cbdSnorby 				break;
2698e709cbdSnorby 			case SHOW_RIB_DTAIL:
2708e709cbdSnorby 				done = show_rib_detail_msg(&imsg);
2718e709cbdSnorby 				break;
2728e709cbdSnorby 			case SHOW_FIB:
2738e709cbdSnorby 				done = show_fib_msg(&imsg);
2748e709cbdSnorby 				break;
2758e709cbdSnorby 			case NONE:
2768e709cbdSnorby 			case FIB:
2778e709cbdSnorby 			case FIB_COUPLE:
2788e709cbdSnorby 			case FIB_DECOUPLE:
279c3319070Sclaudio 			case LOG_VERBOSE:
280c3319070Sclaudio 			case LOG_BRIEF:
2818e709cbdSnorby 			case RELOAD:
2828e709cbdSnorby 				break;
2838e709cbdSnorby 			}
2848e709cbdSnorby 			imsg_free(&imsg);
2858e709cbdSnorby 		}
2868e709cbdSnorby 	}
2878e709cbdSnorby 	close(ctl_sock);
2888e709cbdSnorby 	free(ibuf);
2898e709cbdSnorby 
2908e709cbdSnorby 	return (0);
2918e709cbdSnorby }
2928e709cbdSnorby 
2938e709cbdSnorby int
2948e709cbdSnorby show_summary_msg(struct imsg *imsg)
2958e709cbdSnorby {
2968e709cbdSnorby 	struct ctl_sum		*sum;
2978e709cbdSnorby 	struct ctl_sum_area	*sumarea;
2988e709cbdSnorby 
2998e709cbdSnorby 	switch (imsg->hdr.type) {
3008e709cbdSnorby 	case IMSG_CTL_SHOW_SUM:
3018e709cbdSnorby 		sum = imsg->data;
3028e709cbdSnorby 		printf("Router ID: %s\n", inet_ntoa(sum->rtr_id));
3038e709cbdSnorby 		printf("Uptime: %s\n", fmt_timeframe_core(sum->uptime));
3048e709cbdSnorby 
3058e709cbdSnorby 		printf("SPF delay is %d sec(s), hold time between two SPFs "
3068e709cbdSnorby 		    "is %d sec(s)\n", sum->spf_delay, sum->spf_hold_time);
3078e709cbdSnorby 		printf("Number of external LSA(s) %d\n", sum->num_ext_lsa);
3088e709cbdSnorby 		printf("Number of areas attached to this router: %d\n",
3098e709cbdSnorby 		    sum->num_area);
3108e709cbdSnorby 		break;
3118e709cbdSnorby 	case IMSG_CTL_SHOW_SUM_AREA:
3128e709cbdSnorby 		sumarea = imsg->data;
3138e709cbdSnorby 		printf("\nArea ID: %s\n", inet_ntoa(sumarea->area));
3148e709cbdSnorby 		printf("  Number of interfaces in this area: %d\n",
3158e709cbdSnorby 		    sumarea->num_iface);
3168e709cbdSnorby 		printf("  Number of fully adjacent neighbors in this "
3178e709cbdSnorby 		    "area: %d\n", sumarea->num_adj_nbr);
3188e709cbdSnorby 		printf("  SPF algorithm executed %d time(s)\n",
3198e709cbdSnorby 		    sumarea->num_spf_calc);
3208e709cbdSnorby 		printf("  Number LSA(s) %d\n", sumarea->num_lsa);
3218e709cbdSnorby 		break;
3228e709cbdSnorby 	case IMSG_CTL_END:
3238e709cbdSnorby 		printf("\n");
3248e709cbdSnorby 		return (1);
3258e709cbdSnorby 	default:
3268e709cbdSnorby 		break;
3278e709cbdSnorby 	}
3288e709cbdSnorby 
3298e709cbdSnorby 	return (0);
3308e709cbdSnorby }
3318e709cbdSnorby 
3328e709cbdSnorby int
3338e709cbdSnorby get_ifms_type(int mediatype)
3348e709cbdSnorby {
3358e709cbdSnorby 	switch (mediatype) {
3368e709cbdSnorby 	case IFT_ETHER:
3378e709cbdSnorby 		return (IFM_ETHER);
3388e709cbdSnorby 	case IFT_FDDI:
3398e709cbdSnorby 		return (IFM_FDDI);
3408e709cbdSnorby 	case IFT_CARP:
3418e709cbdSnorby 		return (IFM_CARP);
3428e709cbdSnorby 	case IFT_PPP:
3438e709cbdSnorby 		return (IFM_TDM);
3448e709cbdSnorby 	default:
3458e709cbdSnorby 		return (0);
3468e709cbdSnorby 	}
3478e709cbdSnorby }
3488e709cbdSnorby 
3498e709cbdSnorby int
3508e709cbdSnorby show_interface_msg(struct imsg *imsg)
3518e709cbdSnorby {
3528e709cbdSnorby 	struct ctl_iface	*iface;
3538e709cbdSnorby 	char			*netid;
3548e709cbdSnorby 
3558e709cbdSnorby 	switch (imsg->hdr.type) {
3568e709cbdSnorby 	case IMSG_CTL_SHOW_INTERFACE:
3578e709cbdSnorby 		iface = imsg->data;
3588e709cbdSnorby 
3598e709cbdSnorby 		if (asprintf(&netid, "%s", log_in6addr(&iface->addr)) == -1)
3608e709cbdSnorby 			err(1, NULL);
3611fed8bffSnorby 		printf("%-11s %-29s %-6s %-10s %-10s %s\n",
3628e709cbdSnorby 		    iface->name, netid, if_state_name(iface->state),
3638e709cbdSnorby 		    fmt_timeframe_core(iface->hello_timer),
3640f617141Sclaudio 		    get_linkstate(iface->mediatype, iface->linkstate),
3650f617141Sclaudio 		    fmt_timeframe_core(iface->uptime));
3668e709cbdSnorby 		free(netid);
3678e709cbdSnorby 		break;
3688e709cbdSnorby 	case IMSG_CTL_END:
3698e709cbdSnorby 		printf("\n");
3708e709cbdSnorby 		return (1);
3718e709cbdSnorby 	default:
3728e709cbdSnorby 		break;
3738e709cbdSnorby 	}
3748e709cbdSnorby 
3758e709cbdSnorby 	return (0);
3768e709cbdSnorby }
3778e709cbdSnorby 
3788e709cbdSnorby int
3798e709cbdSnorby show_interface_detail_msg(struct imsg *imsg)
3808e709cbdSnorby {
3818e709cbdSnorby 	struct ctl_iface	*iface;
3828e709cbdSnorby 
3838e709cbdSnorby 	switch (imsg->hdr.type) {
3848e709cbdSnorby 	case IMSG_CTL_SHOW_INTERFACE:
3858e709cbdSnorby 		iface = imsg->data;
3868e709cbdSnorby 		printf("\n");
3878e709cbdSnorby 		printf("Interface %s, line protocol is %s\n",
3888e709cbdSnorby 		    iface->name, print_link(iface->flags));
389ab5e4d03Sclaudio 		printf("  Internet address %s Area %s\n",
390ab5e4d03Sclaudio 		    log_in6addr(&iface->addr), inet_ntoa(iface->area));
391ab5e4d03Sclaudio 		printf("  Link type %s, state %s",
392ab5e4d03Sclaudio 		    get_media_descr(get_ifms_type(iface->mediatype)),
3930f617141Sclaudio 		    get_linkstate(iface->mediatype, iface->linkstate));
394ab5e4d03Sclaudio 		if (iface->linkstate != LINK_STATE_DOWN &&
395ab5e4d03Sclaudio 		    iface->baudrate > 0) {
396ab5e4d03Sclaudio 		    printf(", ");
397ab5e4d03Sclaudio 		    print_baudrate(iface->baudrate);
398ab5e4d03Sclaudio 		}
399ab5e4d03Sclaudio 		printf("\n");
4008e709cbdSnorby 		printf("  Router ID %s, network type %s, cost: %d\n",
4018e709cbdSnorby 		    inet_ntoa(iface->rtr_id),
4028e709cbdSnorby 		    if_type_name(iface->type), iface->metric);
4038e709cbdSnorby 		printf("  Transmit delay is %d sec(s), state %s, priority %d\n",
4048e709cbdSnorby 		    iface->transmit_delay, if_state_name(iface->state),
4058e709cbdSnorby 		    iface->priority);
4067aab4200Snorby 		printf("  Designated Router (ID) %s\n",
4078e709cbdSnorby 		    inet_ntoa(iface->dr_id));
4087aab4200Snorby 		printf("    Interface address %s\n",
4097aab4200Snorby 		    log_in6addr(&iface->dr_addr));
4107aab4200Snorby 		printf("  Backup Designated Router (ID) %s\n",
4118e709cbdSnorby 		    inet_ntoa(iface->bdr_id));
4127aab4200Snorby 		printf("    Interface address %s\n",
4137aab4200Snorby 		    log_in6addr(&iface->bdr_addr));
4148e709cbdSnorby 		printf("  Timer intervals configured, "
4158e709cbdSnorby 		    "hello %d, dead %d, wait %d, retransmit %d\n",
4168e709cbdSnorby 		     iface->hello_interval, iface->dead_interval,
4178e709cbdSnorby 		     iface->dead_interval, iface->rxmt_interval);
4188e709cbdSnorby 		if (iface->passive)
4198e709cbdSnorby 			printf("    Passive interface (No Hellos)\n");
4208e709cbdSnorby 		else if (iface->hello_timer < 0)
4218e709cbdSnorby 			printf("    Hello timer not running\n");
4228e709cbdSnorby 		else
4238e709cbdSnorby 			printf("    Hello timer due in %s\n",
4248e709cbdSnorby 			    fmt_timeframe_core(iface->hello_timer));
4258e709cbdSnorby 		printf("    Uptime %s\n", fmt_timeframe_core(iface->uptime));
4268e709cbdSnorby 		printf("  Neighbor count is %d, adjacent neighbor count is "
4278e709cbdSnorby 		    "%d\n", iface->nbr_cnt, iface->adj_cnt);
4288e709cbdSnorby 		break;
4298e709cbdSnorby 	case IMSG_CTL_END:
4308e709cbdSnorby 		printf("\n");
4318e709cbdSnorby 		return (1);
4328e709cbdSnorby 	default:
4338e709cbdSnorby 		break;
4348e709cbdSnorby 	}
4358e709cbdSnorby 
4368e709cbdSnorby 	return (0);
4378e709cbdSnorby }
4388e709cbdSnorby 
4398e709cbdSnorby const char *
4408e709cbdSnorby print_link(int state)
4418e709cbdSnorby {
4428e709cbdSnorby 	if (state & IFF_UP)
4438e709cbdSnorby 		return ("UP");
4448e709cbdSnorby 	else
4458e709cbdSnorby 		return ("DOWN");
4468e709cbdSnorby }
4478e709cbdSnorby 
4488e709cbdSnorby #define TF_BUFS	8
4498e709cbdSnorby #define TF_LEN	9
4508e709cbdSnorby 
4518e709cbdSnorby const char *
4528e709cbdSnorby fmt_timeframe(time_t t)
4538e709cbdSnorby {
4548e709cbdSnorby 	if (t == 0)
4558e709cbdSnorby 		return ("Never");
4568e709cbdSnorby 	else
4578e709cbdSnorby 		return (fmt_timeframe_core(time(NULL) - t));
4588e709cbdSnorby }
4598e709cbdSnorby 
4608e709cbdSnorby const char *
4618e709cbdSnorby fmt_timeframe_core(time_t t)
4628e709cbdSnorby {
4638e709cbdSnorby 	char		*buf;
4648e709cbdSnorby 	static char	 tfbuf[TF_BUFS][TF_LEN];	/* ring buffer */
4658e709cbdSnorby 	static int	 idx = 0;
466db93f2f1Sderaadt 	unsigned int	 sec, min, hrs, day, week;
4678e709cbdSnorby 
4688e709cbdSnorby 	if (t == 0)
4698e709cbdSnorby 		return ("00:00:00");
4708e709cbdSnorby 
4718e709cbdSnorby 	buf = tfbuf[idx++];
4728e709cbdSnorby 	if (idx == TF_BUFS)
4738e709cbdSnorby 		idx = 0;
4748e709cbdSnorby 
4758e709cbdSnorby 	week = t;
4768e709cbdSnorby 
4778e709cbdSnorby 	sec = week % 60;
4788e709cbdSnorby 	week /= 60;
4798e709cbdSnorby 	min = week % 60;
4808e709cbdSnorby 	week /= 60;
4818e709cbdSnorby 	hrs = week % 24;
4828e709cbdSnorby 	week /= 24;
4838e709cbdSnorby 	day = week % 7;
4848e709cbdSnorby 	week /= 7;
4858e709cbdSnorby 
4868e709cbdSnorby 	if (week > 0)
4878e709cbdSnorby 		snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs);
4888e709cbdSnorby 	else if (day > 0)
4898e709cbdSnorby 		snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
4908e709cbdSnorby 	else
4918e709cbdSnorby 		snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
4928e709cbdSnorby 
4938e709cbdSnorby 	return (buf);
4948e709cbdSnorby }
4958e709cbdSnorby 
4968e709cbdSnorby const char *
4978e709cbdSnorby log_id(u_int32_t id)
4988e709cbdSnorby {
4998e709cbdSnorby 	static char	buf[48];
5008e709cbdSnorby 	struct in_addr	addr;
5018e709cbdSnorby 
5028e709cbdSnorby 	addr.s_addr = id;
5038e709cbdSnorby 
5048e709cbdSnorby 	if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL)
5058e709cbdSnorby 		return ("?");
5068e709cbdSnorby 	else
5078e709cbdSnorby 		return (buf);
5088e709cbdSnorby }
5098e709cbdSnorby 
5108e709cbdSnorby const char *
5118e709cbdSnorby log_adv_rtr(u_int32_t adv_rtr)
5128e709cbdSnorby {
5138e709cbdSnorby 	static char	buf[48];
5148e709cbdSnorby 	struct in_addr	addr;
5158e709cbdSnorby 
5168e709cbdSnorby 	addr.s_addr = adv_rtr;
5178e709cbdSnorby 
5188e709cbdSnorby 	if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL)
5198e709cbdSnorby 		return ("?");
5208e709cbdSnorby 	else
5218e709cbdSnorby 		return (buf);
5228e709cbdSnorby }
5238e709cbdSnorby 
5248e709cbdSnorby void
525cb01fa27Sclaudio show_database_head(struct in_addr aid, char *ifname, u_int16_t type)
5268e709cbdSnorby {
5278e709cbdSnorby 	char	*header, *format;
528cb01fa27Sclaudio 	int	cleanup = 0;
5298e709cbdSnorby 
530005d568eSclaudio 	switch (ntohs(type)) {
5314fabe8f9Snorby 	case LSA_TYPE_LINK:
5328ea4c735Sclaudio 		format = "Link (Type-8) Link States";
5334fabe8f9Snorby 		break;
5348e709cbdSnorby 	case LSA_TYPE_ROUTER:
5358e709cbdSnorby 		format = "Router Link States";
5368e709cbdSnorby 		break;
5378e709cbdSnorby 	case LSA_TYPE_NETWORK:
5388e709cbdSnorby 		format = "Net Link States";
5398e709cbdSnorby 		break;
5404fabe8f9Snorby 	case LSA_TYPE_INTER_A_PREFIX:
5414fabe8f9Snorby 		format = "Inter Area Prefix Link States";
5428e709cbdSnorby 		break;
5434fabe8f9Snorby 	case LSA_TYPE_INTER_A_ROUTER:
5444fabe8f9Snorby 		format = "Inter Area Router Link States";
5454fabe8f9Snorby 		break;
5464fabe8f9Snorby 	case LSA_TYPE_INTRA_A_PREFIX:
5478ec36425Sstsp 		format = "Intra Area Prefix Link States";
5488e709cbdSnorby 		break;
5498e709cbdSnorby 	case LSA_TYPE_EXTERNAL:
550cb01fa27Sclaudio 		printf("\n%-15s %s\n\n", "", "Type-5 AS External Link States");
551cb01fa27Sclaudio 		return;
5528e709cbdSnorby 	default:
553cb01fa27Sclaudio 		if (asprintf(&format, "LSA type %x", ntohs(type)) == -1)
554cb01fa27Sclaudio 			err(1, NULL);
555cb01fa27Sclaudio 		cleanup = 1;
556cb01fa27Sclaudio 		break;
5578e709cbdSnorby 	}
558cb01fa27Sclaudio 	if (LSA_IS_SCOPE_AREA(ntohs(type))) {
5598e709cbdSnorby 		if (asprintf(&header, "%s (Area %s)", format,
5608e709cbdSnorby 		    inet_ntoa(aid)) == -1)
5618e709cbdSnorby 			err(1, NULL);
562cb01fa27Sclaudio 	} else if (LSA_IS_SCOPE_LLOCAL(ntohs(type))) {
563cb01fa27Sclaudio 		if (asprintf(&header, "%s (Area %s Interface %s)", format,
564cb01fa27Sclaudio 		    inet_ntoa(aid), ifname) == -1)
565cb01fa27Sclaudio 			err(1, NULL);
566cb01fa27Sclaudio 	}
5678e709cbdSnorby 
5688e709cbdSnorby 	printf("\n%-15s %s\n\n", "", header);
5698e709cbdSnorby 	free(header);
570cb01fa27Sclaudio 	if (cleanup)
571cb01fa27Sclaudio 		free(format);
5728e709cbdSnorby }
5738e709cbdSnorby 
5748e709cbdSnorby int
5758e709cbdSnorby show_database_msg(struct imsg *imsg)
5768e709cbdSnorby {
5778e709cbdSnorby 	static struct in_addr	 area_id;
5780bc8b661Sclaudio 	static u_int16_t	 lasttype;
579cb01fa27Sclaudio 	static char		 ifname[IF_NAMESIZE];
5808e709cbdSnorby 	struct area		*area;
581cb01fa27Sclaudio 	struct iface		*iface;
5828e709cbdSnorby 	struct lsa_hdr		*lsa;
5838e709cbdSnorby 
5848e709cbdSnorby 	switch (imsg->hdr.type) {
5858e709cbdSnorby 	case IMSG_CTL_SHOW_DATABASE:
5868e709cbdSnorby 	case IMSG_CTL_SHOW_DB_SELF:
5878e709cbdSnorby 		lsa = imsg->data;
5888e709cbdSnorby 		if (lsa->type != lasttype) {
589cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->type);
5908e709cbdSnorby 			printf("%-15s %-15s %-4s %-10s %-8s\n", "Link ID",
5918e709cbdSnorby 			    "Adv Router", "Age", "Seq#", "Checksum");
5928e709cbdSnorby 		}
5938e709cbdSnorby 		printf("%-15s %-15s %-4d 0x%08x 0x%04x\n",
5948e709cbdSnorby 		    log_id(lsa->ls_id), log_adv_rtr(lsa->adv_rtr),
5958e709cbdSnorby 		    ntohs(lsa->age), ntohl(lsa->seq_num),
5968e709cbdSnorby 		    ntohs(lsa->ls_chksum));
5978e709cbdSnorby 		lasttype = lsa->type;
5988e709cbdSnorby 		break;
5998e709cbdSnorby 	case IMSG_CTL_AREA:
6008e709cbdSnorby 		area = imsg->data;
6018e709cbdSnorby 		area_id = area->id;
6028e709cbdSnorby 		lasttype = 0;
6038e709cbdSnorby 		break;
604cb01fa27Sclaudio 	case IMSG_CTL_IFACE:
605cb01fa27Sclaudio 		iface = imsg->data;
606cb01fa27Sclaudio 		strlcpy(ifname, iface->name, sizeof(ifname));
607cb01fa27Sclaudio 		lasttype = 0;
608cb01fa27Sclaudio 		break;
6098e709cbdSnorby 	case IMSG_CTL_END:
6108e709cbdSnorby 		printf("\n");
6118e709cbdSnorby 		return (1);
6128e709cbdSnorby 	default:
6138e709cbdSnorby 		break;
6148e709cbdSnorby 	}
6158e709cbdSnorby 
6168e709cbdSnorby 	return (0);
6178e709cbdSnorby }
6188e709cbdSnorby 
6198e709cbdSnorby char *
6204fabe8f9Snorby print_ls_type(u_int16_t type)
6218e709cbdSnorby {
622005d568eSclaudio 	switch (ntohs(type)) {
6234fabe8f9Snorby 	case LSA_TYPE_LINK:
6244fabe8f9Snorby 		return ("Link");
6258e709cbdSnorby 	case LSA_TYPE_ROUTER:
6268e709cbdSnorby 		return ("Router");
6278e709cbdSnorby 	case LSA_TYPE_NETWORK:
6288e709cbdSnorby 		return ("Network");
6294fabe8f9Snorby 	case LSA_TYPE_INTER_A_PREFIX:
6304fabe8f9Snorby 		return ("Inter Area (Prefix)");
6314fabe8f9Snorby 	case LSA_TYPE_INTER_A_ROUTER:
6324fabe8f9Snorby 		return ("Inter Area (Router)");
6334fabe8f9Snorby 	case LSA_TYPE_INTRA_A_PREFIX:
6344fabe8f9Snorby 		return ("Intra Area (Prefix)");
6358e709cbdSnorby 	case LSA_TYPE_EXTERNAL:
6368e709cbdSnorby 		return ("AS External");
6378e709cbdSnorby 	default:
6388e709cbdSnorby 		return ("Unknown");
6398e709cbdSnorby 	}
6408e709cbdSnorby }
6418e709cbdSnorby 
6428e709cbdSnorby void
6438e709cbdSnorby show_db_hdr_msg_detail(struct lsa_hdr *lsa)
6448e709cbdSnorby {
6458e709cbdSnorby 	printf("LS age: %d\n", ntohs(lsa->age));
6468e709cbdSnorby 	printf("LS Type: %s\n", print_ls_type(lsa->type));
6478e709cbdSnorby 
648005d568eSclaudio 	switch (ntohs(lsa->type)) {
64989f180e4Sstsp 	case LSA_TYPE_ROUTER:
65089f180e4Sstsp 	case LSA_TYPE_INTER_A_PREFIX:
65189f180e4Sstsp 	case LSA_TYPE_INTER_A_ROUTER:
65289f180e4Sstsp 	case LSA_TYPE_INTRA_A_PREFIX:
65389f180e4Sstsp 	case LSA_TYPE_EXTERNAL:
6544fabe8f9Snorby 		printf("Link State ID: %s\n", log_id(lsa->ls_id));
6554fabe8f9Snorby 		break;
65689f180e4Sstsp 	case LSA_TYPE_LINK:
65789f180e4Sstsp 		printf("Link State ID: %s (Interface ID of Advertising "
65889f180e4Sstsp 		    "Router)\n", log_id(lsa->ls_id));
6598e709cbdSnorby 		break;
6608e709cbdSnorby 	case LSA_TYPE_NETWORK:
66189f180e4Sstsp 		printf("Link State ID: %s (Interface ID of Designated "
66289f180e4Sstsp 		    "Router)\n", log_id(lsa->ls_id));
6638e709cbdSnorby 		break;
6648e709cbdSnorby 	}
6658e709cbdSnorby 
6668e709cbdSnorby 	printf("Advertising Router: %s\n", log_adv_rtr(lsa->adv_rtr));
6678e709cbdSnorby 	printf("LS Seq Number: 0x%08x\n", ntohl(lsa->seq_num));
6688e709cbdSnorby 	printf("Checksum: 0x%04x\n", ntohs(lsa->ls_chksum));
6698e709cbdSnorby 	printf("Length: %d\n", ntohs(lsa->len));
6708e709cbdSnorby }
6718e709cbdSnorby 
6728e709cbdSnorby char *
6738e709cbdSnorby print_rtr_link_type(u_int8_t type)
6748e709cbdSnorby {
6758e709cbdSnorby 	switch (type) {
6768e709cbdSnorby 	case LINK_TYPE_POINTTOPOINT:
6778e709cbdSnorby 		return ("Point-to-Point");
6788e709cbdSnorby 	case LINK_TYPE_TRANSIT_NET:
6798e709cbdSnorby 		return ("Transit Network");
680005d568eSclaudio 	case LINK_TYPE_RESERVED:
681005d568eSclaudio 		return ("Reserved");
6828e709cbdSnorby 	case LINK_TYPE_VIRTUAL:
6838e709cbdSnorby 		return ("Virtual Link");
6848e709cbdSnorby 	default:
6858e709cbdSnorby 		return ("Unknown");
6868e709cbdSnorby 	}
6878e709cbdSnorby }
6888e709cbdSnorby 
6898e709cbdSnorby const char *
6908e709cbdSnorby print_ospf_flags(u_int8_t opts)
6918e709cbdSnorby {
6928e709cbdSnorby 	static char	optbuf[32];
6938e709cbdSnorby 
694aff6ccb8Sclaudio 	snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s",
6958e709cbdSnorby 	    opts & OSPF_RTR_V ? "V" : "-",
6968e709cbdSnorby 	    opts & OSPF_RTR_E ? "E" : "-",
6978e709cbdSnorby 	    opts & OSPF_RTR_B ? "B" : "-");
6988e709cbdSnorby 	return (optbuf);
6998e709cbdSnorby }
7008e709cbdSnorby 
701*1aff836dSclaudio const char *
702*1aff836dSclaudio print_asext_flags(u_int32_t opts)
703*1aff836dSclaudio {
704*1aff836dSclaudio 	static char	optbuf[32];
705*1aff836dSclaudio 
706*1aff836dSclaudio 	snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s",
707*1aff836dSclaudio 	    opts & LSA_ASEXT_E_FLAG ? "E" : "-",
708*1aff836dSclaudio 	    opts & LSA_ASEXT_F_FLAG ? "F" : "-",
709*1aff836dSclaudio 	    opts & LSA_ASEXT_T_FLAG ? "T" : "-");
710*1aff836dSclaudio 	return (optbuf);
711*1aff836dSclaudio }
712*1aff836dSclaudio 
713*1aff836dSclaudio const char *
714*1aff836dSclaudio print_prefix_opt(u_int8_t opts)
715*1aff836dSclaudio {
716*1aff836dSclaudio 	static char	optbuf[32];
717*1aff836dSclaudio 
718*1aff836dSclaudio 	if (opts) {
719*1aff836dSclaudio 		snprintf(optbuf, sizeof(optbuf),
720*1aff836dSclaudio 		    " Options: *|*|*|%s|%s|x|%s|%s",
721*1aff836dSclaudio 		    opts & OSPF_PREFIX_DN ? "DN" : "-",
722*1aff836dSclaudio 		    opts & OSPF_PREFIX_P ? "P" : "-",
723*1aff836dSclaudio 		    opts & OSPF_PREFIX_LA ? "LA" : "-",
724*1aff836dSclaudio 		    opts & OSPF_PREFIX_NU ? "NU" : "-");
725*1aff836dSclaudio 		return (optbuf);
726*1aff836dSclaudio 	}
727*1aff836dSclaudio 	return ("");
728*1aff836dSclaudio }
729*1aff836dSclaudio 
7308e709cbdSnorby int
7318e709cbdSnorby show_db_msg_detail(struct imsg *imsg)
7328e709cbdSnorby {
7338e709cbdSnorby 	static struct in_addr	 area_id;
734cb01fa27Sclaudio 	static char		 ifname[IF_NAMESIZE];
735005d568eSclaudio 	static u_int16_t	 lasttype;
736*1aff836dSclaudio 	struct in6_addr		 ia6;
7378e709cbdSnorby 	struct in_addr		 addr, data;
7388e709cbdSnorby 	struct area		*area;
739cb01fa27Sclaudio 	struct iface		*iface;
7408e709cbdSnorby 	struct lsa		*lsa;
7418e709cbdSnorby 	struct lsa_rtr_link	*rtr_link;
7420f96e20cSstsp 	struct lsa_net_link	*net_link;
743aeb06b08Sclaudio 	struct lsa_prefix	*prefix;
7448e709cbdSnorby 	struct lsa_asext	*asext;
745*1aff836dSclaudio 	u_int32_t		 ext_tag;
7468e709cbdSnorby 	u_int16_t		 i, nlinks, off;
7478e709cbdSnorby 
7488e709cbdSnorby 	/* XXX sanity checks! */
7498e709cbdSnorby 
7508e709cbdSnorby 	switch (imsg->hdr.type) {
7518e709cbdSnorby 	case IMSG_CTL_SHOW_DB_EXT:
7528e709cbdSnorby 		lsa = imsg->data;
7538e709cbdSnorby 		if (lsa->hdr.type != lasttype)
754cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
7558e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
7568e709cbdSnorby 
7578e709cbdSnorby 		asext = (struct lsa_asext *)((char *)lsa + sizeof(lsa->hdr));
7588e709cbdSnorby 
759*1aff836dSclaudio 		printf("    Flags: %s\n",
760*1aff836dSclaudio 		    print_asext_flags(ntohl(lsa->data.asext.metric)));
761*1aff836dSclaudio 		printf("    Metric: %d Type: ", ntohl(asext->metric)
762*1aff836dSclaudio 		    & LSA_METRIC_MASK);
7638e709cbdSnorby 		if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_E_FLAG)
7648e709cbdSnorby 			printf("2\n");
7658e709cbdSnorby 		else
7668e709cbdSnorby 			printf("1\n");
7678e709cbdSnorby 
768*1aff836dSclaudio 		prefix = &asext->prefix;
769*1aff836dSclaudio 		bzero(&ia6, sizeof(ia6));
770*1aff836dSclaudio 		bcopy(prefix + 1, &ia6, LSA_PREFIXSIZE(prefix->prefixlen));
771*1aff836dSclaudio 		printf("    Prefix: %s/%d%s\n", log_in6addr(&ia6),
772*1aff836dSclaudio 		    prefix->prefixlen, print_prefix_opt(prefix->options));
773*1aff836dSclaudio 
774*1aff836dSclaudio 		off = sizeof(*asext) + LSA_PREFIXSIZE(prefix->prefixlen);
775*1aff836dSclaudio 		if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_F_FLAG) {
776*1aff836dSclaudio 			bcopy((char *)asext + off, &ia6, sizeof(ia6));
777*1aff836dSclaudio 			printf("    Forwarding Address: %s\n",
778*1aff836dSclaudio 			    log_in6addr(&ia6));
779*1aff836dSclaudio 			off += sizeof(ia6);
780*1aff836dSclaudio 		}
781*1aff836dSclaudio 		if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_T_FLAG) {
782*1aff836dSclaudio 			bcopy((char *)asext + off, &ext_tag, sizeof(ext_tag));
783*1aff836dSclaudio 			printf("    External Route Tag: %d\n", ntohl(ext_tag));
784*1aff836dSclaudio 		}
785*1aff836dSclaudio 		printf("\n");
7868e709cbdSnorby 		lasttype = lsa->hdr.type;
7878e709cbdSnorby 		break;
788aeb06b08Sclaudio 	case IMSG_CTL_SHOW_DB_LINK:
789aeb06b08Sclaudio 		lsa = imsg->data;
790aeb06b08Sclaudio 		if (lsa->hdr.type != lasttype)
791aeb06b08Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
792aeb06b08Sclaudio 		show_db_hdr_msg_detail(&lsa->hdr);
7935a54ac3cSclaudio 		printf("Options: %s\n", print_ospf_options(LSA_24_GETLO(
7945a54ac3cSclaudio 		    ntohl(lsa->data.link.opts))));
7955a54ac3cSclaudio 		printf("Link Local Address: %s\n",
7965a54ac3cSclaudio 		    log_in6addr(&lsa->data.link.lladdr));
797aeb06b08Sclaudio 
798aeb06b08Sclaudio 		nlinks = ntohl(lsa->data.link.numprefix);
799aeb06b08Sclaudio 		printf("Number of Prefixes: %d\n", nlinks);
800aeb06b08Sclaudio 		off = sizeof(lsa->hdr) + sizeof(struct lsa_link);
801aeb06b08Sclaudio 
802aeb06b08Sclaudio 		for (i = 0; i < nlinks; i++) {
803aeb06b08Sclaudio 			prefix = (struct lsa_prefix *)((char *)lsa + off);
8045a54ac3cSclaudio 			bzero(&ia6, sizeof(ia6));
8055a54ac3cSclaudio 			bcopy(prefix + 1, &ia6,
8065a54ac3cSclaudio 			    LSA_PREFIXSIZE(prefix->prefixlen));
807aeb06b08Sclaudio 
808*1aff836dSclaudio 			printf("    Prefix: %s/%d%s\n", log_in6addr(&ia6),
809*1aff836dSclaudio 			    prefix->prefixlen,
810*1aff836dSclaudio 			    print_prefix_opt(prefix->options));
811aeb06b08Sclaudio 
81208720e8dSstsp 			off += sizeof(struct lsa_prefix)
81308720e8dSstsp 			    + LSA_PREFIXSIZE(prefix->prefixlen);
814aeb06b08Sclaudio 		}
815aeb06b08Sclaudio 
816aeb06b08Sclaudio 		printf("\n");
817aeb06b08Sclaudio 		lasttype = lsa->hdr.type;
818aeb06b08Sclaudio 		break;
8198e709cbdSnorby 	case IMSG_CTL_SHOW_DB_NET:
8208e709cbdSnorby 		lsa = imsg->data;
8218e709cbdSnorby 		if (lsa->hdr.type != lasttype)
822cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
8238e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
8240bc8b661Sclaudio 		printf("Options: %s\n",
8250bc8b661Sclaudio 		    print_ospf_options(LSA_24_GETLO(ntohl(lsa->data.net.opts))));
8268e709cbdSnorby 
8270f96e20cSstsp 		nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr) -
8280f96e20cSstsp 		    sizeof(struct lsa_net)) / sizeof(struct lsa_net_link);
8290f96e20cSstsp 		net_link = (struct lsa_net_link *)((char *)lsa +
8300f96e20cSstsp 		    sizeof(lsa->hdr) + sizeof(lsa->data.net));
831aeb06b08Sclaudio 		printf("Number of Routers: %d\n", nlinks);
8328e709cbdSnorby 
8338e709cbdSnorby 		for (i = 0; i < nlinks; i++) {
8340f96e20cSstsp 			addr.s_addr = net_link->att_rtr;
8358e709cbdSnorby 			printf("    Attached Router: %s\n", inet_ntoa(addr));
8360f96e20cSstsp 			net_link++;
8378e709cbdSnorby 		}
8388e709cbdSnorby 
8398e709cbdSnorby 		printf("\n");
8408e709cbdSnorby 		lasttype = lsa->hdr.type;
8418e709cbdSnorby 		break;
8428e709cbdSnorby 	case IMSG_CTL_SHOW_DB_RTR:
8438e709cbdSnorby 		lsa = imsg->data;
8448e709cbdSnorby 		if (lsa->hdr.type != lasttype)
845cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
8468e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
8479d28d229Sclaudio 		printf("Flags: %s\n",
848aff6ccb8Sclaudio 		    print_ospf_flags(LSA_24_GETHI(ntohl(lsa->data.rtr.opts))));
8499d28d229Sclaudio 		printf("Options: %s\n",
850aff6ccb8Sclaudio 		    print_ospf_options(LSA_24_GETLO(ntohl(lsa->data.rtr.opts))));
8519d28d229Sclaudio 
8529d28d229Sclaudio 		nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr)
8539d28d229Sclaudio 		    - sizeof(u_int32_t)) / sizeof(struct lsa_rtr_link);
854aeb06b08Sclaudio 		printf("Number of Links: %d\n", nlinks);
8558e709cbdSnorby 
8568e709cbdSnorby 		off = sizeof(lsa->hdr) + sizeof(struct lsa_rtr);
8578e709cbdSnorby 
8588e709cbdSnorby 		for (i = 0; i < nlinks; i++) {
8598e709cbdSnorby 			rtr_link = (struct lsa_rtr_link *)((char *)lsa + off);
8608e709cbdSnorby 
8613ded35dfSstsp 			printf("    Link (Interface ID %s) connected to: %s\n",
8623ded35dfSstsp 			    log_id(rtr_link->iface_id),
8638e709cbdSnorby 			    print_rtr_link_type(rtr_link->type));
8648e709cbdSnorby 
865005d568eSclaudio 			addr.s_addr = rtr_link->nbr_rtr_id;
8663ded35dfSstsp 			data.s_addr = rtr_link->nbr_iface_id;
8678e709cbdSnorby 
8688e709cbdSnorby 			switch (rtr_link->type) {
8698e709cbdSnorby 			case LINK_TYPE_POINTTOPOINT:
8708e709cbdSnorby 			case LINK_TYPE_VIRTUAL:
871005d568eSclaudio 				printf("    Router ID: %s\n", inet_ntoa(addr));
872005d568eSclaudio 				printf("    Interface ID: %s\n",
873005d568eSclaudio 				    inet_ntoa(data));
8748e709cbdSnorby 				break;
8758e709cbdSnorby 			case LINK_TYPE_TRANSIT_NET:
876005d568eSclaudio 				printf("    Designated Router ID: %s\n",
8778e709cbdSnorby 				    inet_ntoa(addr));
878005d568eSclaudio 				printf("    DR Interface ID: %s\n",
8798e709cbdSnorby 				    inet_ntoa(data));
8808e709cbdSnorby 				break;
8818e709cbdSnorby 			default:
882005d568eSclaudio 				printf("    Link ID (Unknown type %d): %s\n",
883005d568eSclaudio 				    rtr_link->type, inet_ntoa(addr));
8848e709cbdSnorby 				printf("    Link Data (Unknown): %s\n",
8858e709cbdSnorby 				    inet_ntoa(data));
8868e709cbdSnorby 				break;
8878e709cbdSnorby 			}
8888e709cbdSnorby 
8898e709cbdSnorby 			printf("    Metric: %d\n\n", ntohs(rtr_link->metric));
8908e709cbdSnorby 
891005d568eSclaudio 			off += sizeof(struct lsa_rtr_link);
8928e709cbdSnorby 		}
8938e709cbdSnorby 
8948e709cbdSnorby 		lasttype = lsa->hdr.type;
8958e709cbdSnorby 		break;
89641bcac6bSstsp 	case IMSG_CTL_SHOW_DB_INTRA:
89741bcac6bSstsp 		lsa = imsg->data;
89841bcac6bSstsp 		if (lsa->hdr.type != lasttype)
89941bcac6bSstsp 			show_database_head(area_id, ifname, lsa->hdr.type);
90041bcac6bSstsp 		show_db_hdr_msg_detail(&lsa->hdr);
90141bcac6bSstsp 		printf("Referenced LS Type: %s\n",
90241bcac6bSstsp 		    print_ls_type(lsa->data.pref_intra.ref_type));
903e0e6f381Sclaudio 		addr.s_addr = lsa->data.pref_intra.ref_ls_id;
90441bcac6bSstsp 		printf("Referenced Link State ID: %s\n", inet_ntoa(addr));
90541bcac6bSstsp 		addr.s_addr = lsa->data.pref_intra.ref_adv_rtr;
90641bcac6bSstsp 		printf("Referenced Advertising Router: %s\n", inet_ntoa(addr));
90741bcac6bSstsp 		nlinks = ntohs(lsa->data.pref_intra.numprefix);
90841bcac6bSstsp 		printf("Number of Prefixes: %d\n", nlinks);
90941bcac6bSstsp 
91041bcac6bSstsp 		off = sizeof(lsa->hdr) + sizeof(struct lsa_intra_prefix);
91141bcac6bSstsp 
91241bcac6bSstsp 		for (i = 0; i < nlinks; i++) {
91341bcac6bSstsp 			prefix = (struct lsa_prefix *)((char *)lsa + off);
91441bcac6bSstsp 			bzero(&ia6, sizeof(ia6));
91541bcac6bSstsp 			bcopy(prefix + 1, &ia6,
91641bcac6bSstsp 			    LSA_PREFIXSIZE(prefix->prefixlen));
91741bcac6bSstsp 
918*1aff836dSclaudio 			printf("    Prefix: %s/%d%s\n", log_in6addr(&ia6),
919*1aff836dSclaudio 			    prefix->prefixlen,
920*1aff836dSclaudio 			    print_prefix_opt(prefix->options));
92141bcac6bSstsp 
92208720e8dSstsp 			off += sizeof(struct lsa_prefix)
92308720e8dSstsp 			    + LSA_PREFIXSIZE(prefix->prefixlen);
92441bcac6bSstsp 		}
9259415b30cSstsp 
9269415b30cSstsp 		printf("\n");
9279415b30cSstsp 		lasttype = lsa->hdr.type;
92841bcac6bSstsp 		break;
9298e709cbdSnorby 	case IMSG_CTL_SHOW_DB_SUM:
9308e709cbdSnorby 		lsa = imsg->data;
9318e709cbdSnorby 		if (lsa->hdr.type != lasttype)
932cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
9338e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
934cb01fa27Sclaudio 		printf("Prefix: XXX\n");
935aeb06b08Sclaudio 		printf("Metric: %d\n", ntohl(lsa->data.pref_sum.metric) &
9368e709cbdSnorby 		    LSA_METRIC_MASK);
9378e709cbdSnorby 		lasttype = lsa->hdr.type;
9388e709cbdSnorby 		break;
939cb01fa27Sclaudio 	case IMSG_CTL_SHOW_DB_ASBR:
940cb01fa27Sclaudio 		lsa = imsg->data;
941cb01fa27Sclaudio 		if (lsa->hdr.type != lasttype)
942cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
943cb01fa27Sclaudio 		show_db_hdr_msg_detail(&lsa->hdr);
944cb01fa27Sclaudio 
945cb01fa27Sclaudio 		addr.s_addr = lsa->data.rtr_sum.dest_rtr_id;
946cb01fa27Sclaudio 		printf("Destination Router ID: %s\n", inet_ntoa(addr));
947cb01fa27Sclaudio 		printf("Options: %s\n",
948aeb06b08Sclaudio 		    print_ospf_options(ntohl(lsa->data.rtr_sum.opts)));
949cb01fa27Sclaudio 		printf("Metric: %d\n\n", ntohl(lsa->data.rtr_sum.metric) &
950cb01fa27Sclaudio 		    LSA_METRIC_MASK);
9518e709cbdSnorby 	case IMSG_CTL_AREA:
9528e709cbdSnorby 		area = imsg->data;
9538e709cbdSnorby 		area_id = area->id;
9548e709cbdSnorby 		lasttype = 0;
9558e709cbdSnorby 		break;
956cb01fa27Sclaudio 	case IMSG_CTL_IFACE:
957cb01fa27Sclaudio 		iface = imsg->data;
958cb01fa27Sclaudio 		strlcpy(ifname, iface->name, sizeof(ifname));
959cb01fa27Sclaudio 		lasttype = 0;
960cb01fa27Sclaudio 		break;
9618e709cbdSnorby 	case IMSG_CTL_END:
9628e709cbdSnorby 		return (1);
9638e709cbdSnorby 	default:
9648e709cbdSnorby 		break;
9658e709cbdSnorby 	}
9668e709cbdSnorby 
9678e709cbdSnorby 	return (0);
9688e709cbdSnorby }
9698e709cbdSnorby 
9708e709cbdSnorby int
9718e709cbdSnorby show_nbr_msg(struct imsg *imsg)
9728e709cbdSnorby {
9738e709cbdSnorby 	struct ctl_nbr	*nbr;
9748e709cbdSnorby 	char		*state;
9758e709cbdSnorby 
9768e709cbdSnorby 	switch (imsg->hdr.type) {
9778e709cbdSnorby 	case IMSG_CTL_SHOW_NBR:
9788e709cbdSnorby 		nbr = imsg->data;
9798e709cbdSnorby 		if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state),
9808e709cbdSnorby 		    if_state_name(nbr->iface_state)) == -1)
9818e709cbdSnorby 			err(1, NULL);
982558ada41Snorby 		printf("%-15s %-3d %-12s %-10s", inet_ntoa(nbr->id),
9838e709cbdSnorby 		    nbr->priority, state, fmt_timeframe_core(nbr->dead_timer));
984558ada41Snorby 		printf("%-11s %s\n", nbr->name,
9858e709cbdSnorby 		    nbr->uptime == 0 ? "-" : fmt_timeframe_core(nbr->uptime));
9868e709cbdSnorby 		free(state);
9878e709cbdSnorby 		break;
9888e709cbdSnorby 	case IMSG_CTL_END:
9898e709cbdSnorby 		printf("\n");
9908e709cbdSnorby 		return (1);
9918e709cbdSnorby 	default:
9928e709cbdSnorby 		break;
9938e709cbdSnorby 	}
9948e709cbdSnorby 
9958e709cbdSnorby 	return (0);
9968e709cbdSnorby }
9978e709cbdSnorby 
9988e709cbdSnorby const char *
999aff6ccb8Sclaudio print_ospf_options(u_int32_t opts)
10008e709cbdSnorby {
10018e709cbdSnorby 	static char	optbuf[32];
10028e709cbdSnorby 
1003aff6ccb8Sclaudio 	snprintf(optbuf, sizeof(optbuf), "*|*|%s|%s|%s|*|%s|%s",
10048e709cbdSnorby 	    opts & OSPF_OPTION_DC ? "DC" : "-",
10058e709cbdSnorby 	    opts & OSPF_OPTION_R ? "R" : "-",
10068e709cbdSnorby 	    opts & OSPF_OPTION_N ? "N" : "-",
10078e709cbdSnorby 	    opts & OSPF_OPTION_E ? "E" : "-",
10088e709cbdSnorby 	    opts & OSPF_OPTION_V6 ? "V6" : "-");
10098e709cbdSnorby 	return (optbuf);
10108e709cbdSnorby }
10118e709cbdSnorby 
10128e709cbdSnorby int
10138e709cbdSnorby show_nbr_detail_msg(struct imsg *imsg)
10148e709cbdSnorby {
10158e709cbdSnorby 	struct ctl_nbr	*nbr;
10168e709cbdSnorby 
10178e709cbdSnorby 	switch (imsg->hdr.type) {
10188e709cbdSnorby 	case IMSG_CTL_SHOW_NBR:
10198e709cbdSnorby 		nbr = imsg->data;
10208e709cbdSnorby 		printf("\nNeighbor %s, ", inet_ntoa(nbr->id));
10218e709cbdSnorby 		printf("interface address %s\n", log_in6addr(&nbr->addr));
10228e709cbdSnorby 		printf("  Area %s, interface %s\n", inet_ntoa(nbr->area),
10238e709cbdSnorby 		    nbr->name);
10248e709cbdSnorby 		printf("  Neighbor priority is %d, "
10258e709cbdSnorby 		    "State is %s, %d state changes\n",
10268e709cbdSnorby 		    nbr->priority, nbr_state_name(nbr->nbr_state),
10278e709cbdSnorby 		    nbr->state_chng_cnt);
10288e709cbdSnorby 		printf("  DR is %s, ", inet_ntoa(nbr->dr));
10298e709cbdSnorby 		printf("BDR is %s\n", inet_ntoa(nbr->bdr));
10308e709cbdSnorby 		printf("  Options %s\n", print_ospf_options(nbr->options));
10318e709cbdSnorby 		printf("  Dead timer due in %s\n",
10328e709cbdSnorby 		    fmt_timeframe_core(nbr->dead_timer));
10338e709cbdSnorby 		printf("  Uptime %s\n", fmt_timeframe_core(nbr->uptime));
10348e709cbdSnorby 		printf("  Database Summary List %d\n", nbr->db_sum_lst_cnt);
10358e709cbdSnorby 		printf("  Link State Request List %d\n", nbr->ls_req_lst_cnt);
10368e709cbdSnorby 		printf("  Link State Retransmission List %d\n",
10378e709cbdSnorby 		    nbr->ls_retrans_lst_cnt);
10388e709cbdSnorby 		break;
10398e709cbdSnorby 	case IMSG_CTL_END:
10408e709cbdSnorby 		printf("\n");
10418e709cbdSnorby 		return (1);
10428e709cbdSnorby 	default:
10438e709cbdSnorby 		break;
10448e709cbdSnorby 	}
10458e709cbdSnorby 
10468e709cbdSnorby 	return (0);
10478e709cbdSnorby }
10488e709cbdSnorby 
10498e709cbdSnorby int
10508e709cbdSnorby show_rib_msg(struct imsg *imsg)
10518e709cbdSnorby {
10528e709cbdSnorby 	struct ctl_rt	*rt;
10538e709cbdSnorby 	char		*dstnet;
10548e709cbdSnorby 
10558e709cbdSnorby 	switch (imsg->hdr.type) {
10568e709cbdSnorby 	case IMSG_CTL_SHOW_RIB:
10578e709cbdSnorby 		rt = imsg->data;
10588e709cbdSnorby 		switch (rt->d_type) {
10598e709cbdSnorby 		case DT_NET:
10600104e403Sclaudio 			if (asprintf(&dstnet, "%s/%d", log_in6addr(&rt->prefix),
10618e709cbdSnorby 			    rt->prefixlen) == -1)
10628e709cbdSnorby 				err(1, NULL);
10638e709cbdSnorby 			break;
10648e709cbdSnorby 		case DT_RTR:
10658e709cbdSnorby 			if (asprintf(&dstnet, "%s",
10660104e403Sclaudio 			    log_in6addr(&rt->prefix)) == -1)
10678e709cbdSnorby 				err(1, NULL);
10688e709cbdSnorby 			break;
10698e709cbdSnorby 		default:
10708e709cbdSnorby 			errx(1, "Invalid route type");
10718e709cbdSnorby 		}
10728e709cbdSnorby 
10738e709cbdSnorby 		printf("%-20s %-17s %-12s %-9s %-7d %s\n", dstnet,
10740a08a1b1Sclaudio 		    log_in6addr_scope(&rt->nexthop, rt->ifindex),
10750a08a1b1Sclaudio 		    path_type_name(rt->p_type), dst_type_name(rt->d_type),
10760a08a1b1Sclaudio 		    rt->cost,
10778e709cbdSnorby 		    rt->uptime == 0 ? "-" : fmt_timeframe_core(rt->uptime));
10788e709cbdSnorby 		free(dstnet);
10798e709cbdSnorby 		break;
10808e709cbdSnorby 	case IMSG_CTL_END:
10818e709cbdSnorby 		printf("\n");
10828e709cbdSnorby 		return (1);
10838e709cbdSnorby 	default:
10848e709cbdSnorby 		break;
10858e709cbdSnorby 	}
10868e709cbdSnorby 
10878e709cbdSnorby 	return (0);
10888e709cbdSnorby }
10898e709cbdSnorby 
10908e709cbdSnorby void
10918e709cbdSnorby show_rib_head(struct in_addr aid, u_int8_t d_type, u_int8_t p_type)
10928e709cbdSnorby {
10938e709cbdSnorby 	char	*header, *format, *format2;
10948e709cbdSnorby 
10958e709cbdSnorby 	switch (p_type) {
10968e709cbdSnorby 	case PT_INTRA_AREA:
10978e709cbdSnorby 	case PT_INTER_AREA:
10988e709cbdSnorby 		switch (d_type) {
10998e709cbdSnorby 		case DT_NET:
11008e709cbdSnorby 			format = "Network Routing Table";
11018e709cbdSnorby 			format2 = "";
11028e709cbdSnorby 			break;
11038e709cbdSnorby 		case DT_RTR:
11048e709cbdSnorby 			format = "Router Routing Table";
11058e709cbdSnorby 			format2 = "Type";
11068e709cbdSnorby 			break;
11078e709cbdSnorby 		default:
11088e709cbdSnorby 			errx(1, "unknown route type");
11098e709cbdSnorby 		}
11108e709cbdSnorby 		break;
11118e709cbdSnorby 	case PT_TYPE1_EXT:
11128e709cbdSnorby 	case PT_TYPE2_EXT:
11138e709cbdSnorby 		format = NULL;
11148e709cbdSnorby 		format2 = "Cost 2";
11158e709cbdSnorby 		if ((header = strdup("External Routing Table")) == NULL)
11168e709cbdSnorby 			err(1, NULL);
11178e709cbdSnorby 		break;
11188e709cbdSnorby 	default:
11198e709cbdSnorby 		errx(1, "unknown route type");
11208e709cbdSnorby 	}
11218e709cbdSnorby 
11228e709cbdSnorby 	if (p_type != PT_TYPE1_EXT && p_type != PT_TYPE2_EXT)
11238e709cbdSnorby 		if (asprintf(&header, "%s (Area %s)", format,
11248e709cbdSnorby 		    inet_ntoa(aid)) == -1)
11258e709cbdSnorby 			err(1, NULL);
11268e709cbdSnorby 
11278e709cbdSnorby 	printf("\n%-18s %s\n", "", header);
11288e709cbdSnorby 	free(header);
11298e709cbdSnorby 
11308e709cbdSnorby 	printf("\n%-18s %-15s %-15s %-12s %-7s %-7s\n", "Destination",
11318e709cbdSnorby 	    "Nexthop", "Adv Router", "Path type", "Cost", format2);
11328e709cbdSnorby }
11338e709cbdSnorby 
11348e709cbdSnorby const char *
11358e709cbdSnorby print_ospf_rtr_flags(u_int8_t opts)
11368e709cbdSnorby {
11378e709cbdSnorby 	static char	optbuf[32];
11388e709cbdSnorby 
11398e709cbdSnorby 	snprintf(optbuf, sizeof(optbuf), "%s%s%s",
11408e709cbdSnorby 	    opts & OSPF_RTR_E ? "AS" : "",
11418e709cbdSnorby 	    opts & OSPF_RTR_E && opts & OSPF_RTR_B ? "+" : "",
11428e709cbdSnorby 	    opts & OSPF_RTR_B ? "ABR" : "");
11438e709cbdSnorby 	return (optbuf);
11448e709cbdSnorby }
11458e709cbdSnorby 
11468e709cbdSnorby int
11478e709cbdSnorby show_rib_detail_msg(struct imsg *imsg)
11488e709cbdSnorby {
11498e709cbdSnorby 	static struct in_addr	 area_id;
11508e709cbdSnorby 	struct ctl_rt		*rt;
11518e709cbdSnorby 	struct area		*area;
11528e709cbdSnorby 	char			*dstnet;
11538e709cbdSnorby 	static u_int8_t		 lasttype;
11548e709cbdSnorby 
11558e709cbdSnorby 	switch (imsg->hdr.type) {
11568e709cbdSnorby 	case IMSG_CTL_SHOW_RIB:
11578e709cbdSnorby 		rt = imsg->data;
11588e709cbdSnorby 
11598e709cbdSnorby 		switch (rt->p_type) {
11608e709cbdSnorby 		case PT_INTRA_AREA:
11618e709cbdSnorby 		case PT_INTER_AREA:
11628e709cbdSnorby 			switch (rt->d_type) {
11638e709cbdSnorby 			case DT_NET:
11648e709cbdSnorby 				if (lasttype != RIB_NET)
11658e709cbdSnorby 					show_rib_head(rt->area, rt->d_type,
11668e709cbdSnorby 					     rt->p_type);
11678e709cbdSnorby 				if (asprintf(&dstnet, "%s/%d",
11680104e403Sclaudio 				    log_in6addr(&rt->prefix),
11690104e403Sclaudio 				    rt->prefixlen) == -1)
11708e709cbdSnorby 					err(1, NULL);
11718e709cbdSnorby 				lasttype = RIB_NET;
11728e709cbdSnorby 				break;
11738e709cbdSnorby 			case DT_RTR:
11748e709cbdSnorby 				if (lasttype != RIB_RTR)
11758e709cbdSnorby 					show_rib_head(rt->area, rt->d_type,
11768e709cbdSnorby 					     rt->p_type);
11778e709cbdSnorby 				if (asprintf(&dstnet, "%s",
11780104e403Sclaudio 				    log_in6addr(&rt->prefix)) == -1)
11798e709cbdSnorby 					err(1, NULL);
11808e709cbdSnorby 				lasttype = RIB_RTR;
11818e709cbdSnorby 				break;
11828e709cbdSnorby 			default:
11838e709cbdSnorby 				errx(1, "unknown route type");
11848e709cbdSnorby 			}
11850104e403Sclaudio 			printf("%-18s %-15s ", dstnet,
11865d8c2b7fSclaudio 			    log_in6addr_scope(&rt->nexthop, rt->ifindex));
11878e709cbdSnorby 			printf("%-15s %-12s %-7d", inet_ntoa(rt->adv_rtr),
11888e709cbdSnorby 			    path_type_name(rt->p_type), rt->cost);
11898e709cbdSnorby 			free(dstnet);
11908e709cbdSnorby 
11918e709cbdSnorby 			if (rt->d_type == DT_RTR)
11928e709cbdSnorby 				printf(" %-7s",
11938e709cbdSnorby 				    print_ospf_rtr_flags(rt->flags));
11948e709cbdSnorby 
11958e709cbdSnorby 			printf("\n");
11968e709cbdSnorby 			break;
11978e709cbdSnorby 		case PT_TYPE1_EXT:
11988e709cbdSnorby 		case PT_TYPE2_EXT:
11998e709cbdSnorby 			if (lasttype != RIB_EXT)
12008e709cbdSnorby 				show_rib_head(rt->area, rt->d_type, rt->p_type);
12018e709cbdSnorby 
12028e709cbdSnorby 			if (asprintf(&dstnet, "%s/%d",
12030104e403Sclaudio 			    log_in6addr(&rt->prefix), rt->prefixlen) == -1)
12048e709cbdSnorby 				err(1, NULL);
12058e709cbdSnorby 
12060104e403Sclaudio 			printf("%-18s %-15s ", dstnet,
12075d8c2b7fSclaudio 			    log_in6addr_scope(&rt->nexthop, rt->ifindex));
12088e709cbdSnorby 			printf("%-15s %-12s %-7d %-7d\n",
12098e709cbdSnorby 			    inet_ntoa(rt->adv_rtr), path_type_name(rt->p_type),
12108e709cbdSnorby 			    rt->cost, rt->cost2);
12118957b20dSstsp 			free(dstnet);
12128e709cbdSnorby 
12138e709cbdSnorby 			lasttype = RIB_EXT;
12148e709cbdSnorby 			break;
12158e709cbdSnorby 		default:
12168e709cbdSnorby 			errx(1, "unknown route type");
12178e709cbdSnorby 		}
12188e709cbdSnorby 		break;
12198e709cbdSnorby 	case IMSG_CTL_AREA:
12208e709cbdSnorby 		area = imsg->data;
12218e709cbdSnorby 		area_id = area->id;
12228e709cbdSnorby 		break;
12238e709cbdSnorby 	case IMSG_CTL_END:
12248e709cbdSnorby 		printf("\n");
12258e709cbdSnorby 		return (1);
12268e709cbdSnorby 	default:
12278e709cbdSnorby 		break;
12288e709cbdSnorby 	}
12298e709cbdSnorby 
12308e709cbdSnorby 	return (0);
12318e709cbdSnorby }
12328e709cbdSnorby 
12338e709cbdSnorby void
12348e709cbdSnorby show_fib_head(void)
12358e709cbdSnorby {
12368e709cbdSnorby 	printf("flags: * = valid, O = OSPF, C = Connected, S = Static\n");
12378e709cbdSnorby 	printf("%-6s %-20s %-17s\n", "Flags", "Destination", "Nexthop");
12388e709cbdSnorby }
12398e709cbdSnorby 
12408e709cbdSnorby int
12418e709cbdSnorby show_fib_msg(struct imsg *imsg)
12428e709cbdSnorby {
12438e709cbdSnorby 	struct kroute		*k;
12448e709cbdSnorby 	char			*p;
12458e709cbdSnorby 
12468e709cbdSnorby 	switch (imsg->hdr.type) {
12478e709cbdSnorby 	case IMSG_CTL_KROUTE:
12488e709cbdSnorby 		if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute))
12498e709cbdSnorby 			errx(1, "wrong imsg len");
12508e709cbdSnorby 		k = imsg->data;
12518e709cbdSnorby 
12528e709cbdSnorby 		if (k->flags & F_DOWN)
12538e709cbdSnorby 			printf(" ");
12548e709cbdSnorby 		else
12558e709cbdSnorby 			printf("*");
12568e709cbdSnorby 
12578e709cbdSnorby 		if (!(k->flags & F_KERNEL))
12588e709cbdSnorby 			printf("O");
12598e709cbdSnorby 		else if (k->flags & F_CONNECTED)
12608e709cbdSnorby 			printf("C");
12618e709cbdSnorby 		else if (k->flags & F_STATIC)
12628e709cbdSnorby 			printf("S");
12638e709cbdSnorby 		else
12648e709cbdSnorby 			printf(" ");
12658e709cbdSnorby 
12668e709cbdSnorby 		printf("     ");
12670104e403Sclaudio 		if (asprintf(&p, "%s/%u", log_in6addr(&k->prefix),
12680104e403Sclaudio 		    k->prefixlen) == -1)
12698e709cbdSnorby 			err(1, NULL);
12708e709cbdSnorby 		printf("%-20s ", p);
12718e709cbdSnorby 		free(p);
12728e709cbdSnorby 
12730104e403Sclaudio 		if (!IN6_IS_ADDR_UNSPECIFIED(&k->nexthop))
12745d8c2b7fSclaudio 			printf("%s", log_in6addr_scope(&k->nexthop, k->scope));
12758e709cbdSnorby 		else if (k->flags & F_CONNECTED)
12768e709cbdSnorby 			printf("link#%u", k->ifindex);
12778e709cbdSnorby 		printf("\n");
12788e709cbdSnorby 
12798e709cbdSnorby 		break;
12808e709cbdSnorby 	case IMSG_CTL_END:
12818e709cbdSnorby 		printf("\n");
12828e709cbdSnorby 		return (1);
12838e709cbdSnorby 	default:
12848e709cbdSnorby 		break;
12858e709cbdSnorby 	}
12868e709cbdSnorby 
12878e709cbdSnorby 	return (0);
12888e709cbdSnorby }
12898e709cbdSnorby 
12900f617141Sclaudio const struct if_status_description
12910f617141Sclaudio 		if_status_descriptions[] = LINK_STATE_DESCRIPTIONS;
12928e709cbdSnorby const struct ifmedia_description
12938e709cbdSnorby 		ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS;
12948e709cbdSnorby 
12958e709cbdSnorby const char *
12968e709cbdSnorby get_media_descr(int media_type)
12978e709cbdSnorby {
12988e709cbdSnorby 	const struct ifmedia_description	*p;
12998e709cbdSnorby 
13008e709cbdSnorby 	for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++)
13018e709cbdSnorby 		if (media_type == p->ifmt_word)
13028e709cbdSnorby 			return (p->ifmt_string);
13038e709cbdSnorby 
13048e709cbdSnorby 	return ("unknown");
13058e709cbdSnorby }
13068e709cbdSnorby 
13078e709cbdSnorby const char *
13088e709cbdSnorby get_linkstate(int media_type, int link_state)
13098e709cbdSnorby {
13100f617141Sclaudio 	const struct if_status_description *p;
13110f617141Sclaudio 	static char buf[8];
13128e709cbdSnorby 
13130f617141Sclaudio 	for (p = if_status_descriptions; p->ifs_string != NULL; p++) {
13140f617141Sclaudio 		if (LINK_STATE_DESC_MATCH(p, media_type, link_state))
13150f617141Sclaudio 			return (p->ifs_string);
13168e709cbdSnorby 	}
13170f617141Sclaudio 	snprintf(buf, sizeof(buf), "[#%d]", link_state);
13180f617141Sclaudio 	return (buf);
13198e709cbdSnorby }
13208e709cbdSnorby 
13218e709cbdSnorby void
13228e709cbdSnorby print_baudrate(u_int64_t baudrate)
13238e709cbdSnorby {
13248e709cbdSnorby 	if (baudrate > IF_Gbps(1))
13258e709cbdSnorby 		printf("%llu GBit/s", baudrate / IF_Gbps(1));
13268e709cbdSnorby 	else if (baudrate > IF_Mbps(1))
13278e709cbdSnorby 		printf("%llu MBit/s", baudrate / IF_Mbps(1));
13288e709cbdSnorby 	else if (baudrate > IF_Kbps(1))
13298e709cbdSnorby 		printf("%llu KBit/s", baudrate / IF_Kbps(1));
13308e709cbdSnorby 	else
13318e709cbdSnorby 		printf("%llu Bit/s", baudrate);
13328e709cbdSnorby }
1333