xref: /openbsd/usr.sbin/ospf6ctl/ospf6ctl.c (revision db93f2f1)
1*db93f2f1Sderaadt /*	$OpenBSD: ospf6ctl.c,v 1.5 2007/10/15 02:16:35 deraadt 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);
518e709cbdSnorby void		 show_database_head(struct in_addr, u_int8_t);
528e709cbdSnorby int		 show_database_msg(struct imsg *);
538e709cbdSnorby char		*print_ls_type(u_int8_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 *);
598e709cbdSnorby const char	*print_ospf_options(u_int8_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 void		 show_interface_head(void);
688e709cbdSnorby const char *	 get_media_descr(int);
698e709cbdSnorby const char *	 get_linkstate(int, int);
708e709cbdSnorby void		 print_baudrate(u_int64_t);
718e709cbdSnorby int		 show_fib_interface_msg(struct imsg *);
728e709cbdSnorby 
738e709cbdSnorby struct imsgbuf	*ibuf;
748e709cbdSnorby 
758e709cbdSnorby __dead void
768e709cbdSnorby usage(void)
778e709cbdSnorby {
788e709cbdSnorby 	extern char *__progname;
798e709cbdSnorby 
808e709cbdSnorby 	fprintf(stderr, "usage: %s <command> [arg [...]]\n", __progname);
818e709cbdSnorby 	exit(1);
828e709cbdSnorby }
838e709cbdSnorby 
848e709cbdSnorby /* dummy function so that ospf6ctl does not need libevent */
858e709cbdSnorby void
868e709cbdSnorby imsg_event_add(struct imsgbuf *i)
878e709cbdSnorby {
888e709cbdSnorby 	/* nothing */
898e709cbdSnorby }
908e709cbdSnorby 
918e709cbdSnorby int
928e709cbdSnorby main(int argc, char *argv[])
938e709cbdSnorby {
948e709cbdSnorby 	struct sockaddr_un	 sun;
958e709cbdSnorby 	struct parse_result	*res;
968e709cbdSnorby 	struct imsg		 imsg;
978e709cbdSnorby 	unsigned int		 ifidx = 0;
988e709cbdSnorby 	int			 ctl_sock;
998e709cbdSnorby 	int			 done = 0;
1008e709cbdSnorby 	int			 n;
1018e709cbdSnorby 
1028e709cbdSnorby 	/* parse options */
1038e709cbdSnorby 	if ((res = parse(argc - 1, argv + 1)) == NULL)
1048e709cbdSnorby 		exit(1);
1058e709cbdSnorby 
1068e709cbdSnorby 	/* connect to ospf6d control socket */
1078e709cbdSnorby 	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
1088e709cbdSnorby 		err(1, "socket");
1098e709cbdSnorby 
1108e709cbdSnorby 	bzero(&sun, sizeof(sun));
1118e709cbdSnorby 	sun.sun_family = AF_UNIX;
1128e709cbdSnorby 	strlcpy(sun.sun_path, OSPF6D_SOCKET, sizeof(sun.sun_path));
1138e709cbdSnorby 	if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1)
1148e709cbdSnorby 		err(1, "connect: %s", OSPF6D_SOCKET);
1158e709cbdSnorby 
1168e709cbdSnorby 	if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
1178e709cbdSnorby 		err(1, NULL);
1188e709cbdSnorby 	imsg_init(ibuf, ctl_sock, NULL);
1198e709cbdSnorby 	done = 0;
1208e709cbdSnorby 
1218e709cbdSnorby 	/* process user request */
1228e709cbdSnorby 	switch (res->action) {
1238e709cbdSnorby 	case NONE:
1248e709cbdSnorby 		usage();
1258e709cbdSnorby 		/* not reached */
1268e709cbdSnorby 	case SHOW:
1278e709cbdSnorby 	case SHOW_SUM:
1288e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_SUM, 0, 0, NULL, 0);
1298e709cbdSnorby 		break;
1308e709cbdSnorby 	case SHOW_IFACE:
1311fed8bffSnorby 		printf("%-11s %-29s %-6s %-10s %-10s %-8s\n",
1328e709cbdSnorby 		    "Interface", "Address", "State", "HelloTimer", "Linkstate",
1331fed8bffSnorby 		    "Uptime");
134c5ba8b41Sderaadt 		/*FALLTHROUGH*/
1358e709cbdSnorby 	case SHOW_IFACE_DTAIL:
1368e709cbdSnorby 		if (*res->ifname) {
1378e709cbdSnorby 			ifidx = if_nametoindex(res->ifname);
1388e709cbdSnorby 			if (ifidx == 0)
1398e709cbdSnorby 				errx(1, "no such interface %s", res->ifname);
1408e709cbdSnorby 		}
1418e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0,
1428e709cbdSnorby 		    &ifidx, sizeof(ifidx));
1438e709cbdSnorby 		break;
1448e709cbdSnorby 	case SHOW_NBR:
1458e709cbdSnorby 		printf("%-15s %-3s %-12s %-8s %-15s %-9s %s\n", "ID", "Pri",
1468e709cbdSnorby 		    "State", "DeadTime", "Address", "Iface","Uptime");
147c5ba8b41Sderaadt 		/*FALLTHROUGH*/
1488e709cbdSnorby 	case SHOW_NBR_DTAIL:
1498e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, NULL, 0);
1508e709cbdSnorby 		break;
1518e709cbdSnorby 	case SHOW_DB:
1528e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, NULL, 0);
1538e709cbdSnorby 		break;
1548e709cbdSnorby 	case SHOW_DBBYAREA:
1558e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0,
1568e709cbdSnorby 		    &res->addr, sizeof(res->addr));
1578e709cbdSnorby 		break;
1588e709cbdSnorby 	case SHOW_DBEXT:
1598e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_EXT, 0, 0, NULL, 0);
1608e709cbdSnorby 		break;
1618e709cbdSnorby 	case SHOW_DBNET:
1628e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_NET, 0, 0, NULL, 0);
1638e709cbdSnorby 		break;
1648e709cbdSnorby 	case SHOW_DBRTR:
1658e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_RTR, 0, 0, NULL, 0);
1668e709cbdSnorby 		break;
1678e709cbdSnorby 	case SHOW_DBSELF:
1688e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SELF, 0, 0, NULL, 0);
1698e709cbdSnorby 		break;
1708e709cbdSnorby 	case SHOW_DBSUM:
1718e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SUM, 0, 0, NULL, 0);
1728e709cbdSnorby 		break;
1738e709cbdSnorby 	case SHOW_DBASBR:
1748e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_ASBR, 0, 0, NULL, 0);
1758e709cbdSnorby 		break;
1768e709cbdSnorby 	case SHOW_RIB:
1778e709cbdSnorby 		printf("%-20s %-17s %-12s %-9s %-7s %-8s\n", "Destination",
1788e709cbdSnorby 		    "Nexthop", "Path Type", "Type", "Cost", "Uptime");
179c5ba8b41Sderaadt 		/*FALLTHROUGH*/
1808e709cbdSnorby 	case SHOW_RIB_DTAIL:
1818e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, NULL, 0);
1828e709cbdSnorby 		break;
1838e709cbdSnorby 	case SHOW_FIB:
1848e709cbdSnorby 		if (!res->addr.s_addr)
1858e709cbdSnorby 			imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0,
1868e709cbdSnorby 			    &res->flags, sizeof(res->flags));
1878e709cbdSnorby 		else
1888e709cbdSnorby 			imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0,
1898e709cbdSnorby 			    &res->addr, sizeof(res->addr));
1908e709cbdSnorby 		show_fib_head();
1918e709cbdSnorby 		break;
1928e709cbdSnorby 	case SHOW_FIB_IFACE:
1938e709cbdSnorby 		if (*res->ifname)
1948e709cbdSnorby 			imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0,
1958e709cbdSnorby 			    res->ifname, sizeof(res->ifname));
1968e709cbdSnorby 		else
1978e709cbdSnorby 			imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, NULL, 0);
1988e709cbdSnorby 		show_interface_head();
1998e709cbdSnorby 		break;
2008e709cbdSnorby 	case FIB:
2018e709cbdSnorby 		errx(1, "fib couple|decouple");
2028e709cbdSnorby 		break;
2038e709cbdSnorby 	case FIB_COUPLE:
2048e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, NULL, 0);
2058e709cbdSnorby 		printf("couple request sent.\n");
2068e709cbdSnorby 		done = 1;
2078e709cbdSnorby 		break;
2088e709cbdSnorby 	case FIB_DECOUPLE:
2098e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, NULL, 0);
2108e709cbdSnorby 		printf("decouple request sent.\n");
2118e709cbdSnorby 		done = 1;
2128e709cbdSnorby 		break;
2138e709cbdSnorby 	case RELOAD:
2148e709cbdSnorby 		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, 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:
2588e709cbdSnorby 			case SHOW_DBNET:
2598e709cbdSnorby 			case SHOW_DBRTR:
2608e709cbdSnorby 			case SHOW_DBSUM:
2618e709cbdSnorby 			case SHOW_DBASBR:
2628e709cbdSnorby 				done = show_db_msg_detail(&imsg);
2638e709cbdSnorby 				break;
2648e709cbdSnorby 			case SHOW_RIB:
2658e709cbdSnorby 				done = show_rib_msg(&imsg);
2668e709cbdSnorby 				break;
2678e709cbdSnorby 			case SHOW_RIB_DTAIL:
2688e709cbdSnorby 				done = show_rib_detail_msg(&imsg);
2698e709cbdSnorby 				break;
2708e709cbdSnorby 			case SHOW_FIB:
2718e709cbdSnorby 				done = show_fib_msg(&imsg);
2728e709cbdSnorby 				break;
2738e709cbdSnorby 			case SHOW_FIB_IFACE:
2748e709cbdSnorby 				done = show_fib_interface_msg(&imsg);
2758e709cbdSnorby 				break;
2768e709cbdSnorby 			case NONE:
2778e709cbdSnorby 			case FIB:
2788e709cbdSnorby 			case FIB_COUPLE:
2798e709cbdSnorby 			case FIB_DECOUPLE:
2808e709cbdSnorby 			case RELOAD:
2818e709cbdSnorby 				break;
2828e709cbdSnorby 			}
2838e709cbdSnorby 			imsg_free(&imsg);
2848e709cbdSnorby 		}
2858e709cbdSnorby 	}
2868e709cbdSnorby 	close(ctl_sock);
2878e709cbdSnorby 	free(ibuf);
2888e709cbdSnorby 
2898e709cbdSnorby 	return (0);
2908e709cbdSnorby }
2918e709cbdSnorby 
2928e709cbdSnorby int
2938e709cbdSnorby show_summary_msg(struct imsg *imsg)
2948e709cbdSnorby {
2958e709cbdSnorby 	struct ctl_sum		*sum;
2968e709cbdSnorby 	struct ctl_sum_area	*sumarea;
2978e709cbdSnorby 
2988e709cbdSnorby 	switch (imsg->hdr.type) {
2998e709cbdSnorby 	case IMSG_CTL_SHOW_SUM:
3008e709cbdSnorby 		sum = imsg->data;
3018e709cbdSnorby 		printf("Router ID: %s\n", inet_ntoa(sum->rtr_id));
3028e709cbdSnorby 		printf("Uptime: %s\n", fmt_timeframe_core(sum->uptime));
3038e709cbdSnorby 
3048e709cbdSnorby 		printf("SPF delay is %d sec(s), hold time between two SPFs "
3058e709cbdSnorby 		    "is %d sec(s)\n", sum->spf_delay, sum->spf_hold_time);
3068e709cbdSnorby 		printf("Number of external LSA(s) %d\n", sum->num_ext_lsa);
3078e709cbdSnorby 		printf("Number of areas attached to this router: %d\n",
3088e709cbdSnorby 		    sum->num_area);
3098e709cbdSnorby 		break;
3108e709cbdSnorby 	case IMSG_CTL_SHOW_SUM_AREA:
3118e709cbdSnorby 		sumarea = imsg->data;
3128e709cbdSnorby 		printf("\nArea ID: %s\n", inet_ntoa(sumarea->area));
3138e709cbdSnorby 		printf("  Number of interfaces in this area: %d\n",
3148e709cbdSnorby 		    sumarea->num_iface);
3158e709cbdSnorby 		printf("  Number of fully adjacent neighbors in this "
3168e709cbdSnorby 		    "area: %d\n", sumarea->num_adj_nbr);
3178e709cbdSnorby 		printf("  SPF algorithm executed %d time(s)\n",
3188e709cbdSnorby 		    sumarea->num_spf_calc);
3198e709cbdSnorby 		printf("  Number LSA(s) %d\n", sumarea->num_lsa);
3208e709cbdSnorby 		break;
3218e709cbdSnorby 	case IMSG_CTL_END:
3228e709cbdSnorby 		printf("\n");
3238e709cbdSnorby 		return (1);
3248e709cbdSnorby 	default:
3258e709cbdSnorby 		break;
3268e709cbdSnorby 	}
3278e709cbdSnorby 
3288e709cbdSnorby 	return (0);
3298e709cbdSnorby }
3308e709cbdSnorby 
3318e709cbdSnorby int
3328e709cbdSnorby get_ifms_type(int mediatype)
3338e709cbdSnorby {
3348e709cbdSnorby 	switch (mediatype) {
3358e709cbdSnorby 	case IFT_ETHER:
3368e709cbdSnorby 		return (IFM_ETHER);
3378e709cbdSnorby 	case IFT_FDDI:
3388e709cbdSnorby 		return (IFM_FDDI);
3398e709cbdSnorby 	case IFT_CARP:
3408e709cbdSnorby 		return (IFM_CARP);
3418e709cbdSnorby 	case IFT_PPP:
3428e709cbdSnorby 		return (IFM_TDM);
3438e709cbdSnorby 	default:
3448e709cbdSnorby 		return (0);
3458e709cbdSnorby 	}
3468e709cbdSnorby }
3478e709cbdSnorby 
3488e709cbdSnorby int
3498e709cbdSnorby show_interface_msg(struct imsg *imsg)
3508e709cbdSnorby {
3518e709cbdSnorby 	struct ctl_iface	*iface;
3528e709cbdSnorby 	char			*netid;
3538e709cbdSnorby 
3548e709cbdSnorby 	switch (imsg->hdr.type) {
3558e709cbdSnorby 	case IMSG_CTL_SHOW_INTERFACE:
3568e709cbdSnorby 		iface = imsg->data;
3578e709cbdSnorby 
3588e709cbdSnorby 		if (asprintf(&netid, "%s", log_in6addr(&iface->addr)) == -1)
3598e709cbdSnorby 			err(1, NULL);
3601fed8bffSnorby 		printf("%-11s %-29s %-6s %-10s %-10s %s\n",
3618e709cbdSnorby 		    iface->name, netid, if_state_name(iface->state),
3628e709cbdSnorby 		    fmt_timeframe_core(iface->hello_timer),
3638e709cbdSnorby 		    get_linkstate(get_ifms_type(iface->mediatype),
3641fed8bffSnorby 		    iface->linkstate), fmt_timeframe_core(iface->uptime));
3658e709cbdSnorby 		free(netid);
3668e709cbdSnorby 		break;
3678e709cbdSnorby 	case IMSG_CTL_END:
3688e709cbdSnorby 		printf("\n");
3698e709cbdSnorby 		return (1);
3708e709cbdSnorby 	default:
3718e709cbdSnorby 		break;
3728e709cbdSnorby 	}
3738e709cbdSnorby 
3748e709cbdSnorby 	return (0);
3758e709cbdSnorby }
3768e709cbdSnorby 
3778e709cbdSnorby int
3788e709cbdSnorby show_interface_detail_msg(struct imsg *imsg)
3798e709cbdSnorby {
3808e709cbdSnorby 	struct ctl_iface	*iface;
3818e709cbdSnorby 
3828e709cbdSnorby 	switch (imsg->hdr.type) {
3838e709cbdSnorby 	case IMSG_CTL_SHOW_INTERFACE:
3848e709cbdSnorby 		iface = imsg->data;
3858e709cbdSnorby 		printf("\n");
3868e709cbdSnorby 		printf("Interface %s, line protocol is %s\n",
3878e709cbdSnorby 		    iface->name, print_link(iface->flags));
3887aab4200Snorby 		printf("  Internet address %s ",
3898e709cbdSnorby 		    log_in6addr(&iface->addr));
3908e709cbdSnorby 		printf("Area %s\n", inet_ntoa(iface->area));
3918e709cbdSnorby 		printf("  Linkstate %s\n",
3928e709cbdSnorby 		    get_linkstate(get_ifms_type(iface->mediatype),
3938e709cbdSnorby 		    iface->linkstate));
3948e709cbdSnorby 		printf("  Router ID %s, network type %s, cost: %d\n",
3958e709cbdSnorby 		    inet_ntoa(iface->rtr_id),
3968e709cbdSnorby 		    if_type_name(iface->type), iface->metric);
3978e709cbdSnorby 		printf("  Transmit delay is %d sec(s), state %s, priority %d\n",
3988e709cbdSnorby 		    iface->transmit_delay, if_state_name(iface->state),
3998e709cbdSnorby 		    iface->priority);
4007aab4200Snorby 		printf("  Designated Router (ID) %s\n",
4018e709cbdSnorby 		    inet_ntoa(iface->dr_id));
4027aab4200Snorby 		printf("    Interface address %s\n",
4037aab4200Snorby 		    log_in6addr(&iface->dr_addr));
4047aab4200Snorby 		printf("  Backup Designated Router (ID) %s\n",
4058e709cbdSnorby 		    inet_ntoa(iface->bdr_id));
4067aab4200Snorby 		printf("    Interface address %s\n",
4077aab4200Snorby 		    log_in6addr(&iface->bdr_addr));
4088e709cbdSnorby 		printf("  Timer intervals configured, "
4098e709cbdSnorby 		    "hello %d, dead %d, wait %d, retransmit %d\n",
4108e709cbdSnorby 		     iface->hello_interval, iface->dead_interval,
4118e709cbdSnorby 		     iface->dead_interval, iface->rxmt_interval);
4128e709cbdSnorby 		if (iface->passive)
4138e709cbdSnorby 			printf("    Passive interface (No Hellos)\n");
4148e709cbdSnorby 		else if (iface->hello_timer < 0)
4158e709cbdSnorby 			printf("    Hello timer not running\n");
4168e709cbdSnorby 		else
4178e709cbdSnorby 			printf("    Hello timer due in %s\n",
4188e709cbdSnorby 			    fmt_timeframe_core(iface->hello_timer));
4198e709cbdSnorby 		printf("    Uptime %s\n", fmt_timeframe_core(iface->uptime));
4208e709cbdSnorby 		printf("  Neighbor count is %d, adjacent neighbor count is "
4218e709cbdSnorby 		    "%d\n", iface->nbr_cnt, iface->adj_cnt);
4228e709cbdSnorby 		break;
4238e709cbdSnorby 	case IMSG_CTL_END:
4248e709cbdSnorby 		printf("\n");
4258e709cbdSnorby 		return (1);
4268e709cbdSnorby 	default:
4278e709cbdSnorby 		break;
4288e709cbdSnorby 	}
4298e709cbdSnorby 
4308e709cbdSnorby 	return (0);
4318e709cbdSnorby }
4328e709cbdSnorby 
4338e709cbdSnorby const char *
4348e709cbdSnorby print_link(int state)
4358e709cbdSnorby {
4368e709cbdSnorby 	if (state & IFF_UP)
4378e709cbdSnorby 		return ("UP");
4388e709cbdSnorby 	else
4398e709cbdSnorby 		return ("DOWN");
4408e709cbdSnorby }
4418e709cbdSnorby 
4428e709cbdSnorby #define TF_BUFS	8
4438e709cbdSnorby #define TF_LEN	9
4448e709cbdSnorby 
4458e709cbdSnorby const char *
4468e709cbdSnorby fmt_timeframe(time_t t)
4478e709cbdSnorby {
4488e709cbdSnorby 	if (t == 0)
4498e709cbdSnorby 		return ("Never");
4508e709cbdSnorby 	else
4518e709cbdSnorby 		return (fmt_timeframe_core(time(NULL) - t));
4528e709cbdSnorby }
4538e709cbdSnorby 
4548e709cbdSnorby const char *
4558e709cbdSnorby fmt_timeframe_core(time_t t)
4568e709cbdSnorby {
4578e709cbdSnorby 	char		*buf;
4588e709cbdSnorby 	static char	 tfbuf[TF_BUFS][TF_LEN];	/* ring buffer */
4598e709cbdSnorby 	static int	 idx = 0;
460*db93f2f1Sderaadt 	unsigned int	 sec, min, hrs, day, week;
4618e709cbdSnorby 
4628e709cbdSnorby 	if (t == 0)
4638e709cbdSnorby 		return ("00:00:00");
4648e709cbdSnorby 
4658e709cbdSnorby 	buf = tfbuf[idx++];
4668e709cbdSnorby 	if (idx == TF_BUFS)
4678e709cbdSnorby 		idx = 0;
4688e709cbdSnorby 
4698e709cbdSnorby 	week = t;
4708e709cbdSnorby 
4718e709cbdSnorby 	sec = week % 60;
4728e709cbdSnorby 	week /= 60;
4738e709cbdSnorby 	min = week % 60;
4748e709cbdSnorby 	week /= 60;
4758e709cbdSnorby 	hrs = week % 24;
4768e709cbdSnorby 	week /= 24;
4778e709cbdSnorby 	day = week % 7;
4788e709cbdSnorby 	week /= 7;
4798e709cbdSnorby 
4808e709cbdSnorby 	if (week > 0)
4818e709cbdSnorby 		snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs);
4828e709cbdSnorby 	else if (day > 0)
4838e709cbdSnorby 		snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
4848e709cbdSnorby 	else
4858e709cbdSnorby 		snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
4868e709cbdSnorby 
4878e709cbdSnorby 	return (buf);
4888e709cbdSnorby }
4898e709cbdSnorby 
4908e709cbdSnorby const char *
4918e709cbdSnorby log_id(u_int32_t id)
4928e709cbdSnorby {
4938e709cbdSnorby 	static char	buf[48];
4948e709cbdSnorby 	struct in_addr	addr;
4958e709cbdSnorby 
4968e709cbdSnorby 	addr.s_addr = id;
4978e709cbdSnorby 
4988e709cbdSnorby 	if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL)
4998e709cbdSnorby 		return ("?");
5008e709cbdSnorby 	else
5018e709cbdSnorby 		return (buf);
5028e709cbdSnorby }
5038e709cbdSnorby 
5048e709cbdSnorby const char *
5058e709cbdSnorby log_adv_rtr(u_int32_t adv_rtr)
5068e709cbdSnorby {
5078e709cbdSnorby 	static char	buf[48];
5088e709cbdSnorby 	struct in_addr	addr;
5098e709cbdSnorby 
5108e709cbdSnorby 	addr.s_addr = adv_rtr;
5118e709cbdSnorby 
5128e709cbdSnorby 	if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL)
5138e709cbdSnorby 		return ("?");
5148e709cbdSnorby 	else
5158e709cbdSnorby 		return (buf);
5168e709cbdSnorby }
5178e709cbdSnorby 
5188e709cbdSnorby /* prototype defined in ospfd.h and shared with the kroute.c version */
5198e709cbdSnorby u_int8_t
5208e709cbdSnorby mask2prefixlen(in_addr_t ina)
5218e709cbdSnorby {
5228e709cbdSnorby 	if (ina == 0)
5238e709cbdSnorby 		return (0);
5248e709cbdSnorby 	else
5258e709cbdSnorby 		return (33 - ffs(ntohl(ina)));
5268e709cbdSnorby }
5278e709cbdSnorby 
5288e709cbdSnorby void
5298e709cbdSnorby show_database_head(struct in_addr aid, u_int8_t type)
5308e709cbdSnorby {
5318e709cbdSnorby 	char	*header, *format;
5328e709cbdSnorby 
5338e709cbdSnorby 	switch (type) {
5348e709cbdSnorby 	case LSA_TYPE_ROUTER:
5358e709cbdSnorby 		format = "Router Link States";
5368e709cbdSnorby 		break;
5378e709cbdSnorby 	case LSA_TYPE_NETWORK:
5388e709cbdSnorby 		format = "Net Link States";
5398e709cbdSnorby 		break;
5408e709cbdSnorby 	case LSA_TYPE_SUM_NETWORK:
5418e709cbdSnorby 		format = "Summary Net Link States";
5428e709cbdSnorby 		break;
5438e709cbdSnorby 	case LSA_TYPE_SUM_ROUTER:
5448e709cbdSnorby 		format = "Summary Router Link States";
5458e709cbdSnorby 		break;
5468e709cbdSnorby 	case LSA_TYPE_EXTERNAL:
5478e709cbdSnorby 		format = NULL;
5488e709cbdSnorby 		if ((header = strdup("Type-5 AS External Link States")) == NULL)
5498e709cbdSnorby 			err(1, NULL);
5508e709cbdSnorby 		break;
5518e709cbdSnorby 	default:
5528e709cbdSnorby 		errx(1, "unknown LSA type");
5538e709cbdSnorby 	}
5548e709cbdSnorby 	if (type != LSA_TYPE_EXTERNAL)
5558e709cbdSnorby 		if (asprintf(&header, "%s (Area %s)", format,
5568e709cbdSnorby 		    inet_ntoa(aid)) == -1)
5578e709cbdSnorby 			err(1, NULL);
5588e709cbdSnorby 
5598e709cbdSnorby 	printf("\n%-15s %s\n\n", "", header);
5608e709cbdSnorby 	free(header);
5618e709cbdSnorby }
5628e709cbdSnorby 
5638e709cbdSnorby int
5648e709cbdSnorby show_database_msg(struct imsg *imsg)
5658e709cbdSnorby {
5668e709cbdSnorby 	static struct in_addr	 area_id;
5678e709cbdSnorby 	static u_int8_t		 lasttype;
5688e709cbdSnorby 	struct area		*area;
5698e709cbdSnorby 	struct lsa_hdr		*lsa;
5708e709cbdSnorby 
5718e709cbdSnorby 	switch (imsg->hdr.type) {
5728e709cbdSnorby 	case IMSG_CTL_SHOW_DATABASE:
5738e709cbdSnorby 	case IMSG_CTL_SHOW_DB_SELF:
5748e709cbdSnorby 		lsa = imsg->data;
5758e709cbdSnorby 		if (lsa->type != lasttype) {
5768e709cbdSnorby 			show_database_head(area_id, lsa->type);
5778e709cbdSnorby 			printf("%-15s %-15s %-4s %-10s %-8s\n", "Link ID",
5788e709cbdSnorby 			    "Adv Router", "Age", "Seq#", "Checksum");
5798e709cbdSnorby 		}
5808e709cbdSnorby 		printf("%-15s %-15s %-4d 0x%08x 0x%04x\n",
5818e709cbdSnorby 		    log_id(lsa->ls_id), log_adv_rtr(lsa->adv_rtr),
5828e709cbdSnorby 		    ntohs(lsa->age), ntohl(lsa->seq_num),
5838e709cbdSnorby 		    ntohs(lsa->ls_chksum));
5848e709cbdSnorby 		lasttype = lsa->type;
5858e709cbdSnorby 		break;
5868e709cbdSnorby 	case IMSG_CTL_AREA:
5878e709cbdSnorby 		area = imsg->data;
5888e709cbdSnorby 		area_id = area->id;
5898e709cbdSnorby 		lasttype = 0;
5908e709cbdSnorby 		break;
5918e709cbdSnorby 	case IMSG_CTL_END:
5928e709cbdSnorby 		printf("\n");
5938e709cbdSnorby 		return (1);
5948e709cbdSnorby 	default:
5958e709cbdSnorby 		break;
5968e709cbdSnorby 	}
5978e709cbdSnorby 
5988e709cbdSnorby 	return (0);
5998e709cbdSnorby }
6008e709cbdSnorby 
6018e709cbdSnorby char *
6028e709cbdSnorby print_ls_type(u_int8_t type)
6038e709cbdSnorby {
6048e709cbdSnorby 	switch (type) {
6058e709cbdSnorby 	case LSA_TYPE_ROUTER:
6068e709cbdSnorby 		return ("Router");
6078e709cbdSnorby 	case LSA_TYPE_NETWORK:
6088e709cbdSnorby 		return ("Network");
6098e709cbdSnorby 	case LSA_TYPE_SUM_NETWORK:
6108e709cbdSnorby 		return ("Summary (Network)");
6118e709cbdSnorby 	case LSA_TYPE_SUM_ROUTER:
6128e709cbdSnorby 		return ("Summary (Router)");
6138e709cbdSnorby 	case LSA_TYPE_EXTERNAL:
6148e709cbdSnorby 		return ("AS External");
6158e709cbdSnorby 	default:
6168e709cbdSnorby 		return ("Unknown");
6178e709cbdSnorby 	}
6188e709cbdSnorby }
6198e709cbdSnorby 
6208e709cbdSnorby void
6218e709cbdSnorby show_db_hdr_msg_detail(struct lsa_hdr *lsa)
6228e709cbdSnorby {
6238e709cbdSnorby 	printf("LS age: %d\n", ntohs(lsa->age));
6248e709cbdSnorby //XXX	printf("Options: %s\n", print_ospf_options(lsa->opts));
6258e709cbdSnorby 	printf("LS Type: %s\n", print_ls_type(lsa->type));
6268e709cbdSnorby 
6278e709cbdSnorby 	switch (lsa->type) {
6288e709cbdSnorby 	case LSA_TYPE_ROUTER:
6298e709cbdSnorby 		printf("Link State ID: %s\n", log_id(lsa->ls_id));
6308e709cbdSnorby 		break;
6318e709cbdSnorby 	case LSA_TYPE_NETWORK:
6328e709cbdSnorby 		printf("Link State ID: %s (address of Designated Router)\n",
6338e709cbdSnorby 		    log_id(lsa->ls_id));
6348e709cbdSnorby 		break;
6358e709cbdSnorby 	case LSA_TYPE_SUM_NETWORK:
6368e709cbdSnorby 		printf("Link State ID: %s (Network ID)\n", log_id(lsa->ls_id));
6378e709cbdSnorby 		break;
6388e709cbdSnorby 	case LSA_TYPE_SUM_ROUTER:
6398e709cbdSnorby 		printf("Link State ID: %s (ASBR Router ID)\n",
6408e709cbdSnorby 		    log_id(lsa->ls_id));
6418e709cbdSnorby 		break;
6428e709cbdSnorby 	case LSA_TYPE_EXTERNAL:
6438e709cbdSnorby 		printf("Link State ID: %s (External Network Number)\n",
6448e709cbdSnorby 		     log_id(lsa->ls_id));
6458e709cbdSnorby 		break;
6468e709cbdSnorby 	}
6478e709cbdSnorby 
6488e709cbdSnorby 	printf("Advertising Router: %s\n", log_adv_rtr(lsa->adv_rtr));
6498e709cbdSnorby 	printf("LS Seq Number: 0x%08x\n", ntohl(lsa->seq_num));
6508e709cbdSnorby 	printf("Checksum: 0x%04x\n", ntohs(lsa->ls_chksum));
6518e709cbdSnorby 	printf("Length: %d\n", ntohs(lsa->len));
6528e709cbdSnorby }
6538e709cbdSnorby 
6548e709cbdSnorby char *
6558e709cbdSnorby print_rtr_link_type(u_int8_t type)
6568e709cbdSnorby {
6578e709cbdSnorby 	switch (type) {
6588e709cbdSnorby 	case LINK_TYPE_POINTTOPOINT:
6598e709cbdSnorby 		return ("Point-to-Point");
6608e709cbdSnorby 	case LINK_TYPE_TRANSIT_NET:
6618e709cbdSnorby 		return ("Transit Network");
6628e709cbdSnorby 	case LINK_TYPE_STUB_NET:
6638e709cbdSnorby 		return ("Stub Network");
6648e709cbdSnorby 	case LINK_TYPE_VIRTUAL:
6658e709cbdSnorby 		return ("Virtual Link");
6668e709cbdSnorby 	default:
6678e709cbdSnorby 		return ("Unknown");
6688e709cbdSnorby 	}
6698e709cbdSnorby }
6708e709cbdSnorby 
6718e709cbdSnorby const char *
6728e709cbdSnorby print_ospf_flags(u_int8_t opts)
6738e709cbdSnorby {
6748e709cbdSnorby 	static char	optbuf[32];
6758e709cbdSnorby 
6768e709cbdSnorby 	snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s",
6778e709cbdSnorby 	    opts & OSPF_RTR_V ? "V" : "-",
6788e709cbdSnorby 	    opts & OSPF_RTR_E ? "E" : "-",
6798e709cbdSnorby 	    opts & OSPF_RTR_B ? "B" : "-");
6808e709cbdSnorby 	return (optbuf);
6818e709cbdSnorby }
6828e709cbdSnorby 
6838e709cbdSnorby int
6848e709cbdSnorby show_db_msg_detail(struct imsg *imsg)
6858e709cbdSnorby {
6868e709cbdSnorby 	static struct in_addr	 area_id;
6878e709cbdSnorby 	static u_int8_t		 lasttype;
6888e709cbdSnorby 	struct in_addr		 addr, data;
6898e709cbdSnorby 	struct area		*area;
6908e709cbdSnorby 	struct lsa		*lsa;
6918e709cbdSnorby 	struct lsa_rtr_link	*rtr_link;
6928e709cbdSnorby 	struct lsa_asext	*asext;
6938e709cbdSnorby 	u_int16_t		 i, nlinks, off;
6948e709cbdSnorby 
6958e709cbdSnorby 	/* XXX sanity checks! */
6968e709cbdSnorby 
6978e709cbdSnorby 	switch (imsg->hdr.type) {
6988e709cbdSnorby 	case IMSG_CTL_SHOW_DB_EXT:
6998e709cbdSnorby 		lsa = imsg->data;
7008e709cbdSnorby 		if (lsa->hdr.type != lasttype)
7018e709cbdSnorby 			show_database_head(area_id, lsa->hdr.type);
7028e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
7038e709cbdSnorby 		addr.s_addr = lsa->data.asext.mask;
7048e709cbdSnorby 		printf("Network Mask: %s\n", inet_ntoa(addr));
7058e709cbdSnorby 
7068e709cbdSnorby 		asext = (struct lsa_asext *)((char *)lsa + sizeof(lsa->hdr));
7078e709cbdSnorby 
7088e709cbdSnorby 		printf("    Metric type: ");
7098e709cbdSnorby 		if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_E_FLAG)
7108e709cbdSnorby 			printf("2\n");
7118e709cbdSnorby 		else
7128e709cbdSnorby 			printf("1\n");
7138e709cbdSnorby 		printf("    Metric: %d\n", ntohl(asext->metric)
7148e709cbdSnorby 		    & LSA_METRIC_MASK);
7158e709cbdSnorby 		addr.s_addr = asext->fw_addr;
7168e709cbdSnorby 		printf("    Forwarding Address: %s\n", inet_ntoa(addr));
7178e709cbdSnorby 		printf("    External Route Tag: %d\n\n", ntohl(asext->ext_tag));
7188e709cbdSnorby 
7198e709cbdSnorby 		lasttype = lsa->hdr.type;
7208e709cbdSnorby 		break;
7218e709cbdSnorby 	case IMSG_CTL_SHOW_DB_NET:
7228e709cbdSnorby 		lsa = imsg->data;
7238e709cbdSnorby 		if (lsa->hdr.type != lasttype)
7248e709cbdSnorby 			show_database_head(area_id, lsa->hdr.type);
7258e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
7268e709cbdSnorby 		addr.s_addr = lsa->data.net.mask;
7278e709cbdSnorby 		printf("Network Mask: %s\n", inet_ntoa(addr));
7288e709cbdSnorby 
7298e709cbdSnorby 		nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr)
7308e709cbdSnorby 		    - sizeof(u_int32_t)) / sizeof(struct lsa_net_link);
7318e709cbdSnorby 		off = sizeof(lsa->hdr) + sizeof(u_int32_t);
7328e709cbdSnorby 
7338e709cbdSnorby 		for (i = 0; i < nlinks; i++) {
7348e709cbdSnorby 			addr.s_addr = lsa->data.net.att_rtr[i];
7358e709cbdSnorby 			printf("    Attached Router: %s\n", inet_ntoa(addr));
7368e709cbdSnorby 		}
7378e709cbdSnorby 
7388e709cbdSnorby 		printf("\n");
7398e709cbdSnorby 		lasttype = lsa->hdr.type;
7408e709cbdSnorby 		break;
7418e709cbdSnorby 	case IMSG_CTL_SHOW_DB_RTR:
7428e709cbdSnorby 		lsa = imsg->data;
7438e709cbdSnorby 		if (lsa->hdr.type != lasttype)
7448e709cbdSnorby 			show_database_head(area_id, lsa->hdr.type);
7458e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
7468e709cbdSnorby 		printf("Flags: %s\n", print_ospf_flags(lsa->data.rtr.flags));
7478e709cbdSnorby 		nlinks = ntohs(lsa->data.rtr.nlinks);
7488e709cbdSnorby 		printf("Number of Links: %d\n\n", nlinks);
7498e709cbdSnorby 
7508e709cbdSnorby 		off = sizeof(lsa->hdr) + sizeof(struct lsa_rtr);
7518e709cbdSnorby 
7528e709cbdSnorby 		for (i = 0; i < nlinks; i++) {
7538e709cbdSnorby 			rtr_link = (struct lsa_rtr_link *)((char *)lsa + off);
7548e709cbdSnorby 
7558e709cbdSnorby 			printf("    Link connected to: %s\n",
7568e709cbdSnorby 			    print_rtr_link_type(rtr_link->type));
7578e709cbdSnorby 
7588e709cbdSnorby 			addr.s_addr = rtr_link->id;
7598e709cbdSnorby 			data.s_addr = rtr_link->data;
7608e709cbdSnorby 
7618e709cbdSnorby 			switch (rtr_link->type) {
7628e709cbdSnorby 			case LINK_TYPE_POINTTOPOINT:
7638e709cbdSnorby 			case LINK_TYPE_VIRTUAL:
7648e709cbdSnorby 				printf("    Link ID (Neighbors Router ID):"
7658e709cbdSnorby 				    " %s\n", inet_ntoa(addr));
7668e709cbdSnorby 				printf("    Link Data (Router Interface "
7678e709cbdSnorby 				    "address): %s\n", inet_ntoa(data));
7688e709cbdSnorby 				break;
7698e709cbdSnorby 			case LINK_TYPE_TRANSIT_NET:
7708e709cbdSnorby 				printf("    Link ID (Designated Router "
7718e709cbdSnorby 				    "address): %s\n", inet_ntoa(addr));
7728e709cbdSnorby 				printf("    Link Data (Router Interface "
7738e709cbdSnorby 				    "address): %s\n", inet_ntoa(data));
7748e709cbdSnorby 				break;
7758e709cbdSnorby 			case LINK_TYPE_STUB_NET:
7768e709cbdSnorby 				printf("    Link ID (Network ID): %s\n",
7778e709cbdSnorby 				    inet_ntoa(addr));
7788e709cbdSnorby 				printf("    Link Data (Network Mask): %s\n",
7798e709cbdSnorby 				    inet_ntoa(data));
7808e709cbdSnorby 				break;
7818e709cbdSnorby 			default:
7828e709cbdSnorby 				printf("    Link ID (Unknown): %s\n",
7838e709cbdSnorby 				    inet_ntoa(addr));
7848e709cbdSnorby 				printf("    Link Data (Unknown): %s\n",
7858e709cbdSnorby 				    inet_ntoa(data));
7868e709cbdSnorby 				break;
7878e709cbdSnorby 			}
7888e709cbdSnorby 
7898e709cbdSnorby 			printf("    Metric: %d\n\n", ntohs(rtr_link->metric));
7908e709cbdSnorby 
7918e709cbdSnorby 			off += sizeof(struct lsa_rtr_link) +
7928e709cbdSnorby 			    rtr_link->num_tos * sizeof(u_int32_t);
7938e709cbdSnorby 		}
7948e709cbdSnorby 
7958e709cbdSnorby 		lasttype = lsa->hdr.type;
7968e709cbdSnorby 		break;
7978e709cbdSnorby 	case IMSG_CTL_SHOW_DB_SUM:
7988e709cbdSnorby 	case IMSG_CTL_SHOW_DB_ASBR:
7998e709cbdSnorby 		lsa = imsg->data;
8008e709cbdSnorby 		if (lsa->hdr.type != lasttype)
8018e709cbdSnorby 			show_database_head(area_id, lsa->hdr.type);
8028e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
8038e709cbdSnorby 		addr.s_addr = lsa->data.sum.mask;
8048e709cbdSnorby 		printf("Network Mask: %s\n", inet_ntoa(addr));
8058e709cbdSnorby 		printf("Metric: %d\n\n", ntohl(lsa->data.sum.metric) &
8068e709cbdSnorby 		    LSA_METRIC_MASK);
8078e709cbdSnorby 		lasttype = lsa->hdr.type;
8088e709cbdSnorby 		break;
8098e709cbdSnorby 	case IMSG_CTL_AREA:
8108e709cbdSnorby 		area = imsg->data;
8118e709cbdSnorby 		area_id = area->id;
8128e709cbdSnorby 		lasttype = 0;
8138e709cbdSnorby 		break;
8148e709cbdSnorby 	case IMSG_CTL_END:
8158e709cbdSnorby 		return (1);
8168e709cbdSnorby 	default:
8178e709cbdSnorby 		break;
8188e709cbdSnorby 	}
8198e709cbdSnorby 
8208e709cbdSnorby 	return (0);
8218e709cbdSnorby }
8228e709cbdSnorby 
8238e709cbdSnorby int
8248e709cbdSnorby show_nbr_msg(struct imsg *imsg)
8258e709cbdSnorby {
8268e709cbdSnorby 	struct ctl_nbr	*nbr;
8278e709cbdSnorby 	char		*state;
8288e709cbdSnorby 
8298e709cbdSnorby 	switch (imsg->hdr.type) {
8308e709cbdSnorby 	case IMSG_CTL_SHOW_NBR:
8318e709cbdSnorby 		nbr = imsg->data;
8328e709cbdSnorby 		if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state),
8338e709cbdSnorby 		    if_state_name(nbr->iface_state)) == -1)
8348e709cbdSnorby 			err(1, NULL);
8358e709cbdSnorby 		printf("%-15s %-3d %-12s %-9s", inet_ntoa(nbr->id),
8368e709cbdSnorby 		    nbr->priority, state, fmt_timeframe_core(nbr->dead_timer));
8378e709cbdSnorby 		printf("%-15s %-9s %s\n", log_in6addr(&nbr->addr), nbr->name,
8388e709cbdSnorby 		    nbr->uptime == 0 ? "-" : fmt_timeframe_core(nbr->uptime));
8398e709cbdSnorby 		free(state);
8408e709cbdSnorby 		break;
8418e709cbdSnorby 	case IMSG_CTL_END:
8428e709cbdSnorby 		printf("\n");
8438e709cbdSnorby 		return (1);
8448e709cbdSnorby 	default:
8458e709cbdSnorby 		break;
8468e709cbdSnorby 	}
8478e709cbdSnorby 
8488e709cbdSnorby 	return (0);
8498e709cbdSnorby }
8508e709cbdSnorby 
8518e709cbdSnorby const char *
8528e709cbdSnorby print_ospf_options(u_int8_t opts)
8538e709cbdSnorby {
8548e709cbdSnorby 	static char	optbuf[32];
8558e709cbdSnorby 
8568e709cbdSnorby 	snprintf(optbuf, sizeof(optbuf), "*|*|%s|%s|%s|%s|%s|%s",
8578e709cbdSnorby 	    opts & OSPF_OPTION_DC ? "DC" : "-",
8588e709cbdSnorby 	    opts & OSPF_OPTION_R ? "R" : "-",
8598e709cbdSnorby 	    opts & OSPF_OPTION_N ? "N" : "-",
8608e709cbdSnorby 	    opts & OSPF_OPTION_MC ? "MC" : "-",
8618e709cbdSnorby 	    opts & OSPF_OPTION_E ? "E" : "-",
8628e709cbdSnorby 	    opts & OSPF_OPTION_V6 ? "V6" : "-");
8638e709cbdSnorby 	return (optbuf);
8648e709cbdSnorby }
8658e709cbdSnorby 
8668e709cbdSnorby int
8678e709cbdSnorby show_nbr_detail_msg(struct imsg *imsg)
8688e709cbdSnorby {
8698e709cbdSnorby 	struct ctl_nbr	*nbr;
8708e709cbdSnorby 
8718e709cbdSnorby 	switch (imsg->hdr.type) {
8728e709cbdSnorby 	case IMSG_CTL_SHOW_NBR:
8738e709cbdSnorby 		nbr = imsg->data;
8748e709cbdSnorby 		printf("\nNeighbor %s, ", inet_ntoa(nbr->id));
8758e709cbdSnorby 		printf("interface address %s\n", log_in6addr(&nbr->addr));
8768e709cbdSnorby 		printf("  Area %s, interface %s\n", inet_ntoa(nbr->area),
8778e709cbdSnorby 		    nbr->name);
8788e709cbdSnorby 		printf("  Neighbor priority is %d, "
8798e709cbdSnorby 		    "State is %s, %d state changes\n",
8808e709cbdSnorby 		    nbr->priority, nbr_state_name(nbr->nbr_state),
8818e709cbdSnorby 		    nbr->state_chng_cnt);
8828e709cbdSnorby 		printf("  DR is %s, ", inet_ntoa(nbr->dr));
8838e709cbdSnorby 		printf("BDR is %s\n", inet_ntoa(nbr->bdr));
8848e709cbdSnorby 		printf("  Options %s\n", print_ospf_options(nbr->options));
8858e709cbdSnorby 		printf("  Dead timer due in %s\n",
8868e709cbdSnorby 		    fmt_timeframe_core(nbr->dead_timer));
8878e709cbdSnorby 		printf("  Uptime %s\n", fmt_timeframe_core(nbr->uptime));
8888e709cbdSnorby 		printf("  Database Summary List %d\n", nbr->db_sum_lst_cnt);
8898e709cbdSnorby 		printf("  Link State Request List %d\n", nbr->ls_req_lst_cnt);
8908e709cbdSnorby 		printf("  Link State Retransmission List %d\n",
8918e709cbdSnorby 		    nbr->ls_retrans_lst_cnt);
8928e709cbdSnorby 		break;
8938e709cbdSnorby 	case IMSG_CTL_END:
8948e709cbdSnorby 		printf("\n");
8958e709cbdSnorby 		return (1);
8968e709cbdSnorby 	default:
8978e709cbdSnorby 		break;
8988e709cbdSnorby 	}
8998e709cbdSnorby 
9008e709cbdSnorby 	return (0);
9018e709cbdSnorby }
9028e709cbdSnorby 
9038e709cbdSnorby int
9048e709cbdSnorby show_rib_msg(struct imsg *imsg)
9058e709cbdSnorby {
9068e709cbdSnorby 	struct ctl_rt	*rt;
9078e709cbdSnorby 	char		*dstnet;
9088e709cbdSnorby 
9098e709cbdSnorby 	switch (imsg->hdr.type) {
9108e709cbdSnorby 	case IMSG_CTL_SHOW_RIB:
9118e709cbdSnorby 		rt = imsg->data;
9128e709cbdSnorby 		switch (rt->d_type) {
9138e709cbdSnorby 		case DT_NET:
9148e709cbdSnorby 			if (asprintf(&dstnet, "%s/%d", inet_ntoa(rt->prefix),
9158e709cbdSnorby 			    rt->prefixlen) == -1)
9168e709cbdSnorby 				err(1, NULL);
9178e709cbdSnorby 			break;
9188e709cbdSnorby 		case DT_RTR:
9198e709cbdSnorby 			if (asprintf(&dstnet, "%s",
9208e709cbdSnorby 			    inet_ntoa(rt->prefix)) == -1)
9218e709cbdSnorby 				err(1, NULL);
9228e709cbdSnorby 			break;
9238e709cbdSnorby 		default:
9248e709cbdSnorby 			errx(1, "Invalid route type");
9258e709cbdSnorby 		}
9268e709cbdSnorby 
9278e709cbdSnorby 		printf("%-20s %-17s %-12s %-9s %-7d %s\n", dstnet,
9288e709cbdSnorby 		    inet_ntoa(rt->nexthop), path_type_name(rt->p_type),
9298e709cbdSnorby 		    dst_type_name(rt->d_type), rt->cost,
9308e709cbdSnorby 		    rt->uptime == 0 ? "-" : fmt_timeframe_core(rt->uptime));
9318e709cbdSnorby 		free(dstnet);
9328e709cbdSnorby 		break;
9338e709cbdSnorby 	case IMSG_CTL_END:
9348e709cbdSnorby 		printf("\n");
9358e709cbdSnorby 		return (1);
9368e709cbdSnorby 	default:
9378e709cbdSnorby 		break;
9388e709cbdSnorby 	}
9398e709cbdSnorby 
9408e709cbdSnorby 	return (0);
9418e709cbdSnorby }
9428e709cbdSnorby 
9438e709cbdSnorby void
9448e709cbdSnorby show_rib_head(struct in_addr aid, u_int8_t d_type, u_int8_t p_type)
9458e709cbdSnorby {
9468e709cbdSnorby 	char	*header, *format, *format2;
9478e709cbdSnorby 
9488e709cbdSnorby 	switch (p_type) {
9498e709cbdSnorby 	case PT_INTRA_AREA:
9508e709cbdSnorby 	case PT_INTER_AREA:
9518e709cbdSnorby 		switch (d_type) {
9528e709cbdSnorby 		case DT_NET:
9538e709cbdSnorby 			format = "Network Routing Table";
9548e709cbdSnorby 			format2 = "";
9558e709cbdSnorby 			break;
9568e709cbdSnorby 		case DT_RTR:
9578e709cbdSnorby 			format = "Router Routing Table";
9588e709cbdSnorby 			format2 = "Type";
9598e709cbdSnorby 			break;
9608e709cbdSnorby 		default:
9618e709cbdSnorby 			errx(1, "unknown route type");
9628e709cbdSnorby 		}
9638e709cbdSnorby 		break;
9648e709cbdSnorby 	case PT_TYPE1_EXT:
9658e709cbdSnorby 	case PT_TYPE2_EXT:
9668e709cbdSnorby 		format = NULL;
9678e709cbdSnorby 		format2 = "Cost 2";
9688e709cbdSnorby 		if ((header = strdup("External Routing Table")) == NULL)
9698e709cbdSnorby 			err(1, NULL);
9708e709cbdSnorby 		break;
9718e709cbdSnorby 	default:
9728e709cbdSnorby 		errx(1, "unknown route type");
9738e709cbdSnorby 	}
9748e709cbdSnorby 
9758e709cbdSnorby 	if (p_type != PT_TYPE1_EXT && p_type != PT_TYPE2_EXT)
9768e709cbdSnorby 		if (asprintf(&header, "%s (Area %s)", format,
9778e709cbdSnorby 		    inet_ntoa(aid)) == -1)
9788e709cbdSnorby 			err(1, NULL);
9798e709cbdSnorby 
9808e709cbdSnorby 	printf("\n%-18s %s\n", "", header);
9818e709cbdSnorby 	free(header);
9828e709cbdSnorby 
9838e709cbdSnorby 	printf("\n%-18s %-15s %-15s %-12s %-7s %-7s\n", "Destination",
9848e709cbdSnorby 	    "Nexthop", "Adv Router", "Path type", "Cost", format2);
9858e709cbdSnorby }
9868e709cbdSnorby 
9878e709cbdSnorby const char *
9888e709cbdSnorby print_ospf_rtr_flags(u_int8_t opts)
9898e709cbdSnorby {
9908e709cbdSnorby 	static char	optbuf[32];
9918e709cbdSnorby 
9928e709cbdSnorby 	snprintf(optbuf, sizeof(optbuf), "%s%s%s",
9938e709cbdSnorby 	    opts & OSPF_RTR_E ? "AS" : "",
9948e709cbdSnorby 	    opts & OSPF_RTR_E && opts & OSPF_RTR_B ? "+" : "",
9958e709cbdSnorby 	    opts & OSPF_RTR_B ? "ABR" : "");
9968e709cbdSnorby 	return (optbuf);
9978e709cbdSnorby }
9988e709cbdSnorby 
9998e709cbdSnorby int
10008e709cbdSnorby show_rib_detail_msg(struct imsg *imsg)
10018e709cbdSnorby {
10028e709cbdSnorby 	static struct in_addr	 area_id;
10038e709cbdSnorby 	struct ctl_rt		*rt;
10048e709cbdSnorby 	struct area		*area;
10058e709cbdSnorby 	char			*dstnet;
10068e709cbdSnorby 	static u_int8_t		 lasttype;
10078e709cbdSnorby 
10088e709cbdSnorby 	switch (imsg->hdr.type) {
10098e709cbdSnorby 	case IMSG_CTL_SHOW_RIB:
10108e709cbdSnorby 		rt = imsg->data;
10118e709cbdSnorby 
10128e709cbdSnorby 		switch (rt->p_type) {
10138e709cbdSnorby 		case PT_INTRA_AREA:
10148e709cbdSnorby 		case PT_INTER_AREA:
10158e709cbdSnorby 			switch (rt->d_type) {
10168e709cbdSnorby 			case DT_NET:
10178e709cbdSnorby 				if (lasttype != RIB_NET)
10188e709cbdSnorby 					show_rib_head(rt->area, rt->d_type,
10198e709cbdSnorby 					     rt->p_type);
10208e709cbdSnorby 				if (asprintf(&dstnet, "%s/%d",
10218e709cbdSnorby 				    inet_ntoa(rt->prefix), rt->prefixlen) == -1)
10228e709cbdSnorby 					err(1, NULL);
10238e709cbdSnorby 				lasttype = RIB_NET;
10248e709cbdSnorby 				break;
10258e709cbdSnorby 			case DT_RTR:
10268e709cbdSnorby 				if (lasttype != RIB_RTR)
10278e709cbdSnorby 					show_rib_head(rt->area, rt->d_type,
10288e709cbdSnorby 					     rt->p_type);
10298e709cbdSnorby 				if (asprintf(&dstnet, "%s",
10308e709cbdSnorby 				    inet_ntoa(rt->prefix)) == -1)
10318e709cbdSnorby 					err(1, NULL);
10328e709cbdSnorby 				lasttype = RIB_RTR;
10338e709cbdSnorby 				break;
10348e709cbdSnorby 			default:
10358e709cbdSnorby 				errx(1, "unknown route type");
10368e709cbdSnorby 			}
10378e709cbdSnorby 			printf("%-18s %-15s ", dstnet, inet_ntoa(rt->nexthop));
10388e709cbdSnorby 			printf("%-15s %-12s %-7d", inet_ntoa(rt->adv_rtr),
10398e709cbdSnorby 			    path_type_name(rt->p_type), rt->cost);
10408e709cbdSnorby 			free(dstnet);
10418e709cbdSnorby 
10428e709cbdSnorby 			if (rt->d_type == DT_RTR)
10438e709cbdSnorby 				printf(" %-7s",
10448e709cbdSnorby 				    print_ospf_rtr_flags(rt->flags));
10458e709cbdSnorby 
10468e709cbdSnorby 			printf("\n");
10478e709cbdSnorby 			break;
10488e709cbdSnorby 		case PT_TYPE1_EXT:
10498e709cbdSnorby 		case PT_TYPE2_EXT:
10508e709cbdSnorby 			if (lasttype != RIB_EXT)
10518e709cbdSnorby 				show_rib_head(rt->area, rt->d_type, rt->p_type);
10528e709cbdSnorby 
10538e709cbdSnorby 			if (asprintf(&dstnet, "%s/%d",
10548e709cbdSnorby 			    inet_ntoa(rt->prefix), rt->prefixlen) == -1)
10558e709cbdSnorby 				err(1, NULL);
10568e709cbdSnorby 
10578e709cbdSnorby 			printf("%-18s %-15s ", dstnet, inet_ntoa(rt->nexthop));
10588e709cbdSnorby 			printf("%-15s %-12s %-7d %-7d\n",
10598e709cbdSnorby 			    inet_ntoa(rt->adv_rtr), path_type_name(rt->p_type),
10608e709cbdSnorby 			    rt->cost, rt->cost2);
10618e709cbdSnorby 
10628e709cbdSnorby 			lasttype = RIB_EXT;
10638e709cbdSnorby 			break;
10648e709cbdSnorby 		default:
10658e709cbdSnorby 			errx(1, "unknown route type");
10668e709cbdSnorby 		}
10678e709cbdSnorby 		break;
10688e709cbdSnorby 	case IMSG_CTL_AREA:
10698e709cbdSnorby 		area = imsg->data;
10708e709cbdSnorby 		area_id = area->id;
10718e709cbdSnorby 		break;
10728e709cbdSnorby 	case IMSG_CTL_END:
10738e709cbdSnorby 		printf("\n");
10748e709cbdSnorby 		return (1);
10758e709cbdSnorby 	default:
10768e709cbdSnorby 		break;
10778e709cbdSnorby 	}
10788e709cbdSnorby 
10798e709cbdSnorby 	return (0);
10808e709cbdSnorby }
10818e709cbdSnorby 
10828e709cbdSnorby void
10838e709cbdSnorby show_fib_head(void)
10848e709cbdSnorby {
10858e709cbdSnorby 	printf("flags: * = valid, O = OSPF, C = Connected, S = Static\n");
10868e709cbdSnorby 	printf("%-6s %-20s %-17s\n", "Flags", "Destination", "Nexthop");
10878e709cbdSnorby }
10888e709cbdSnorby 
10898e709cbdSnorby int
10908e709cbdSnorby show_fib_msg(struct imsg *imsg)
10918e709cbdSnorby {
10928e709cbdSnorby 	struct kroute		*k;
10938e709cbdSnorby 	char			*p;
10948e709cbdSnorby 
10958e709cbdSnorby 	switch (imsg->hdr.type) {
10968e709cbdSnorby 	case IMSG_CTL_KROUTE:
10978e709cbdSnorby 		if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute))
10988e709cbdSnorby 			errx(1, "wrong imsg len");
10998e709cbdSnorby 		k = imsg->data;
11008e709cbdSnorby 
11018e709cbdSnorby 		if (k->flags & F_DOWN)
11028e709cbdSnorby 			printf(" ");
11038e709cbdSnorby 		else
11048e709cbdSnorby 			printf("*");
11058e709cbdSnorby 
11068e709cbdSnorby 		if (!(k->flags & F_KERNEL))
11078e709cbdSnorby 			printf("O");
11088e709cbdSnorby 		else if (k->flags & F_CONNECTED)
11098e709cbdSnorby 			printf("C");
11108e709cbdSnorby 		else if (k->flags & F_STATIC)
11118e709cbdSnorby 			printf("S");
11128e709cbdSnorby 		else
11138e709cbdSnorby 			printf(" ");
11148e709cbdSnorby 
11158e709cbdSnorby 		printf("     ");
11168e709cbdSnorby 		if (asprintf(&p, "%s/%u", inet_ntoa(k->prefix), k->prefixlen) ==
11178e709cbdSnorby 		    -1)
11188e709cbdSnorby 			err(1, NULL);
11198e709cbdSnorby 		printf("%-20s ", p);
11208e709cbdSnorby 		free(p);
11218e709cbdSnorby 
11228e709cbdSnorby 		if (k->nexthop.s_addr)
11238e709cbdSnorby 			printf("%s", inet_ntoa(k->nexthop));
11248e709cbdSnorby 		else if (k->flags & F_CONNECTED)
11258e709cbdSnorby 			printf("link#%u", k->ifindex);
11268e709cbdSnorby 		printf("\n");
11278e709cbdSnorby 
11288e709cbdSnorby 		break;
11298e709cbdSnorby 	case IMSG_CTL_END:
11308e709cbdSnorby 		printf("\n");
11318e709cbdSnorby 		return (1);
11328e709cbdSnorby 	default:
11338e709cbdSnorby 		break;
11348e709cbdSnorby 	}
11358e709cbdSnorby 
11368e709cbdSnorby 	return (0);
11378e709cbdSnorby }
11388e709cbdSnorby 
11398e709cbdSnorby void
11408e709cbdSnorby show_interface_head(void)
11418e709cbdSnorby {
11428e709cbdSnorby 	printf("%-15s%-15s%s\n", "Interface", "Flags",
11438e709cbdSnorby 	    "Link state");
11448e709cbdSnorby }
11458e709cbdSnorby 
11468e709cbdSnorby const int	ifm_status_valid_list[] = IFM_STATUS_VALID_LIST;
11478e709cbdSnorby const struct ifmedia_status_description
11488e709cbdSnorby 		ifm_status_descriptions[] = IFM_STATUS_DESCRIPTIONS;
11498e709cbdSnorby const struct ifmedia_description
11508e709cbdSnorby 		ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS;
11518e709cbdSnorby 
11528e709cbdSnorby const char *
11538e709cbdSnorby get_media_descr(int media_type)
11548e709cbdSnorby {
11558e709cbdSnorby 	const struct ifmedia_description	*p;
11568e709cbdSnorby 
11578e709cbdSnorby 	for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++)
11588e709cbdSnorby 		if (media_type == p->ifmt_word)
11598e709cbdSnorby 			return (p->ifmt_string);
11608e709cbdSnorby 
11618e709cbdSnorby 	return ("unknown");
11628e709cbdSnorby }
11638e709cbdSnorby 
11648e709cbdSnorby const char *
11658e709cbdSnorby get_linkstate(int media_type, int link_state)
11668e709cbdSnorby {
11678e709cbdSnorby 	const struct ifmedia_status_description	*p;
11688e709cbdSnorby 	int					 i;
11698e709cbdSnorby 
11708e709cbdSnorby 	if (link_state == LINK_STATE_UNKNOWN)
11718e709cbdSnorby 		return ("unknown");
11728e709cbdSnorby 
11738e709cbdSnorby 	for (i = 0; ifm_status_valid_list[i] != 0; i++)
11748e709cbdSnorby 		for (p = ifm_status_descriptions; p->ifms_valid != 0; p++) {
11758e709cbdSnorby 			if (p->ifms_type != media_type ||
11768e709cbdSnorby 			    p->ifms_valid != ifm_status_valid_list[i])
11778e709cbdSnorby 				continue;
11788e709cbdSnorby 			if (LINK_STATE_IS_UP(link_state))
11798e709cbdSnorby 				return (p->ifms_string[1]);
11808e709cbdSnorby 			return (p->ifms_string[0]);
11818e709cbdSnorby 		}
11828e709cbdSnorby 
11838e709cbdSnorby 	return ("unknown");
11848e709cbdSnorby }
11858e709cbdSnorby 
11868e709cbdSnorby void
11878e709cbdSnorby print_baudrate(u_int64_t baudrate)
11888e709cbdSnorby {
11898e709cbdSnorby 	if (baudrate > IF_Gbps(1))
11908e709cbdSnorby 		printf("%llu GBit/s", baudrate / IF_Gbps(1));
11918e709cbdSnorby 	else if (baudrate > IF_Mbps(1))
11928e709cbdSnorby 		printf("%llu MBit/s", baudrate / IF_Mbps(1));
11938e709cbdSnorby 	else if (baudrate > IF_Kbps(1))
11948e709cbdSnorby 		printf("%llu KBit/s", baudrate / IF_Kbps(1));
11958e709cbdSnorby 	else
11968e709cbdSnorby 		printf("%llu Bit/s", baudrate);
11978e709cbdSnorby }
11988e709cbdSnorby 
11998e709cbdSnorby int
12008e709cbdSnorby show_fib_interface_msg(struct imsg *imsg)
12018e709cbdSnorby {
12028e709cbdSnorby 	struct kif	*k;
12038e709cbdSnorby 	int		 ifms_type;
12048e709cbdSnorby 
12058e709cbdSnorby 	switch (imsg->hdr.type) {
12068e709cbdSnorby 	case IMSG_CTL_IFINFO:
12078e709cbdSnorby 		k = imsg->data;
12088e709cbdSnorby 		printf("%-15s", k->ifname);
12098e709cbdSnorby 		printf("%-15s", k->flags & IFF_UP ? "UP" : "");
12108e709cbdSnorby 		switch (k->media_type) {
12118e709cbdSnorby 		case IFT_ETHER:
12128e709cbdSnorby 			ifms_type = IFM_ETHER;
12138e709cbdSnorby 			break;
12148e709cbdSnorby 		case IFT_FDDI:
12158e709cbdSnorby 			ifms_type = IFM_FDDI;
12168e709cbdSnorby 			break;
12178e709cbdSnorby 		case IFT_CARP:
12188e709cbdSnorby 			ifms_type = IFM_CARP;
12198e709cbdSnorby 			break;
12208e709cbdSnorby 		default:
12218e709cbdSnorby 			ifms_type = 0;
12228e709cbdSnorby 			break;
12238e709cbdSnorby 		}
12248e709cbdSnorby 
12258e709cbdSnorby 		if (ifms_type)
12268e709cbdSnorby 			printf("%s, %s", get_media_descr(ifms_type),
12278e709cbdSnorby 			    get_linkstate(ifms_type, k->link_state));
12288e709cbdSnorby 		else if (k->link_state == LINK_STATE_UNKNOWN)
12298e709cbdSnorby 			printf("unknown");
12308e709cbdSnorby 		else
12318e709cbdSnorby 			printf("link state %u", k->link_state);
12328e709cbdSnorby 
12338e709cbdSnorby 		if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) {
12348e709cbdSnorby 			printf(", ");
12358e709cbdSnorby 			print_baudrate(k->baudrate);
12368e709cbdSnorby 		}
12378e709cbdSnorby 		printf("\n");
12388e709cbdSnorby 		break;
12398e709cbdSnorby 	case IMSG_CTL_END:
12408e709cbdSnorby 		printf("\n");
12418e709cbdSnorby 		return (1);
12428e709cbdSnorby 	default:
12438e709cbdSnorby 		break;
12448e709cbdSnorby 	}
12458e709cbdSnorby 
12468e709cbdSnorby 	return (0);
12478e709cbdSnorby }
1248