xref: /openbsd/usr.sbin/ospf6ctl/ospf6ctl.c (revision 8957b20d)
1*8957b20dSstsp /*	$OpenBSD: ospf6ctl.c,v 1.24 2009/01/30 22:23:30 stsp 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);
578e709cbdSnorby int		 show_db_msg_detail(struct imsg *imsg);
588e709cbdSnorby int		 show_nbr_msg(struct imsg *);
59aff6ccb8Sclaudio const char	*print_ospf_options(u_int32_t);
608e709cbdSnorby int		 show_nbr_detail_msg(struct imsg *);
618e709cbdSnorby int		 show_rib_msg(struct imsg *);
628e709cbdSnorby void		 show_rib_head(struct in_addr, u_int8_t, u_int8_t);
638e709cbdSnorby const char	*print_ospf_rtr_flags(u_int8_t);
648e709cbdSnorby int		 show_rib_detail_msg(struct imsg *);
658e709cbdSnorby void		 show_fib_head(void);
668e709cbdSnorby int		 show_fib_msg(struct imsg *);
678e709cbdSnorby const char *	 get_media_descr(int);
688e709cbdSnorby const char *	 get_linkstate(int, int);
698e709cbdSnorby void		 print_baudrate(u_int64_t);
708e709cbdSnorby 
718e709cbdSnorby struct imsgbuf	*ibuf;
728e709cbdSnorby 
738e709cbdSnorby __dead void
748e709cbdSnorby usage(void)
758e709cbdSnorby {
768e709cbdSnorby 	extern char *__progname;
778e709cbdSnorby 
785ff7227cSsobrado 	fprintf(stderr, "usage: %s command [argument ...]\n", __progname);
798e709cbdSnorby 	exit(1);
808e709cbdSnorby }
818e709cbdSnorby 
828e709cbdSnorby /* dummy function so that ospf6ctl does not need libevent */
838e709cbdSnorby void
848e709cbdSnorby imsg_event_add(struct imsgbuf *i)
858e709cbdSnorby {
868e709cbdSnorby 	/* nothing */
878e709cbdSnorby }
888e709cbdSnorby 
898e709cbdSnorby int
908e709cbdSnorby main(int argc, char *argv[])
918e709cbdSnorby {
928e709cbdSnorby 	struct sockaddr_un	 sun;
938e709cbdSnorby 	struct parse_result	*res;
948e709cbdSnorby 	struct imsg		 imsg;
958e709cbdSnorby 	unsigned int		 ifidx = 0;
968e709cbdSnorby 	int			 ctl_sock;
978e709cbdSnorby 	int			 done = 0;
988e709cbdSnorby 	int			 n;
998e709cbdSnorby 
1008e709cbdSnorby 	/* parse options */
1018e709cbdSnorby 	if ((res = parse(argc - 1, argv + 1)) == NULL)
1028e709cbdSnorby 		exit(1);
1038e709cbdSnorby 
1048e709cbdSnorby 	/* connect to ospf6d control socket */
1058e709cbdSnorby 	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
1068e709cbdSnorby 		err(1, "socket");
1078e709cbdSnorby 
1088e709cbdSnorby 	bzero(&sun, sizeof(sun));
1098e709cbdSnorby 	sun.sun_family = AF_UNIX;
1108e709cbdSnorby 	strlcpy(sun.sun_path, OSPF6D_SOCKET, sizeof(sun.sun_path));
1118e709cbdSnorby 	if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1)
1128e709cbdSnorby 		err(1, "connect: %s", OSPF6D_SOCKET);
1138e709cbdSnorby 
1148e709cbdSnorby 	if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
1158e709cbdSnorby 		err(1, NULL);
1168e709cbdSnorby 	imsg_init(ibuf, ctl_sock, NULL);
1178e709cbdSnorby 	done = 0;
1188e709cbdSnorby 
1198e709cbdSnorby 	/* process user request */
1208e709cbdSnorby 	switch (res->action) {
1218e709cbdSnorby 	case NONE:
1228e709cbdSnorby 		usage();
1238e709cbdSnorby 		/* not reached */
1248e709cbdSnorby 	case SHOW:
1258e709cbdSnorby 	case SHOW_SUM:
1268e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_SUM, 0, 0, NULL, 0);
1278e709cbdSnorby 		break;
1288e709cbdSnorby 	case SHOW_IFACE:
1291fed8bffSnorby 		printf("%-11s %-29s %-6s %-10s %-10s %-8s\n",
1308e709cbdSnorby 		    "Interface", "Address", "State", "HelloTimer", "Linkstate",
1311fed8bffSnorby 		    "Uptime");
132c5ba8b41Sderaadt 		/*FALLTHROUGH*/
1338e709cbdSnorby 	case SHOW_IFACE_DTAIL:
1348e709cbdSnorby 		if (*res->ifname) {
1358e709cbdSnorby 			ifidx = if_nametoindex(res->ifname);
1368e709cbdSnorby 			if (ifidx == 0)
1378e709cbdSnorby 				errx(1, "no such interface %s", res->ifname);
1388e709cbdSnorby 		}
1398e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0,
1408e709cbdSnorby 		    &ifidx, sizeof(ifidx));
1418e709cbdSnorby 		break;
1428e709cbdSnorby 	case SHOW_NBR:
143558ada41Snorby 		printf("%-15s %-3s %-12s %-9s %-11s %s\n", "ID", "Pri",
144558ada41Snorby 		    "State", "DeadTime", "Iface","Uptime");
145c5ba8b41Sderaadt 		/*FALLTHROUGH*/
1468e709cbdSnorby 	case SHOW_NBR_DTAIL:
1478e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, NULL, 0);
1488e709cbdSnorby 		break;
1498e709cbdSnorby 	case SHOW_DB:
1508e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, NULL, 0);
1518e709cbdSnorby 		break;
1528e709cbdSnorby 	case SHOW_DBBYAREA:
1538e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0,
1548e709cbdSnorby 		    &res->addr, sizeof(res->addr));
1558e709cbdSnorby 		break;
1568e709cbdSnorby 	case SHOW_DBEXT:
1578e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_EXT, 0, 0, NULL, 0);
1588e709cbdSnorby 		break;
159aeb06b08Sclaudio 	case SHOW_DBLINK:
160aeb06b08Sclaudio 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_LINK, 0, 0, NULL, 0);
161aeb06b08Sclaudio 		break;
1628e709cbdSnorby 	case SHOW_DBNET:
1638e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_NET, 0, 0, NULL, 0);
1648e709cbdSnorby 		break;
1658e709cbdSnorby 	case SHOW_DBRTR:
1668e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_RTR, 0, 0, NULL, 0);
1678e709cbdSnorby 		break;
16841bcac6bSstsp 	case SHOW_DBINTRA:
16941bcac6bSstsp 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_INTRA, 0, 0, NULL, 0);
17041bcac6bSstsp 		break;
1718e709cbdSnorby 	case SHOW_DBSELF:
1728e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SELF, 0, 0, NULL, 0);
1738e709cbdSnorby 		break;
1748e709cbdSnorby 	case SHOW_DBSUM:
1758e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SUM, 0, 0, NULL, 0);
1768e709cbdSnorby 		break;
1778e709cbdSnorby 	case SHOW_DBASBR:
1788e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_ASBR, 0, 0, NULL, 0);
1798e709cbdSnorby 		break;
1808e709cbdSnorby 	case SHOW_RIB:
1818e709cbdSnorby 		printf("%-20s %-17s %-12s %-9s %-7s %-8s\n", "Destination",
1828e709cbdSnorby 		    "Nexthop", "Path Type", "Type", "Cost", "Uptime");
183c5ba8b41Sderaadt 		/*FALLTHROUGH*/
1848e709cbdSnorby 	case SHOW_RIB_DTAIL:
1858e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, NULL, 0);
1868e709cbdSnorby 		break;
1878e709cbdSnorby 	case SHOW_FIB:
1880104e403Sclaudio 		if (IN6_IS_ADDR_UNSPECIFIED(&res->addr))
1898e709cbdSnorby 			imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0,
1908e709cbdSnorby 			    &res->flags, sizeof(res->flags));
1918e709cbdSnorby 		else
1928e709cbdSnorby 			imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0,
1938e709cbdSnorby 			    &res->addr, sizeof(res->addr));
1948e709cbdSnorby 		show_fib_head();
1958e709cbdSnorby 		break;
1968e709cbdSnorby 	case FIB:
1978e709cbdSnorby 		errx(1, "fib couple|decouple");
1988e709cbdSnorby 		break;
1998e709cbdSnorby 	case FIB_COUPLE:
2008e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, NULL, 0);
2018e709cbdSnorby 		printf("couple request sent.\n");
2028e709cbdSnorby 		done = 1;
2038e709cbdSnorby 		break;
2048e709cbdSnorby 	case FIB_DECOUPLE:
2058e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, NULL, 0);
2068e709cbdSnorby 		printf("decouple request sent.\n");
2078e709cbdSnorby 		done = 1;
2088e709cbdSnorby 		break;
2098e709cbdSnorby 	case RELOAD:
2108e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, NULL, 0);
2118e709cbdSnorby 		printf("reload request sent.\n");
2128e709cbdSnorby 		done = 1;
2138e709cbdSnorby 		break;
2148e709cbdSnorby 	}
2158e709cbdSnorby 
2168e709cbdSnorby 	while (ibuf->w.queued)
2178e709cbdSnorby 		if (msgbuf_write(&ibuf->w) < 0)
2188e709cbdSnorby 			err(1, "write error");
2198e709cbdSnorby 
2208e709cbdSnorby 	while (!done) {
2218e709cbdSnorby 		if ((n = imsg_read(ibuf)) == -1)
2228e709cbdSnorby 			errx(1, "imsg_read error");
2238e709cbdSnorby 		if (n == 0)
2248e709cbdSnorby 			errx(1, "pipe closed");
2258e709cbdSnorby 
2268e709cbdSnorby 		while (!done) {
2278e709cbdSnorby 			if ((n = imsg_get(ibuf, &imsg)) == -1)
2288e709cbdSnorby 				errx(1, "imsg_get error");
2298e709cbdSnorby 			if (n == 0)
2308e709cbdSnorby 				break;
2318e709cbdSnorby 			switch (res->action) {
2328e709cbdSnorby 			case SHOW:
2338e709cbdSnorby 			case SHOW_SUM:
2348e709cbdSnorby 				done = show_summary_msg(&imsg);
2358e709cbdSnorby 				break;
2368e709cbdSnorby 			case SHOW_IFACE:
2378e709cbdSnorby 				done = show_interface_msg(&imsg);
2388e709cbdSnorby 				break;
2398e709cbdSnorby 			case SHOW_IFACE_DTAIL:
2408e709cbdSnorby 				done = show_interface_detail_msg(&imsg);
2418e709cbdSnorby 				break;
2428e709cbdSnorby 			case SHOW_NBR:
2438e709cbdSnorby 				done = show_nbr_msg(&imsg);
2448e709cbdSnorby 				break;
2458e709cbdSnorby 			case SHOW_NBR_DTAIL:
2468e709cbdSnorby 				done = show_nbr_detail_msg(&imsg);
2478e709cbdSnorby 				break;
2488e709cbdSnorby 			case SHOW_DB:
2498e709cbdSnorby 			case SHOW_DBBYAREA:
2508e709cbdSnorby 			case SHOW_DBSELF:
2518e709cbdSnorby 				done = show_database_msg(&imsg);
2528e709cbdSnorby 				break;
2538e709cbdSnorby 			case SHOW_DBEXT:
254aeb06b08Sclaudio 			case SHOW_DBLINK:
2558e709cbdSnorby 			case SHOW_DBNET:
2568e709cbdSnorby 			case SHOW_DBRTR:
25741bcac6bSstsp 			case SHOW_DBINTRA:
2588e709cbdSnorby 			case SHOW_DBSUM:
2598e709cbdSnorby 			case SHOW_DBASBR:
2608e709cbdSnorby 				done = show_db_msg_detail(&imsg);
2618e709cbdSnorby 				break;
2628e709cbdSnorby 			case SHOW_RIB:
2638e709cbdSnorby 				done = show_rib_msg(&imsg);
2648e709cbdSnorby 				break;
2658e709cbdSnorby 			case SHOW_RIB_DTAIL:
2668e709cbdSnorby 				done = show_rib_detail_msg(&imsg);
2678e709cbdSnorby 				break;
2688e709cbdSnorby 			case SHOW_FIB:
2698e709cbdSnorby 				done = show_fib_msg(&imsg);
2708e709cbdSnorby 				break;
2718e709cbdSnorby 			case NONE:
2728e709cbdSnorby 			case FIB:
2738e709cbdSnorby 			case FIB_COUPLE:
2748e709cbdSnorby 			case FIB_DECOUPLE:
2758e709cbdSnorby 			case RELOAD:
2768e709cbdSnorby 				break;
2778e709cbdSnorby 			}
2788e709cbdSnorby 			imsg_free(&imsg);
2798e709cbdSnorby 		}
2808e709cbdSnorby 	}
2818e709cbdSnorby 	close(ctl_sock);
2828e709cbdSnorby 	free(ibuf);
2838e709cbdSnorby 
2848e709cbdSnorby 	return (0);
2858e709cbdSnorby }
2868e709cbdSnorby 
2878e709cbdSnorby int
2888e709cbdSnorby show_summary_msg(struct imsg *imsg)
2898e709cbdSnorby {
2908e709cbdSnorby 	struct ctl_sum		*sum;
2918e709cbdSnorby 	struct ctl_sum_area	*sumarea;
2928e709cbdSnorby 
2938e709cbdSnorby 	switch (imsg->hdr.type) {
2948e709cbdSnorby 	case IMSG_CTL_SHOW_SUM:
2958e709cbdSnorby 		sum = imsg->data;
2968e709cbdSnorby 		printf("Router ID: %s\n", inet_ntoa(sum->rtr_id));
2978e709cbdSnorby 		printf("Uptime: %s\n", fmt_timeframe_core(sum->uptime));
2988e709cbdSnorby 
2998e709cbdSnorby 		printf("SPF delay is %d sec(s), hold time between two SPFs "
3008e709cbdSnorby 		    "is %d sec(s)\n", sum->spf_delay, sum->spf_hold_time);
3018e709cbdSnorby 		printf("Number of external LSA(s) %d\n", sum->num_ext_lsa);
3028e709cbdSnorby 		printf("Number of areas attached to this router: %d\n",
3038e709cbdSnorby 		    sum->num_area);
3048e709cbdSnorby 		break;
3058e709cbdSnorby 	case IMSG_CTL_SHOW_SUM_AREA:
3068e709cbdSnorby 		sumarea = imsg->data;
3078e709cbdSnorby 		printf("\nArea ID: %s\n", inet_ntoa(sumarea->area));
3088e709cbdSnorby 		printf("  Number of interfaces in this area: %d\n",
3098e709cbdSnorby 		    sumarea->num_iface);
3108e709cbdSnorby 		printf("  Number of fully adjacent neighbors in this "
3118e709cbdSnorby 		    "area: %d\n", sumarea->num_adj_nbr);
3128e709cbdSnorby 		printf("  SPF algorithm executed %d time(s)\n",
3138e709cbdSnorby 		    sumarea->num_spf_calc);
3148e709cbdSnorby 		printf("  Number LSA(s) %d\n", sumarea->num_lsa);
3158e709cbdSnorby 		break;
3168e709cbdSnorby 	case IMSG_CTL_END:
3178e709cbdSnorby 		printf("\n");
3188e709cbdSnorby 		return (1);
3198e709cbdSnorby 	default:
3208e709cbdSnorby 		break;
3218e709cbdSnorby 	}
3228e709cbdSnorby 
3238e709cbdSnorby 	return (0);
3248e709cbdSnorby }
3258e709cbdSnorby 
3268e709cbdSnorby int
3278e709cbdSnorby get_ifms_type(int mediatype)
3288e709cbdSnorby {
3298e709cbdSnorby 	switch (mediatype) {
3308e709cbdSnorby 	case IFT_ETHER:
3318e709cbdSnorby 		return (IFM_ETHER);
3328e709cbdSnorby 	case IFT_FDDI:
3338e709cbdSnorby 		return (IFM_FDDI);
3348e709cbdSnorby 	case IFT_CARP:
3358e709cbdSnorby 		return (IFM_CARP);
3368e709cbdSnorby 	case IFT_PPP:
3378e709cbdSnorby 		return (IFM_TDM);
3388e709cbdSnorby 	default:
3398e709cbdSnorby 		return (0);
3408e709cbdSnorby 	}
3418e709cbdSnorby }
3428e709cbdSnorby 
3438e709cbdSnorby int
3448e709cbdSnorby show_interface_msg(struct imsg *imsg)
3458e709cbdSnorby {
3468e709cbdSnorby 	struct ctl_iface	*iface;
3478e709cbdSnorby 	char			*netid;
3488e709cbdSnorby 
3498e709cbdSnorby 	switch (imsg->hdr.type) {
3508e709cbdSnorby 	case IMSG_CTL_SHOW_INTERFACE:
3518e709cbdSnorby 		iface = imsg->data;
3528e709cbdSnorby 
3538e709cbdSnorby 		if (asprintf(&netid, "%s", log_in6addr(&iface->addr)) == -1)
3548e709cbdSnorby 			err(1, NULL);
3551fed8bffSnorby 		printf("%-11s %-29s %-6s %-10s %-10s %s\n",
3568e709cbdSnorby 		    iface->name, netid, if_state_name(iface->state),
3578e709cbdSnorby 		    fmt_timeframe_core(iface->hello_timer),
3588e709cbdSnorby 		    get_linkstate(get_ifms_type(iface->mediatype),
3591fed8bffSnorby 		    iface->linkstate), fmt_timeframe_core(iface->uptime));
3608e709cbdSnorby 		free(netid);
3618e709cbdSnorby 		break;
3628e709cbdSnorby 	case IMSG_CTL_END:
3638e709cbdSnorby 		printf("\n");
3648e709cbdSnorby 		return (1);
3658e709cbdSnorby 	default:
3668e709cbdSnorby 		break;
3678e709cbdSnorby 	}
3688e709cbdSnorby 
3698e709cbdSnorby 	return (0);
3708e709cbdSnorby }
3718e709cbdSnorby 
3728e709cbdSnorby int
3738e709cbdSnorby show_interface_detail_msg(struct imsg *imsg)
3748e709cbdSnorby {
3758e709cbdSnorby 	struct ctl_iface	*iface;
3768e709cbdSnorby 
3778e709cbdSnorby 	switch (imsg->hdr.type) {
3788e709cbdSnorby 	case IMSG_CTL_SHOW_INTERFACE:
3798e709cbdSnorby 		iface = imsg->data;
3808e709cbdSnorby 		printf("\n");
3818e709cbdSnorby 		printf("Interface %s, line protocol is %s\n",
3828e709cbdSnorby 		    iface->name, print_link(iface->flags));
383ab5e4d03Sclaudio 		printf("  Internet address %s Area %s\n",
384ab5e4d03Sclaudio 		    log_in6addr(&iface->addr), inet_ntoa(iface->area));
385ab5e4d03Sclaudio 		printf("  Link type %s, state %s",
386ab5e4d03Sclaudio 		    get_media_descr(get_ifms_type(iface->mediatype)),
3878e709cbdSnorby 		    get_linkstate(get_ifms_type(iface->mediatype),
3888e709cbdSnorby 		    iface->linkstate));
389ab5e4d03Sclaudio 		if (iface->linkstate != LINK_STATE_DOWN &&
390ab5e4d03Sclaudio 		    iface->baudrate > 0) {
391ab5e4d03Sclaudio 		    printf(", ");
392ab5e4d03Sclaudio 		    print_baudrate(iface->baudrate);
393ab5e4d03Sclaudio 		}
394ab5e4d03Sclaudio 		printf("\n");
3958e709cbdSnorby 		printf("  Router ID %s, network type %s, cost: %d\n",
3968e709cbdSnorby 		    inet_ntoa(iface->rtr_id),
3978e709cbdSnorby 		    if_type_name(iface->type), iface->metric);
3988e709cbdSnorby 		printf("  Transmit delay is %d sec(s), state %s, priority %d\n",
3998e709cbdSnorby 		    iface->transmit_delay, if_state_name(iface->state),
4008e709cbdSnorby 		    iface->priority);
4017aab4200Snorby 		printf("  Designated Router (ID) %s\n",
4028e709cbdSnorby 		    inet_ntoa(iface->dr_id));
4037aab4200Snorby 		printf("    Interface address %s\n",
4047aab4200Snorby 		    log_in6addr(&iface->dr_addr));
4057aab4200Snorby 		printf("  Backup Designated Router (ID) %s\n",
4068e709cbdSnorby 		    inet_ntoa(iface->bdr_id));
4077aab4200Snorby 		printf("    Interface address %s\n",
4087aab4200Snorby 		    log_in6addr(&iface->bdr_addr));
4098e709cbdSnorby 		printf("  Timer intervals configured, "
4108e709cbdSnorby 		    "hello %d, dead %d, wait %d, retransmit %d\n",
4118e709cbdSnorby 		     iface->hello_interval, iface->dead_interval,
4128e709cbdSnorby 		     iface->dead_interval, iface->rxmt_interval);
4138e709cbdSnorby 		if (iface->passive)
4148e709cbdSnorby 			printf("    Passive interface (No Hellos)\n");
4158e709cbdSnorby 		else if (iface->hello_timer < 0)
4168e709cbdSnorby 			printf("    Hello timer not running\n");
4178e709cbdSnorby 		else
4188e709cbdSnorby 			printf("    Hello timer due in %s\n",
4198e709cbdSnorby 			    fmt_timeframe_core(iface->hello_timer));
4208e709cbdSnorby 		printf("    Uptime %s\n", fmt_timeframe_core(iface->uptime));
4218e709cbdSnorby 		printf("  Neighbor count is %d, adjacent neighbor count is "
4228e709cbdSnorby 		    "%d\n", iface->nbr_cnt, iface->adj_cnt);
4238e709cbdSnorby 		break;
4248e709cbdSnorby 	case IMSG_CTL_END:
4258e709cbdSnorby 		printf("\n");
4268e709cbdSnorby 		return (1);
4278e709cbdSnorby 	default:
4288e709cbdSnorby 		break;
4298e709cbdSnorby 	}
4308e709cbdSnorby 
4318e709cbdSnorby 	return (0);
4328e709cbdSnorby }
4338e709cbdSnorby 
4348e709cbdSnorby const char *
4358e709cbdSnorby print_link(int state)
4368e709cbdSnorby {
4378e709cbdSnorby 	if (state & IFF_UP)
4388e709cbdSnorby 		return ("UP");
4398e709cbdSnorby 	else
4408e709cbdSnorby 		return ("DOWN");
4418e709cbdSnorby }
4428e709cbdSnorby 
4438e709cbdSnorby #define TF_BUFS	8
4448e709cbdSnorby #define TF_LEN	9
4458e709cbdSnorby 
4468e709cbdSnorby const char *
4478e709cbdSnorby fmt_timeframe(time_t t)
4488e709cbdSnorby {
4498e709cbdSnorby 	if (t == 0)
4508e709cbdSnorby 		return ("Never");
4518e709cbdSnorby 	else
4528e709cbdSnorby 		return (fmt_timeframe_core(time(NULL) - t));
4538e709cbdSnorby }
4548e709cbdSnorby 
4558e709cbdSnorby const char *
4568e709cbdSnorby fmt_timeframe_core(time_t t)
4578e709cbdSnorby {
4588e709cbdSnorby 	char		*buf;
4598e709cbdSnorby 	static char	 tfbuf[TF_BUFS][TF_LEN];	/* ring buffer */
4608e709cbdSnorby 	static int	 idx = 0;
461db93f2f1Sderaadt 	unsigned int	 sec, min, hrs, day, week;
4628e709cbdSnorby 
4638e709cbdSnorby 	if (t == 0)
4648e709cbdSnorby 		return ("00:00:00");
4658e709cbdSnorby 
4668e709cbdSnorby 	buf = tfbuf[idx++];
4678e709cbdSnorby 	if (idx == TF_BUFS)
4688e709cbdSnorby 		idx = 0;
4698e709cbdSnorby 
4708e709cbdSnorby 	week = t;
4718e709cbdSnorby 
4728e709cbdSnorby 	sec = week % 60;
4738e709cbdSnorby 	week /= 60;
4748e709cbdSnorby 	min = week % 60;
4758e709cbdSnorby 	week /= 60;
4768e709cbdSnorby 	hrs = week % 24;
4778e709cbdSnorby 	week /= 24;
4788e709cbdSnorby 	day = week % 7;
4798e709cbdSnorby 	week /= 7;
4808e709cbdSnorby 
4818e709cbdSnorby 	if (week > 0)
4828e709cbdSnorby 		snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs);
4838e709cbdSnorby 	else if (day > 0)
4848e709cbdSnorby 		snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
4858e709cbdSnorby 	else
4868e709cbdSnorby 		snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
4878e709cbdSnorby 
4888e709cbdSnorby 	return (buf);
4898e709cbdSnorby }
4908e709cbdSnorby 
4918e709cbdSnorby const char *
4928e709cbdSnorby log_id(u_int32_t id)
4938e709cbdSnorby {
4948e709cbdSnorby 	static char	buf[48];
4958e709cbdSnorby 	struct in_addr	addr;
4968e709cbdSnorby 
4978e709cbdSnorby 	addr.s_addr = id;
4988e709cbdSnorby 
4998e709cbdSnorby 	if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL)
5008e709cbdSnorby 		return ("?");
5018e709cbdSnorby 	else
5028e709cbdSnorby 		return (buf);
5038e709cbdSnorby }
5048e709cbdSnorby 
5058e709cbdSnorby const char *
5068e709cbdSnorby log_adv_rtr(u_int32_t adv_rtr)
5078e709cbdSnorby {
5088e709cbdSnorby 	static char	buf[48];
5098e709cbdSnorby 	struct in_addr	addr;
5108e709cbdSnorby 
5118e709cbdSnorby 	addr.s_addr = adv_rtr;
5128e709cbdSnorby 
5138e709cbdSnorby 	if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL)
5148e709cbdSnorby 		return ("?");
5158e709cbdSnorby 	else
5168e709cbdSnorby 		return (buf);
5178e709cbdSnorby }
5188e709cbdSnorby 
5198e709cbdSnorby void
520cb01fa27Sclaudio show_database_head(struct in_addr aid, char *ifname, u_int16_t type)
5218e709cbdSnorby {
5228e709cbdSnorby 	char	*header, *format;
523cb01fa27Sclaudio 	int	cleanup = 0;
5248e709cbdSnorby 
525005d568eSclaudio 	switch (ntohs(type)) {
5264fabe8f9Snorby 	case LSA_TYPE_LINK:
5278ea4c735Sclaudio 		format = "Link (Type-8) Link States";
5284fabe8f9Snorby 		break;
5298e709cbdSnorby 	case LSA_TYPE_ROUTER:
5308e709cbdSnorby 		format = "Router Link States";
5318e709cbdSnorby 		break;
5328e709cbdSnorby 	case LSA_TYPE_NETWORK:
5338e709cbdSnorby 		format = "Net Link States";
5348e709cbdSnorby 		break;
5354fabe8f9Snorby 	case LSA_TYPE_INTER_A_PREFIX:
5364fabe8f9Snorby 		format = "Inter Area Prefix Link States";
5378e709cbdSnorby 		break;
5384fabe8f9Snorby 	case LSA_TYPE_INTER_A_ROUTER:
5394fabe8f9Snorby 		format = "Inter Area Router Link States";
5404fabe8f9Snorby 		break;
5414fabe8f9Snorby 	case LSA_TYPE_INTRA_A_PREFIX:
5428ec36425Sstsp 		format = "Intra Area Prefix Link States";
5438e709cbdSnorby 		break;
5448e709cbdSnorby 	case LSA_TYPE_EXTERNAL:
545cb01fa27Sclaudio 		printf("\n%-15s %s\n\n", "", "Type-5 AS External Link States");
546cb01fa27Sclaudio 		return;
5478e709cbdSnorby 	default:
548cb01fa27Sclaudio 		if (asprintf(&format, "LSA type %x", ntohs(type)) == -1)
549cb01fa27Sclaudio 			err(1, NULL);
550cb01fa27Sclaudio 		cleanup = 1;
551cb01fa27Sclaudio 		break;
5528e709cbdSnorby 	}
553cb01fa27Sclaudio 	if (LSA_IS_SCOPE_AREA(ntohs(type))) {
5548e709cbdSnorby 		if (asprintf(&header, "%s (Area %s)", format,
5558e709cbdSnorby 		    inet_ntoa(aid)) == -1)
5568e709cbdSnorby 			err(1, NULL);
557cb01fa27Sclaudio 	} else if (LSA_IS_SCOPE_LLOCAL(ntohs(type))) {
558cb01fa27Sclaudio 		if (asprintf(&header, "%s (Area %s Interface %s)", format,
559cb01fa27Sclaudio 		    inet_ntoa(aid), ifname) == -1)
560cb01fa27Sclaudio 			err(1, NULL);
561cb01fa27Sclaudio 	}
5628e709cbdSnorby 
5638e709cbdSnorby 	printf("\n%-15s %s\n\n", "", header);
5648e709cbdSnorby 	free(header);
565cb01fa27Sclaudio 	if (cleanup)
566cb01fa27Sclaudio 		free(format);
5678e709cbdSnorby }
5688e709cbdSnorby 
5698e709cbdSnorby int
5708e709cbdSnorby show_database_msg(struct imsg *imsg)
5718e709cbdSnorby {
5728e709cbdSnorby 	static struct in_addr	 area_id;
5730bc8b661Sclaudio 	static u_int16_t	 lasttype;
574cb01fa27Sclaudio 	static char		 ifname[IF_NAMESIZE];
5758e709cbdSnorby 	struct area		*area;
576cb01fa27Sclaudio 	struct iface		*iface;
5778e709cbdSnorby 	struct lsa_hdr		*lsa;
5788e709cbdSnorby 
5798e709cbdSnorby 	switch (imsg->hdr.type) {
5808e709cbdSnorby 	case IMSG_CTL_SHOW_DATABASE:
5818e709cbdSnorby 	case IMSG_CTL_SHOW_DB_SELF:
5828e709cbdSnorby 		lsa = imsg->data;
5838e709cbdSnorby 		if (lsa->type != lasttype) {
584cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->type);
5858e709cbdSnorby 			printf("%-15s %-15s %-4s %-10s %-8s\n", "Link ID",
5868e709cbdSnorby 			    "Adv Router", "Age", "Seq#", "Checksum");
5878e709cbdSnorby 		}
5888e709cbdSnorby 		printf("%-15s %-15s %-4d 0x%08x 0x%04x\n",
5898e709cbdSnorby 		    log_id(lsa->ls_id), log_adv_rtr(lsa->adv_rtr),
5908e709cbdSnorby 		    ntohs(lsa->age), ntohl(lsa->seq_num),
5918e709cbdSnorby 		    ntohs(lsa->ls_chksum));
5928e709cbdSnorby 		lasttype = lsa->type;
5938e709cbdSnorby 		break;
5948e709cbdSnorby 	case IMSG_CTL_AREA:
5958e709cbdSnorby 		area = imsg->data;
5968e709cbdSnorby 		area_id = area->id;
5978e709cbdSnorby 		lasttype = 0;
5988e709cbdSnorby 		break;
599cb01fa27Sclaudio 	case IMSG_CTL_IFACE:
600cb01fa27Sclaudio 		iface = imsg->data;
601cb01fa27Sclaudio 		strlcpy(ifname, iface->name, sizeof(ifname));
602cb01fa27Sclaudio 		lasttype = 0;
603cb01fa27Sclaudio 		break;
6048e709cbdSnorby 	case IMSG_CTL_END:
6058e709cbdSnorby 		printf("\n");
6068e709cbdSnorby 		return (1);
6078e709cbdSnorby 	default:
6088e709cbdSnorby 		break;
6098e709cbdSnorby 	}
6108e709cbdSnorby 
6118e709cbdSnorby 	return (0);
6128e709cbdSnorby }
6138e709cbdSnorby 
6148e709cbdSnorby char *
6154fabe8f9Snorby print_ls_type(u_int16_t type)
6168e709cbdSnorby {
617005d568eSclaudio 	switch (ntohs(type)) {
6184fabe8f9Snorby 	case LSA_TYPE_LINK:
6194fabe8f9Snorby 		return ("Link");
6208e709cbdSnorby 	case LSA_TYPE_ROUTER:
6218e709cbdSnorby 		return ("Router");
6228e709cbdSnorby 	case LSA_TYPE_NETWORK:
6238e709cbdSnorby 		return ("Network");
6244fabe8f9Snorby 	case LSA_TYPE_INTER_A_PREFIX:
6254fabe8f9Snorby 		return ("Inter Area (Prefix)");
6264fabe8f9Snorby 	case LSA_TYPE_INTER_A_ROUTER:
6274fabe8f9Snorby 		return ("Inter Area (Router)");
6284fabe8f9Snorby 	case LSA_TYPE_INTRA_A_PREFIX:
6294fabe8f9Snorby 		return ("Intra Area (Prefix)");
6308e709cbdSnorby 	case LSA_TYPE_EXTERNAL:
6318e709cbdSnorby 		return ("AS External");
6328e709cbdSnorby 	default:
6338e709cbdSnorby 		return ("Unknown");
6348e709cbdSnorby 	}
6358e709cbdSnorby }
6368e709cbdSnorby 
6378e709cbdSnorby void
6388e709cbdSnorby show_db_hdr_msg_detail(struct lsa_hdr *lsa)
6398e709cbdSnorby {
6408e709cbdSnorby 	printf("LS age: %d\n", ntohs(lsa->age));
6418e709cbdSnorby 	printf("LS Type: %s\n", print_ls_type(lsa->type));
6428e709cbdSnorby 
643005d568eSclaudio 	switch (ntohs(lsa->type)) {
64489f180e4Sstsp 	case LSA_TYPE_ROUTER:
64589f180e4Sstsp 	case LSA_TYPE_INTER_A_PREFIX:
64689f180e4Sstsp 	case LSA_TYPE_INTER_A_ROUTER:
64789f180e4Sstsp 	case LSA_TYPE_INTRA_A_PREFIX:
64889f180e4Sstsp 	case LSA_TYPE_EXTERNAL:
6494fabe8f9Snorby 		printf("Link State ID: %s\n", log_id(lsa->ls_id));
6504fabe8f9Snorby 		break;
65189f180e4Sstsp 	case LSA_TYPE_LINK:
65289f180e4Sstsp 		printf("Link State ID: %s (Interface ID of Advertising "
65389f180e4Sstsp 		    "Router)\n", log_id(lsa->ls_id));
6548e709cbdSnorby 		break;
6558e709cbdSnorby 	case LSA_TYPE_NETWORK:
65689f180e4Sstsp 		printf("Link State ID: %s (Interface ID of Designated "
65789f180e4Sstsp 		    "Router)\n", log_id(lsa->ls_id));
6588e709cbdSnorby 		break;
6598e709cbdSnorby 	}
6608e709cbdSnorby 
6618e709cbdSnorby 	printf("Advertising Router: %s\n", log_adv_rtr(lsa->adv_rtr));
6628e709cbdSnorby 	printf("LS Seq Number: 0x%08x\n", ntohl(lsa->seq_num));
6638e709cbdSnorby 	printf("Checksum: 0x%04x\n", ntohs(lsa->ls_chksum));
6648e709cbdSnorby 	printf("Length: %d\n", ntohs(lsa->len));
6658e709cbdSnorby }
6668e709cbdSnorby 
6678e709cbdSnorby char *
6688e709cbdSnorby print_rtr_link_type(u_int8_t type)
6698e709cbdSnorby {
6708e709cbdSnorby 	switch (type) {
6718e709cbdSnorby 	case LINK_TYPE_POINTTOPOINT:
6728e709cbdSnorby 		return ("Point-to-Point");
6738e709cbdSnorby 	case LINK_TYPE_TRANSIT_NET:
6748e709cbdSnorby 		return ("Transit Network");
675005d568eSclaudio 	case LINK_TYPE_RESERVED:
676005d568eSclaudio 		return ("Reserved");
6778e709cbdSnorby 	case LINK_TYPE_VIRTUAL:
6788e709cbdSnorby 		return ("Virtual Link");
6798e709cbdSnorby 	default:
6808e709cbdSnorby 		return ("Unknown");
6818e709cbdSnorby 	}
6828e709cbdSnorby }
6838e709cbdSnorby 
6848e709cbdSnorby const char *
6858e709cbdSnorby print_ospf_flags(u_int8_t opts)
6868e709cbdSnorby {
6878e709cbdSnorby 	static char	optbuf[32];
6888e709cbdSnorby 
689aff6ccb8Sclaudio 	snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s",
6908e709cbdSnorby 	    opts & OSPF_RTR_V ? "V" : "-",
6918e709cbdSnorby 	    opts & OSPF_RTR_E ? "E" : "-",
6928e709cbdSnorby 	    opts & OSPF_RTR_B ? "B" : "-");
6938e709cbdSnorby 	return (optbuf);
6948e709cbdSnorby }
6958e709cbdSnorby 
6968e709cbdSnorby int
6978e709cbdSnorby show_db_msg_detail(struct imsg *imsg)
6988e709cbdSnorby {
6998e709cbdSnorby 	static struct in_addr	 area_id;
700cb01fa27Sclaudio 	static char		 ifname[IF_NAMESIZE];
701005d568eSclaudio 	static u_int16_t	 lasttype;
7028e709cbdSnorby 	struct in_addr		 addr, data;
7038e709cbdSnorby 	struct area		*area;
704cb01fa27Sclaudio 	struct iface		*iface;
7058e709cbdSnorby 	struct lsa		*lsa;
7068e709cbdSnorby 	struct lsa_rtr_link	*rtr_link;
707aeb06b08Sclaudio 	struct lsa_prefix	*prefix;
7088e709cbdSnorby 	struct lsa_asext	*asext;
7098e709cbdSnorby 	u_int16_t		 i, nlinks, off;
7108e709cbdSnorby 
7118e709cbdSnorby 	/* XXX sanity checks! */
7128e709cbdSnorby 
7138e709cbdSnorby 	switch (imsg->hdr.type) {
7148e709cbdSnorby 	case IMSG_CTL_SHOW_DB_EXT:
7158e709cbdSnorby 		lsa = imsg->data;
7168e709cbdSnorby 		if (lsa->hdr.type != lasttype)
717cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
7188e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
7198e709cbdSnorby 		addr.s_addr = lsa->data.asext.mask;
7208e709cbdSnorby 		printf("Network Mask: %s\n", inet_ntoa(addr));
7218e709cbdSnorby 
7228e709cbdSnorby 		asext = (struct lsa_asext *)((char *)lsa + sizeof(lsa->hdr));
7238e709cbdSnorby 
7248e709cbdSnorby 		printf("    Metric type: ");
7258e709cbdSnorby 		if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_E_FLAG)
7268e709cbdSnorby 			printf("2\n");
7278e709cbdSnorby 		else
7288e709cbdSnorby 			printf("1\n");
7298e709cbdSnorby 		printf("    Metric: %d\n", ntohl(asext->metric)
7308e709cbdSnorby 		    & LSA_METRIC_MASK);
7318e709cbdSnorby 		addr.s_addr = asext->fw_addr;
7328e709cbdSnorby 		printf("    Forwarding Address: %s\n", inet_ntoa(addr));
7338e709cbdSnorby 		printf("    External Route Tag: %d\n\n", ntohl(asext->ext_tag));
7348e709cbdSnorby 
7358e709cbdSnorby 		lasttype = lsa->hdr.type;
7368e709cbdSnorby 		break;
737aeb06b08Sclaudio 	case IMSG_CTL_SHOW_DB_LINK:
738aeb06b08Sclaudio 		lsa = imsg->data;
739aeb06b08Sclaudio 		if (lsa->hdr.type != lasttype)
740aeb06b08Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
741aeb06b08Sclaudio 		show_db_hdr_msg_detail(&lsa->hdr);
7425a54ac3cSclaudio 		printf("Options: %s\n", print_ospf_options(LSA_24_GETLO(
7435a54ac3cSclaudio 		    ntohl(lsa->data.link.opts))));
7445a54ac3cSclaudio 		printf("Link Local Address: %s\n",
7455a54ac3cSclaudio 		    log_in6addr(&lsa->data.link.lladdr));
746aeb06b08Sclaudio 
747aeb06b08Sclaudio 		nlinks = ntohl(lsa->data.link.numprefix);
748aeb06b08Sclaudio 		printf("Number of Prefixes: %d\n", nlinks);
749aeb06b08Sclaudio 		off = sizeof(lsa->hdr) + sizeof(struct lsa_link);
750aeb06b08Sclaudio 
751aeb06b08Sclaudio 		for (i = 0; i < nlinks; i++) {
7525a54ac3cSclaudio 			struct in6_addr	ia6;
753aeb06b08Sclaudio 			prefix = (struct lsa_prefix *)((char *)lsa + off);
7545a54ac3cSclaudio 			bzero(&ia6, sizeof(ia6));
7555a54ac3cSclaudio 			bcopy(prefix + 1, &ia6,
7565a54ac3cSclaudio 			    LSA_PREFIXSIZE(prefix->prefixlen));
757aeb06b08Sclaudio 
7585a54ac3cSclaudio 			printf("    Prefix Address: %s\n", log_in6addr(&ia6));
7595a54ac3cSclaudio 			printf("    Prefix Length: %d, Options: %x\n",
7605a54ac3cSclaudio 			    prefix->prefixlen, prefix->options);
761aeb06b08Sclaudio 
76208720e8dSstsp 			off += sizeof(struct lsa_prefix)
76308720e8dSstsp 			    + LSA_PREFIXSIZE(prefix->prefixlen);
764aeb06b08Sclaudio 		}
765aeb06b08Sclaudio 
766aeb06b08Sclaudio 		printf("\n");
767aeb06b08Sclaudio 		lasttype = lsa->hdr.type;
768aeb06b08Sclaudio 		break;
7698e709cbdSnorby 	case IMSG_CTL_SHOW_DB_NET:
7708e709cbdSnorby 		lsa = imsg->data;
7718e709cbdSnorby 		if (lsa->hdr.type != lasttype)
772cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
7738e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
7740bc8b661Sclaudio 		printf("Options: %s\n",
7750bc8b661Sclaudio 		    print_ospf_options(LSA_24_GETLO(ntohl(lsa->data.net.opts))));
7768e709cbdSnorby 
7778e709cbdSnorby 		nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr)
7788e709cbdSnorby 		    - sizeof(u_int32_t)) / sizeof(struct lsa_net_link);
7798e709cbdSnorby 		off = sizeof(lsa->hdr) + sizeof(u_int32_t);
780aeb06b08Sclaudio 		printf("Number of Routers: %d\n", nlinks);
7818e709cbdSnorby 
7828e709cbdSnorby 		for (i = 0; i < nlinks; i++) {
7838e709cbdSnorby 			addr.s_addr = lsa->data.net.att_rtr[i];
7848e709cbdSnorby 			printf("    Attached Router: %s\n", inet_ntoa(addr));
7858e709cbdSnorby 		}
7868e709cbdSnorby 
7878e709cbdSnorby 		printf("\n");
7888e709cbdSnorby 		lasttype = lsa->hdr.type;
7898e709cbdSnorby 		break;
7908e709cbdSnorby 	case IMSG_CTL_SHOW_DB_RTR:
7918e709cbdSnorby 		lsa = imsg->data;
7928e709cbdSnorby 		if (lsa->hdr.type != lasttype)
793cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
7948e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
7959d28d229Sclaudio 		printf("Flags: %s\n",
796aff6ccb8Sclaudio 		    print_ospf_flags(LSA_24_GETHI(ntohl(lsa->data.rtr.opts))));
7979d28d229Sclaudio 		printf("Options: %s\n",
798aff6ccb8Sclaudio 		    print_ospf_options(LSA_24_GETLO(ntohl(lsa->data.rtr.opts))));
7999d28d229Sclaudio 
8009d28d229Sclaudio 		nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr)
8019d28d229Sclaudio 		    - sizeof(u_int32_t)) / sizeof(struct lsa_rtr_link);
802aeb06b08Sclaudio 		printf("Number of Links: %d\n", nlinks);
8038e709cbdSnorby 
8048e709cbdSnorby 		off = sizeof(lsa->hdr) + sizeof(struct lsa_rtr);
8058e709cbdSnorby 
8068e709cbdSnorby 		for (i = 0; i < nlinks; i++) {
8078e709cbdSnorby 			rtr_link = (struct lsa_rtr_link *)((char *)lsa + off);
8088e709cbdSnorby 
8098e709cbdSnorby 			printf("    Link connected to: %s\n",
8108e709cbdSnorby 			    print_rtr_link_type(rtr_link->type));
8118e709cbdSnorby 
812005d568eSclaudio 			addr.s_addr = rtr_link->nbr_rtr_id;
813005d568eSclaudio 			data.s_addr = rtr_link->iface_id;
8148e709cbdSnorby 
8158e709cbdSnorby 			switch (rtr_link->type) {
8168e709cbdSnorby 			case LINK_TYPE_POINTTOPOINT:
8178e709cbdSnorby 			case LINK_TYPE_VIRTUAL:
818005d568eSclaudio 				printf("    Router ID: %s\n", inet_ntoa(addr));
819005d568eSclaudio 				printf("    Interface ID: %s\n",
820005d568eSclaudio 				    inet_ntoa(data));
8218e709cbdSnorby 				break;
8228e709cbdSnorby 			case LINK_TYPE_TRANSIT_NET:
823005d568eSclaudio 				printf("    Designated Router ID: %s\n",
8248e709cbdSnorby 				    inet_ntoa(addr));
825005d568eSclaudio 				printf("    DR Interface ID: %s\n",
8268e709cbdSnorby 				    inet_ntoa(data));
8278e709cbdSnorby 				break;
8288e709cbdSnorby 			default:
829005d568eSclaudio 				printf("    Link ID (Unknown type %d): %s\n",
830005d568eSclaudio 				    rtr_link->type, inet_ntoa(addr));
8318e709cbdSnorby 				printf("    Link Data (Unknown): %s\n",
8328e709cbdSnorby 				    inet_ntoa(data));
8338e709cbdSnorby 				break;
8348e709cbdSnorby 			}
8358e709cbdSnorby 
8368e709cbdSnorby 			printf("    Metric: %d\n\n", ntohs(rtr_link->metric));
8378e709cbdSnorby 
838005d568eSclaudio 			off += sizeof(struct lsa_rtr_link);
8398e709cbdSnorby 		}
8408e709cbdSnorby 
8418e709cbdSnorby 		lasttype = lsa->hdr.type;
8428e709cbdSnorby 		break;
84341bcac6bSstsp 	case IMSG_CTL_SHOW_DB_INTRA:
84441bcac6bSstsp 		lsa = imsg->data;
84541bcac6bSstsp 		if (lsa->hdr.type != lasttype)
84641bcac6bSstsp 			show_database_head(area_id, ifname, lsa->hdr.type);
84741bcac6bSstsp 		show_db_hdr_msg_detail(&lsa->hdr);
84841bcac6bSstsp 		printf("Referenced LS Type: %s\n",
84941bcac6bSstsp 		    print_ls_type(lsa->data.pref_intra.ref_type));
85041bcac6bSstsp 		addr.s_addr = lsa->data.pref_intra.ref_lsid;
85141bcac6bSstsp 		printf("Referenced Link State ID: %s\n", inet_ntoa(addr));
85241bcac6bSstsp 		addr.s_addr = lsa->data.pref_intra.ref_adv_rtr;
85341bcac6bSstsp 		printf("Referenced Advertising Router: %s\n", inet_ntoa(addr));
85441bcac6bSstsp 		nlinks = ntohs(lsa->data.pref_intra.numprefix);
85541bcac6bSstsp 		printf("Number of Prefixes: %d\n", nlinks);
85641bcac6bSstsp 
85741bcac6bSstsp 		off = sizeof(lsa->hdr) + sizeof(struct lsa_intra_prefix);
85841bcac6bSstsp 
85941bcac6bSstsp 		for (i = 0; i < nlinks; i++) {
86041bcac6bSstsp 			struct in6_addr	ia6;
86141bcac6bSstsp 			prefix = (struct lsa_prefix *)((char *)lsa + off);
86241bcac6bSstsp 			bzero(&ia6, sizeof(ia6));
86341bcac6bSstsp 			bcopy(prefix + 1, &ia6,
86441bcac6bSstsp 			    LSA_PREFIXSIZE(prefix->prefixlen));
86541bcac6bSstsp 
86641bcac6bSstsp 			printf("    Prefix Address: %s\n", log_in6addr(&ia6));
86741bcac6bSstsp 			printf("    Prefix Length: %d, Options: %x\n",
86841bcac6bSstsp 			    prefix->prefixlen, prefix->options);
86941bcac6bSstsp 
87008720e8dSstsp 			off += sizeof(struct lsa_prefix)
87108720e8dSstsp 			    + LSA_PREFIXSIZE(prefix->prefixlen);
87241bcac6bSstsp 		}
8739415b30cSstsp 
8749415b30cSstsp 		printf("\n");
8759415b30cSstsp 		lasttype = lsa->hdr.type;
87641bcac6bSstsp 		break;
8778e709cbdSnorby 	case IMSG_CTL_SHOW_DB_SUM:
8788e709cbdSnorby 		lsa = imsg->data;
8798e709cbdSnorby 		if (lsa->hdr.type != lasttype)
880cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
8818e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
882cb01fa27Sclaudio 		printf("Prefix: XXX\n");
883aeb06b08Sclaudio 		printf("Metric: %d\n", ntohl(lsa->data.pref_sum.metric) &
8848e709cbdSnorby 		    LSA_METRIC_MASK);
8858e709cbdSnorby 		lasttype = lsa->hdr.type;
8868e709cbdSnorby 		break;
887cb01fa27Sclaudio 	case IMSG_CTL_SHOW_DB_ASBR:
888cb01fa27Sclaudio 		lsa = imsg->data;
889cb01fa27Sclaudio 		if (lsa->hdr.type != lasttype)
890cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
891cb01fa27Sclaudio 		show_db_hdr_msg_detail(&lsa->hdr);
892cb01fa27Sclaudio 
893cb01fa27Sclaudio 		addr.s_addr = lsa->data.rtr_sum.dest_rtr_id;
894cb01fa27Sclaudio 		printf("Destination Router ID: %s\n", inet_ntoa(addr));
895cb01fa27Sclaudio 		printf("Options: %s\n",
896aeb06b08Sclaudio 		    print_ospf_options(ntohl(lsa->data.rtr_sum.opts)));
897cb01fa27Sclaudio 		printf("Metric: %d\n\n", ntohl(lsa->data.rtr_sum.metric) &
898cb01fa27Sclaudio 		    LSA_METRIC_MASK);
8998e709cbdSnorby 	case IMSG_CTL_AREA:
9008e709cbdSnorby 		area = imsg->data;
9018e709cbdSnorby 		area_id = area->id;
9028e709cbdSnorby 		lasttype = 0;
9038e709cbdSnorby 		break;
904cb01fa27Sclaudio 	case IMSG_CTL_IFACE:
905cb01fa27Sclaudio 		iface = imsg->data;
906cb01fa27Sclaudio 		strlcpy(ifname, iface->name, sizeof(ifname));
907cb01fa27Sclaudio 		lasttype = 0;
908cb01fa27Sclaudio 		break;
9098e709cbdSnorby 	case IMSG_CTL_END:
9108e709cbdSnorby 		return (1);
9118e709cbdSnorby 	default:
9128e709cbdSnorby 		break;
9138e709cbdSnorby 	}
9148e709cbdSnorby 
9158e709cbdSnorby 	return (0);
9168e709cbdSnorby }
9178e709cbdSnorby 
9188e709cbdSnorby int
9198e709cbdSnorby show_nbr_msg(struct imsg *imsg)
9208e709cbdSnorby {
9218e709cbdSnorby 	struct ctl_nbr	*nbr;
9228e709cbdSnorby 	char		*state;
9238e709cbdSnorby 
9248e709cbdSnorby 	switch (imsg->hdr.type) {
9258e709cbdSnorby 	case IMSG_CTL_SHOW_NBR:
9268e709cbdSnorby 		nbr = imsg->data;
9278e709cbdSnorby 		if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state),
9288e709cbdSnorby 		    if_state_name(nbr->iface_state)) == -1)
9298e709cbdSnorby 			err(1, NULL);
930558ada41Snorby 		printf("%-15s %-3d %-12s %-10s", inet_ntoa(nbr->id),
9318e709cbdSnorby 		    nbr->priority, state, fmt_timeframe_core(nbr->dead_timer));
932558ada41Snorby 		printf("%-11s %s\n", nbr->name,
9338e709cbdSnorby 		    nbr->uptime == 0 ? "-" : fmt_timeframe_core(nbr->uptime));
9348e709cbdSnorby 		free(state);
9358e709cbdSnorby 		break;
9368e709cbdSnorby 	case IMSG_CTL_END:
9378e709cbdSnorby 		printf("\n");
9388e709cbdSnorby 		return (1);
9398e709cbdSnorby 	default:
9408e709cbdSnorby 		break;
9418e709cbdSnorby 	}
9428e709cbdSnorby 
9438e709cbdSnorby 	return (0);
9448e709cbdSnorby }
9458e709cbdSnorby 
9468e709cbdSnorby const char *
947aff6ccb8Sclaudio print_ospf_options(u_int32_t opts)
9488e709cbdSnorby {
9498e709cbdSnorby 	static char	optbuf[32];
9508e709cbdSnorby 
951aff6ccb8Sclaudio 	snprintf(optbuf, sizeof(optbuf), "*|*|%s|%s|%s|*|%s|%s",
9528e709cbdSnorby 	    opts & OSPF_OPTION_DC ? "DC" : "-",
9538e709cbdSnorby 	    opts & OSPF_OPTION_R ? "R" : "-",
9548e709cbdSnorby 	    opts & OSPF_OPTION_N ? "N" : "-",
9558e709cbdSnorby 	    opts & OSPF_OPTION_E ? "E" : "-",
9568e709cbdSnorby 	    opts & OSPF_OPTION_V6 ? "V6" : "-");
9578e709cbdSnorby 	return (optbuf);
9588e709cbdSnorby }
9598e709cbdSnorby 
9608e709cbdSnorby int
9618e709cbdSnorby show_nbr_detail_msg(struct imsg *imsg)
9628e709cbdSnorby {
9638e709cbdSnorby 	struct ctl_nbr	*nbr;
9648e709cbdSnorby 
9658e709cbdSnorby 	switch (imsg->hdr.type) {
9668e709cbdSnorby 	case IMSG_CTL_SHOW_NBR:
9678e709cbdSnorby 		nbr = imsg->data;
9688e709cbdSnorby 		printf("\nNeighbor %s, ", inet_ntoa(nbr->id));
9698e709cbdSnorby 		printf("interface address %s\n", log_in6addr(&nbr->addr));
9708e709cbdSnorby 		printf("  Area %s, interface %s\n", inet_ntoa(nbr->area),
9718e709cbdSnorby 		    nbr->name);
9728e709cbdSnorby 		printf("  Neighbor priority is %d, "
9738e709cbdSnorby 		    "State is %s, %d state changes\n",
9748e709cbdSnorby 		    nbr->priority, nbr_state_name(nbr->nbr_state),
9758e709cbdSnorby 		    nbr->state_chng_cnt);
9768e709cbdSnorby 		printf("  DR is %s, ", inet_ntoa(nbr->dr));
9778e709cbdSnorby 		printf("BDR is %s\n", inet_ntoa(nbr->bdr));
9788e709cbdSnorby 		printf("  Options %s\n", print_ospf_options(nbr->options));
9798e709cbdSnorby 		printf("  Dead timer due in %s\n",
9808e709cbdSnorby 		    fmt_timeframe_core(nbr->dead_timer));
9818e709cbdSnorby 		printf("  Uptime %s\n", fmt_timeframe_core(nbr->uptime));
9828e709cbdSnorby 		printf("  Database Summary List %d\n", nbr->db_sum_lst_cnt);
9838e709cbdSnorby 		printf("  Link State Request List %d\n", nbr->ls_req_lst_cnt);
9848e709cbdSnorby 		printf("  Link State Retransmission List %d\n",
9858e709cbdSnorby 		    nbr->ls_retrans_lst_cnt);
9868e709cbdSnorby 		break;
9878e709cbdSnorby 	case IMSG_CTL_END:
9888e709cbdSnorby 		printf("\n");
9898e709cbdSnorby 		return (1);
9908e709cbdSnorby 	default:
9918e709cbdSnorby 		break;
9928e709cbdSnorby 	}
9938e709cbdSnorby 
9948e709cbdSnorby 	return (0);
9958e709cbdSnorby }
9968e709cbdSnorby 
9978e709cbdSnorby int
9988e709cbdSnorby show_rib_msg(struct imsg *imsg)
9998e709cbdSnorby {
10008e709cbdSnorby 	struct ctl_rt	*rt;
10018e709cbdSnorby 	char		*dstnet;
10028e709cbdSnorby 
10038e709cbdSnorby 	switch (imsg->hdr.type) {
10048e709cbdSnorby 	case IMSG_CTL_SHOW_RIB:
10058e709cbdSnorby 		rt = imsg->data;
10068e709cbdSnorby 		switch (rt->d_type) {
10078e709cbdSnorby 		case DT_NET:
10080104e403Sclaudio 			if (asprintf(&dstnet, "%s/%d", log_in6addr(&rt->prefix),
10098e709cbdSnorby 			    rt->prefixlen) == -1)
10108e709cbdSnorby 				err(1, NULL);
10118e709cbdSnorby 			break;
10128e709cbdSnorby 		case DT_RTR:
10138e709cbdSnorby 			if (asprintf(&dstnet, "%s",
10140104e403Sclaudio 			    log_in6addr(&rt->prefix)) == -1)
10158e709cbdSnorby 				err(1, NULL);
10168e709cbdSnorby 			break;
10178e709cbdSnorby 		default:
10188e709cbdSnorby 			errx(1, "Invalid route type");
10198e709cbdSnorby 		}
10208e709cbdSnorby 
10218e709cbdSnorby 		printf("%-20s %-17s %-12s %-9s %-7d %s\n", dstnet,
10220104e403Sclaudio 		    log_in6addr(&rt->nexthop), path_type_name(rt->p_type),
10238e709cbdSnorby 		    dst_type_name(rt->d_type), rt->cost,
10248e709cbdSnorby 		    rt->uptime == 0 ? "-" : fmt_timeframe_core(rt->uptime));
10258e709cbdSnorby 		free(dstnet);
10268e709cbdSnorby 		break;
10278e709cbdSnorby 	case IMSG_CTL_END:
10288e709cbdSnorby 		printf("\n");
10298e709cbdSnorby 		return (1);
10308e709cbdSnorby 	default:
10318e709cbdSnorby 		break;
10328e709cbdSnorby 	}
10338e709cbdSnorby 
10348e709cbdSnorby 	return (0);
10358e709cbdSnorby }
10368e709cbdSnorby 
10378e709cbdSnorby void
10388e709cbdSnorby show_rib_head(struct in_addr aid, u_int8_t d_type, u_int8_t p_type)
10398e709cbdSnorby {
10408e709cbdSnorby 	char	*header, *format, *format2;
10418e709cbdSnorby 
10428e709cbdSnorby 	switch (p_type) {
10438e709cbdSnorby 	case PT_INTRA_AREA:
10448e709cbdSnorby 	case PT_INTER_AREA:
10458e709cbdSnorby 		switch (d_type) {
10468e709cbdSnorby 		case DT_NET:
10478e709cbdSnorby 			format = "Network Routing Table";
10488e709cbdSnorby 			format2 = "";
10498e709cbdSnorby 			break;
10508e709cbdSnorby 		case DT_RTR:
10518e709cbdSnorby 			format = "Router Routing Table";
10528e709cbdSnorby 			format2 = "Type";
10538e709cbdSnorby 			break;
10548e709cbdSnorby 		default:
10558e709cbdSnorby 			errx(1, "unknown route type");
10568e709cbdSnorby 		}
10578e709cbdSnorby 		break;
10588e709cbdSnorby 	case PT_TYPE1_EXT:
10598e709cbdSnorby 	case PT_TYPE2_EXT:
10608e709cbdSnorby 		format = NULL;
10618e709cbdSnorby 		format2 = "Cost 2";
10628e709cbdSnorby 		if ((header = strdup("External Routing Table")) == NULL)
10638e709cbdSnorby 			err(1, NULL);
10648e709cbdSnorby 		break;
10658e709cbdSnorby 	default:
10668e709cbdSnorby 		errx(1, "unknown route type");
10678e709cbdSnorby 	}
10688e709cbdSnorby 
10698e709cbdSnorby 	if (p_type != PT_TYPE1_EXT && p_type != PT_TYPE2_EXT)
10708e709cbdSnorby 		if (asprintf(&header, "%s (Area %s)", format,
10718e709cbdSnorby 		    inet_ntoa(aid)) == -1)
10728e709cbdSnorby 			err(1, NULL);
10738e709cbdSnorby 
10748e709cbdSnorby 	printf("\n%-18s %s\n", "", header);
10758e709cbdSnorby 	free(header);
10768e709cbdSnorby 
10778e709cbdSnorby 	printf("\n%-18s %-15s %-15s %-12s %-7s %-7s\n", "Destination",
10788e709cbdSnorby 	    "Nexthop", "Adv Router", "Path type", "Cost", format2);
10798e709cbdSnorby }
10808e709cbdSnorby 
10818e709cbdSnorby const char *
10828e709cbdSnorby print_ospf_rtr_flags(u_int8_t opts)
10838e709cbdSnorby {
10848e709cbdSnorby 	static char	optbuf[32];
10858e709cbdSnorby 
10868e709cbdSnorby 	snprintf(optbuf, sizeof(optbuf), "%s%s%s",
10878e709cbdSnorby 	    opts & OSPF_RTR_E ? "AS" : "",
10888e709cbdSnorby 	    opts & OSPF_RTR_E && opts & OSPF_RTR_B ? "+" : "",
10898e709cbdSnorby 	    opts & OSPF_RTR_B ? "ABR" : "");
10908e709cbdSnorby 	return (optbuf);
10918e709cbdSnorby }
10928e709cbdSnorby 
10938e709cbdSnorby int
10948e709cbdSnorby show_rib_detail_msg(struct imsg *imsg)
10958e709cbdSnorby {
10968e709cbdSnorby 	static struct in_addr	 area_id;
10978e709cbdSnorby 	struct ctl_rt		*rt;
10988e709cbdSnorby 	struct area		*area;
10998e709cbdSnorby 	char			*dstnet;
11008e709cbdSnorby 	static u_int8_t		 lasttype;
11018e709cbdSnorby 
11028e709cbdSnorby 	switch (imsg->hdr.type) {
11038e709cbdSnorby 	case IMSG_CTL_SHOW_RIB:
11048e709cbdSnorby 		rt = imsg->data;
11058e709cbdSnorby 
11068e709cbdSnorby 		switch (rt->p_type) {
11078e709cbdSnorby 		case PT_INTRA_AREA:
11088e709cbdSnorby 		case PT_INTER_AREA:
11098e709cbdSnorby 			switch (rt->d_type) {
11108e709cbdSnorby 			case DT_NET:
11118e709cbdSnorby 				if (lasttype != RIB_NET)
11128e709cbdSnorby 					show_rib_head(rt->area, rt->d_type,
11138e709cbdSnorby 					     rt->p_type);
11148e709cbdSnorby 				if (asprintf(&dstnet, "%s/%d",
11150104e403Sclaudio 				    log_in6addr(&rt->prefix),
11160104e403Sclaudio 				    rt->prefixlen) == -1)
11178e709cbdSnorby 					err(1, NULL);
11188e709cbdSnorby 				lasttype = RIB_NET;
11198e709cbdSnorby 				break;
11208e709cbdSnorby 			case DT_RTR:
11218e709cbdSnorby 				if (lasttype != RIB_RTR)
11228e709cbdSnorby 					show_rib_head(rt->area, rt->d_type,
11238e709cbdSnorby 					     rt->p_type);
11248e709cbdSnorby 				if (asprintf(&dstnet, "%s",
11250104e403Sclaudio 				    log_in6addr(&rt->prefix)) == -1)
11268e709cbdSnorby 					err(1, NULL);
11278e709cbdSnorby 				lasttype = RIB_RTR;
11288e709cbdSnorby 				break;
11298e709cbdSnorby 			default:
11308e709cbdSnorby 				errx(1, "unknown route type");
11318e709cbdSnorby 			}
11320104e403Sclaudio 			printf("%-18s %-15s ", dstnet,
11330104e403Sclaudio 			    log_in6addr(&rt->nexthop));
11348e709cbdSnorby 			printf("%-15s %-12s %-7d", inet_ntoa(rt->adv_rtr),
11358e709cbdSnorby 			    path_type_name(rt->p_type), rt->cost);
11368e709cbdSnorby 			free(dstnet);
11378e709cbdSnorby 
11388e709cbdSnorby 			if (rt->d_type == DT_RTR)
11398e709cbdSnorby 				printf(" %-7s",
11408e709cbdSnorby 				    print_ospf_rtr_flags(rt->flags));
11418e709cbdSnorby 
11428e709cbdSnorby 			printf("\n");
11438e709cbdSnorby 			break;
11448e709cbdSnorby 		case PT_TYPE1_EXT:
11458e709cbdSnorby 		case PT_TYPE2_EXT:
11468e709cbdSnorby 			if (lasttype != RIB_EXT)
11478e709cbdSnorby 				show_rib_head(rt->area, rt->d_type, rt->p_type);
11488e709cbdSnorby 
11498e709cbdSnorby 			if (asprintf(&dstnet, "%s/%d",
11500104e403Sclaudio 			    log_in6addr(&rt->prefix), rt->prefixlen) == -1)
11518e709cbdSnorby 				err(1, NULL);
11528e709cbdSnorby 
11530104e403Sclaudio 			printf("%-18s %-15s ", dstnet,
11540104e403Sclaudio 			    log_in6addr(&rt->nexthop));
11558e709cbdSnorby 			printf("%-15s %-12s %-7d %-7d\n",
11568e709cbdSnorby 			    inet_ntoa(rt->adv_rtr), path_type_name(rt->p_type),
11578e709cbdSnorby 			    rt->cost, rt->cost2);
1158*8957b20dSstsp 			free(dstnet);
11598e709cbdSnorby 
11608e709cbdSnorby 			lasttype = RIB_EXT;
11618e709cbdSnorby 			break;
11628e709cbdSnorby 		default:
11638e709cbdSnorby 			errx(1, "unknown route type");
11648e709cbdSnorby 		}
11658e709cbdSnorby 		break;
11668e709cbdSnorby 	case IMSG_CTL_AREA:
11678e709cbdSnorby 		area = imsg->data;
11688e709cbdSnorby 		area_id = area->id;
11698e709cbdSnorby 		break;
11708e709cbdSnorby 	case IMSG_CTL_END:
11718e709cbdSnorby 		printf("\n");
11728e709cbdSnorby 		return (1);
11738e709cbdSnorby 	default:
11748e709cbdSnorby 		break;
11758e709cbdSnorby 	}
11768e709cbdSnorby 
11778e709cbdSnorby 	return (0);
11788e709cbdSnorby }
11798e709cbdSnorby 
11808e709cbdSnorby void
11818e709cbdSnorby show_fib_head(void)
11828e709cbdSnorby {
11838e709cbdSnorby 	printf("flags: * = valid, O = OSPF, C = Connected, S = Static\n");
11848e709cbdSnorby 	printf("%-6s %-20s %-17s\n", "Flags", "Destination", "Nexthop");
11858e709cbdSnorby }
11868e709cbdSnorby 
11878e709cbdSnorby int
11888e709cbdSnorby show_fib_msg(struct imsg *imsg)
11898e709cbdSnorby {
11908e709cbdSnorby 	struct kroute		*k;
11918e709cbdSnorby 	char			*p;
11928e709cbdSnorby 
11938e709cbdSnorby 	switch (imsg->hdr.type) {
11948e709cbdSnorby 	case IMSG_CTL_KROUTE:
11958e709cbdSnorby 		if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute))
11968e709cbdSnorby 			errx(1, "wrong imsg len");
11978e709cbdSnorby 		k = imsg->data;
11988e709cbdSnorby 
11998e709cbdSnorby 		if (k->flags & F_DOWN)
12008e709cbdSnorby 			printf(" ");
12018e709cbdSnorby 		else
12028e709cbdSnorby 			printf("*");
12038e709cbdSnorby 
12048e709cbdSnorby 		if (!(k->flags & F_KERNEL))
12058e709cbdSnorby 			printf("O");
12068e709cbdSnorby 		else if (k->flags & F_CONNECTED)
12078e709cbdSnorby 			printf("C");
12088e709cbdSnorby 		else if (k->flags & F_STATIC)
12098e709cbdSnorby 			printf("S");
12108e709cbdSnorby 		else
12118e709cbdSnorby 			printf(" ");
12128e709cbdSnorby 
12138e709cbdSnorby 		printf("     ");
12140104e403Sclaudio 		if (asprintf(&p, "%s/%u", log_in6addr(&k->prefix),
12150104e403Sclaudio 		    k->prefixlen) == -1)
12168e709cbdSnorby 			err(1, NULL);
12178e709cbdSnorby 		printf("%-20s ", p);
12188e709cbdSnorby 		free(p);
12198e709cbdSnorby 
12200104e403Sclaudio 		if (!IN6_IS_ADDR_UNSPECIFIED(&k->nexthop))
12210104e403Sclaudio 			printf("%s", log_in6addr(&k->nexthop));
12228e709cbdSnorby 		else if (k->flags & F_CONNECTED)
12238e709cbdSnorby 			printf("link#%u", k->ifindex);
12248e709cbdSnorby 		printf("\n");
12258e709cbdSnorby 
12268e709cbdSnorby 		break;
12278e709cbdSnorby 	case IMSG_CTL_END:
12288e709cbdSnorby 		printf("\n");
12298e709cbdSnorby 		return (1);
12308e709cbdSnorby 	default:
12318e709cbdSnorby 		break;
12328e709cbdSnorby 	}
12338e709cbdSnorby 
12348e709cbdSnorby 	return (0);
12358e709cbdSnorby }
12368e709cbdSnorby 
12378e709cbdSnorby const int	ifm_status_valid_list[] = IFM_STATUS_VALID_LIST;
12388e709cbdSnorby const struct ifmedia_status_description
12398e709cbdSnorby 		ifm_status_descriptions[] = IFM_STATUS_DESCRIPTIONS;
12408e709cbdSnorby const struct ifmedia_description
12418e709cbdSnorby 		ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS;
12428e709cbdSnorby 
12438e709cbdSnorby const char *
12448e709cbdSnorby get_media_descr(int media_type)
12458e709cbdSnorby {
12468e709cbdSnorby 	const struct ifmedia_description	*p;
12478e709cbdSnorby 
12488e709cbdSnorby 	for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++)
12498e709cbdSnorby 		if (media_type == p->ifmt_word)
12508e709cbdSnorby 			return (p->ifmt_string);
12518e709cbdSnorby 
12528e709cbdSnorby 	return ("unknown");
12538e709cbdSnorby }
12548e709cbdSnorby 
12558e709cbdSnorby const char *
12568e709cbdSnorby get_linkstate(int media_type, int link_state)
12578e709cbdSnorby {
12588e709cbdSnorby 	const struct ifmedia_status_description	*p;
12598e709cbdSnorby 	int					 i;
12608e709cbdSnorby 
12618e709cbdSnorby 	if (link_state == LINK_STATE_UNKNOWN)
12628e709cbdSnorby 		return ("unknown");
12638e709cbdSnorby 
12648e709cbdSnorby 	for (i = 0; ifm_status_valid_list[i] != 0; i++)
12658e709cbdSnorby 		for (p = ifm_status_descriptions; p->ifms_valid != 0; p++) {
12668e709cbdSnorby 			if (p->ifms_type != media_type ||
12678e709cbdSnorby 			    p->ifms_valid != ifm_status_valid_list[i])
12688e709cbdSnorby 				continue;
12698e709cbdSnorby 			if (LINK_STATE_IS_UP(link_state))
12708e709cbdSnorby 				return (p->ifms_string[1]);
12718e709cbdSnorby 			return (p->ifms_string[0]);
12728e709cbdSnorby 		}
12738e709cbdSnorby 
12748e709cbdSnorby 	return ("unknown");
12758e709cbdSnorby }
12768e709cbdSnorby 
12778e709cbdSnorby void
12788e709cbdSnorby print_baudrate(u_int64_t baudrate)
12798e709cbdSnorby {
12808e709cbdSnorby 	if (baudrate > IF_Gbps(1))
12818e709cbdSnorby 		printf("%llu GBit/s", baudrate / IF_Gbps(1));
12828e709cbdSnorby 	else if (baudrate > IF_Mbps(1))
12838e709cbdSnorby 		printf("%llu MBit/s", baudrate / IF_Mbps(1));
12848e709cbdSnorby 	else if (baudrate > IF_Kbps(1))
12858e709cbdSnorby 		printf("%llu KBit/s", baudrate / IF_Kbps(1));
12868e709cbdSnorby 	else
12878e709cbdSnorby 		printf("%llu Bit/s", baudrate);
12888e709cbdSnorby }
1289