xref: /openbsd/usr.sbin/ospf6ctl/ospf6ctl.c (revision dd3b9a80)
1*dd3b9a80Ssthen /*	$OpenBSD: ospf6ctl.c,v 1.54 2023/06/21 09:47:03 sthen 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>
30c0dbf5cfSsthen #include <errno.h>
318e709cbdSnorby #include <stdio.h>
328e709cbdSnorby #include <stdlib.h>
338e709cbdSnorby #include <string.h>
348e709cbdSnorby #include <unistd.h>
358e709cbdSnorby 
368e709cbdSnorby #include "ospf6.h"
378e709cbdSnorby #include "ospf6d.h"
388e709cbdSnorby #include "ospfe.h"
398e709cbdSnorby #include "parser.h"
408e709cbdSnorby #include "log.h"
418e709cbdSnorby 
428e709cbdSnorby __dead void	 usage(void);
438e709cbdSnorby int		 show_summary_msg(struct imsg *);
4418ffdd94Sstsp uint64_t	 get_ifms_type(uint8_t);
458e709cbdSnorby int		 show_interface_msg(struct imsg *);
468e709cbdSnorby int		 show_interface_detail_msg(struct imsg *);
478e709cbdSnorby const char	*print_link(int);
488e709cbdSnorby const char	*fmt_timeframe(time_t t);
498e709cbdSnorby const char	*fmt_timeframe_core(time_t t);
508e709cbdSnorby const char	*log_id(u_int32_t );
518e709cbdSnorby const char	*log_adv_rtr(u_int32_t);
52cb01fa27Sclaudio void		 show_database_head(struct in_addr, char *, u_int16_t);
538e709cbdSnorby int		 show_database_msg(struct imsg *);
544fabe8f9Snorby char		*print_ls_type(u_int16_t);
558e709cbdSnorby void		 show_db_hdr_msg_detail(struct lsa_hdr *);
568e709cbdSnorby char		*print_rtr_link_type(u_int8_t);
578e709cbdSnorby const char	*print_ospf_flags(u_int8_t);
581aff836dSclaudio const char	*print_asext_flags(u_int32_t);
591aff836dSclaudio const char	*print_prefix_opt(u_int8_t);
608e709cbdSnorby int		 show_db_msg_detail(struct imsg *imsg);
618e709cbdSnorby int		 show_nbr_msg(struct imsg *);
62aff6ccb8Sclaudio const char	*print_ospf_options(u_int32_t);
638e709cbdSnorby int		 show_nbr_detail_msg(struct imsg *);
648e709cbdSnorby int		 show_rib_msg(struct imsg *);
658e709cbdSnorby void		 show_rib_head(struct in_addr, u_int8_t, u_int8_t);
668e709cbdSnorby const char	*print_ospf_rtr_flags(u_int8_t);
678e709cbdSnorby int		 show_rib_detail_msg(struct imsg *);
688e709cbdSnorby void		 show_fib_head(void);
698e709cbdSnorby int		 show_fib_msg(struct imsg *);
70e5605ae3Sderaadt const char *	 get_media_descr(uint64_t);
7118ffdd94Sstsp const char *	 get_linkstate(uint8_t, int);
728e709cbdSnorby void		 print_baudrate(u_int64_t);
738e709cbdSnorby 
748e709cbdSnorby struct imsgbuf	*ibuf;
758e709cbdSnorby 
768e709cbdSnorby __dead void
usage(void)778e709cbdSnorby usage(void)
788e709cbdSnorby {
798e709cbdSnorby 	extern char *__progname;
808e709cbdSnorby 
81c2ca8945Ssthen 	fprintf(stderr, "usage: %s [-s socket] command [argument ...]\n",
82c2ca8945Ssthen 	    __progname);
838e709cbdSnorby 	exit(1);
848e709cbdSnorby }
858e709cbdSnorby 
868e709cbdSnorby int
main(int argc,char * argv[])878e709cbdSnorby main(int argc, char *argv[])
888e709cbdSnorby {
898e709cbdSnorby 	struct sockaddr_un	 sun;
908e709cbdSnorby 	struct parse_result	*res;
918e709cbdSnorby 	struct imsg		 imsg;
928e709cbdSnorby 	unsigned int		 ifidx = 0;
935d393f89Sremi 	int			 ctl_sock, r;
94c3319070Sclaudio 	int			 done = 0, verbose = 0;
958e709cbdSnorby 	int			 n;
96c2ca8945Ssthen 	int			 ch;
97c2ca8945Ssthen 	char			*sockname;
98c2ca8945Ssthen 
995d393f89Sremi 	r = getrtable();
1005d393f89Sremi 	if (asprintf(&sockname, "%s.%d", OSPF6D_SOCKET, r) == -1)
1015d393f89Sremi 		err(1, "asprintf");
1025d393f89Sremi 
103c2ca8945Ssthen 	while ((ch = getopt(argc, argv, "s:")) != -1) {
104c2ca8945Ssthen 		switch (ch) {
105c2ca8945Ssthen 		case 's':
106c2ca8945Ssthen 			sockname = optarg;
107c2ca8945Ssthen 			break;
108c2ca8945Ssthen 		default:
109c2ca8945Ssthen 			usage();
110c2ca8945Ssthen 			/* NOTREACHED */
111c2ca8945Ssthen 		}
112c2ca8945Ssthen 	}
113c2ca8945Ssthen 	argc -= optind;
114c2ca8945Ssthen 	argv += optind;
1158e709cbdSnorby 
1168e709cbdSnorby 	/* parse options */
117c2ca8945Ssthen 	if ((res = parse(argc, argv)) == NULL)
1188e709cbdSnorby 		exit(1);
1198e709cbdSnorby 
1208e709cbdSnorby 	/* connect to ospf6d control socket */
1218e709cbdSnorby 	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
1228e709cbdSnorby 		err(1, "socket");
1238e709cbdSnorby 
1248e709cbdSnorby 	bzero(&sun, sizeof(sun));
1258e709cbdSnorby 	sun.sun_family = AF_UNIX;
126c2ca8945Ssthen 	strlcpy(sun.sun_path, sockname, sizeof(sun.sun_path));
1278e709cbdSnorby 	if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1)
128c2ca8945Ssthen 		err(1, "connect: %s", sockname);
1298e709cbdSnorby 
130a18c3fe3Sderaadt 	if (pledge("stdio", NULL) == -1)
131becb4c8cSbenno 		err(1, "pledge");
132becb4c8cSbenno 
1338e709cbdSnorby 	if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
1348e709cbdSnorby 		err(1, NULL);
135f78850efSeric 	imsg_init(ibuf, ctl_sock);
1368e709cbdSnorby 	done = 0;
1378e709cbdSnorby 
1388e709cbdSnorby 	/* process user request */
1398e709cbdSnorby 	switch (res->action) {
1408e709cbdSnorby 	case NONE:
1418e709cbdSnorby 		usage();
1428e709cbdSnorby 		/* not reached */
1438e709cbdSnorby 	case SHOW:
1448e709cbdSnorby 	case SHOW_SUM:
145f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_SUM, 0, 0, -1, NULL, 0);
1468e709cbdSnorby 		break;
1478e709cbdSnorby 	case SHOW_IFACE:
1481fed8bffSnorby 		printf("%-11s %-29s %-6s %-10s %-10s %-8s\n",
1498e709cbdSnorby 		    "Interface", "Address", "State", "HelloTimer", "Linkstate",
1501fed8bffSnorby 		    "Uptime");
151c5ba8b41Sderaadt 		/*FALLTHROUGH*/
1528e709cbdSnorby 	case SHOW_IFACE_DTAIL:
1538e709cbdSnorby 		if (*res->ifname) {
1548e709cbdSnorby 			ifidx = if_nametoindex(res->ifname);
1558e709cbdSnorby 			if (ifidx == 0)
1568e709cbdSnorby 				errx(1, "no such interface %s", res->ifname);
1578e709cbdSnorby 		}
158f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1,
1598e709cbdSnorby 		    &ifidx, sizeof(ifidx));
1608e709cbdSnorby 		break;
1618e709cbdSnorby 	case SHOW_NBR:
162558ada41Snorby 		printf("%-15s %-3s %-12s %-9s %-11s %s\n", "ID", "Pri",
163558ada41Snorby 		    "State", "DeadTime", "Iface","Uptime");
164c5ba8b41Sderaadt 		/*FALLTHROUGH*/
1658e709cbdSnorby 	case SHOW_NBR_DTAIL:
166f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0);
1678e709cbdSnorby 		break;
1688e709cbdSnorby 	case SHOW_DB:
169f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1, NULL, 0);
1708e709cbdSnorby 		break;
1718e709cbdSnorby 	case SHOW_DBBYAREA:
172f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1,
17396950f83Sremi 		    &res->area, sizeof(res->area));
1748e709cbdSnorby 		break;
1758e709cbdSnorby 	case SHOW_DBEXT:
176f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_EXT, 0, 0, -1, NULL, 0);
1778e709cbdSnorby 		break;
178aeb06b08Sclaudio 	case SHOW_DBLINK:
179f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_LINK, 0, 0, -1, NULL, 0);
180aeb06b08Sclaudio 		break;
1818e709cbdSnorby 	case SHOW_DBNET:
182f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_NET, 0, 0, -1, NULL, 0);
1838e709cbdSnorby 		break;
1848e709cbdSnorby 	case SHOW_DBRTR:
185f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_RTR, 0, 0, -1, NULL, 0);
1868e709cbdSnorby 		break;
18741bcac6bSstsp 	case SHOW_DBINTRA:
188f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_INTRA, 0, 0, -1, NULL, 0);
18941bcac6bSstsp 		break;
1908e709cbdSnorby 	case SHOW_DBSELF:
191f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SELF, 0, 0, -1, NULL, 0);
1928e709cbdSnorby 		break;
1938e709cbdSnorby 	case SHOW_DBSUM:
194f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SUM, 0, 0, -1, NULL, 0);
1958e709cbdSnorby 		break;
1968e709cbdSnorby 	case SHOW_DBASBR:
197f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_ASBR, 0, 0, -1, NULL, 0);
1988e709cbdSnorby 		break;
1998e709cbdSnorby 	case SHOW_RIB:
2008e709cbdSnorby 		printf("%-20s %-17s %-12s %-9s %-7s %-8s\n", "Destination",
2018e709cbdSnorby 		    "Nexthop", "Path Type", "Type", "Cost", "Uptime");
202c5ba8b41Sderaadt 		/*FALLTHROUGH*/
2038e709cbdSnorby 	case SHOW_RIB_DTAIL:
204f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, -1, NULL, 0);
2058e709cbdSnorby 		break;
2068e709cbdSnorby 	case SHOW_FIB:
2070104e403Sclaudio 		if (IN6_IS_ADDR_UNSPECIFIED(&res->addr))
208f78850efSeric 			imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0, -1,
2098e709cbdSnorby 			    &res->flags, sizeof(res->flags));
2108e709cbdSnorby 		else
211f78850efSeric 			imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1,
2128e709cbdSnorby 			    &res->addr, sizeof(res->addr));
2138e709cbdSnorby 		show_fib_head();
2148e709cbdSnorby 		break;
2158e709cbdSnorby 	case FIB:
2168e709cbdSnorby 		errx(1, "fib couple|decouple");
2178e709cbdSnorby 		break;
2188e709cbdSnorby 	case FIB_COUPLE:
219f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, -1, NULL, 0);
2208e709cbdSnorby 		printf("couple request sent.\n");
2218e709cbdSnorby 		done = 1;
2228e709cbdSnorby 		break;
2238e709cbdSnorby 	case FIB_DECOUPLE:
224f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, -1, NULL, 0);
2258e709cbdSnorby 		printf("decouple request sent.\n");
2268e709cbdSnorby 		done = 1;
2278e709cbdSnorby 		break;
228*dd3b9a80Ssthen 	case FIB_RELOAD:
229*dd3b9a80Ssthen 		imsg_compose(ibuf, IMSG_CTL_FIB_RELOAD, 0, 0, -1, NULL, 0);
230*dd3b9a80Ssthen 		printf("reload request sent.\n");
231*dd3b9a80Ssthen 		done = 1;
232*dd3b9a80Ssthen 		break;
233c3319070Sclaudio 	case LOG_VERBOSE:
234c3319070Sclaudio 		verbose = 1;
235c3319070Sclaudio 		/* FALLTHROUGH */
236c3319070Sclaudio 	case LOG_BRIEF:
237c3319070Sclaudio 		imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1,
238c3319070Sclaudio 		    &verbose, sizeof(verbose));
239c3319070Sclaudio 		printf("logging request sent.\n");
240c3319070Sclaudio 		done = 1;
241c3319070Sclaudio 		break;
2428e709cbdSnorby 	case RELOAD:
2438bf9509aSjca #ifdef notyet
244f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0);
2458e709cbdSnorby 		printf("reload request sent.\n");
2468e709cbdSnorby 		done = 1;
2478e709cbdSnorby 		break;
2488bf9509aSjca #else
2498bf9509aSjca 		errx(1, "reload not supported");
2508bf9509aSjca #endif
2518e709cbdSnorby 	}
2528e709cbdSnorby 
2538e709cbdSnorby 	while (ibuf->w.queued)
254c0dbf5cfSsthen 		if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
2558e709cbdSnorby 			err(1, "write error");
2568e709cbdSnorby 
2578e709cbdSnorby 	while (!done) {
258262992b2Sclaudio 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
2598e709cbdSnorby 			errx(1, "imsg_read error");
2608e709cbdSnorby 		if (n == 0)
2618e709cbdSnorby 			errx(1, "pipe closed");
2628e709cbdSnorby 
2638e709cbdSnorby 		while (!done) {
2648e709cbdSnorby 			if ((n = imsg_get(ibuf, &imsg)) == -1)
2658e709cbdSnorby 				errx(1, "imsg_get error");
2668e709cbdSnorby 			if (n == 0)
2678e709cbdSnorby 				break;
2688e709cbdSnorby 			switch (res->action) {
2698e709cbdSnorby 			case SHOW:
2708e709cbdSnorby 			case SHOW_SUM:
2718e709cbdSnorby 				done = show_summary_msg(&imsg);
2728e709cbdSnorby 				break;
2738e709cbdSnorby 			case SHOW_IFACE:
2748e709cbdSnorby 				done = show_interface_msg(&imsg);
2758e709cbdSnorby 				break;
2768e709cbdSnorby 			case SHOW_IFACE_DTAIL:
2778e709cbdSnorby 				done = show_interface_detail_msg(&imsg);
2788e709cbdSnorby 				break;
2798e709cbdSnorby 			case SHOW_NBR:
2808e709cbdSnorby 				done = show_nbr_msg(&imsg);
2818e709cbdSnorby 				break;
2828e709cbdSnorby 			case SHOW_NBR_DTAIL:
2838e709cbdSnorby 				done = show_nbr_detail_msg(&imsg);
2848e709cbdSnorby 				break;
2858e709cbdSnorby 			case SHOW_DB:
2868e709cbdSnorby 			case SHOW_DBBYAREA:
2878e709cbdSnorby 			case SHOW_DBSELF:
2888e709cbdSnorby 				done = show_database_msg(&imsg);
2898e709cbdSnorby 				break;
2908e709cbdSnorby 			case SHOW_DBEXT:
291aeb06b08Sclaudio 			case SHOW_DBLINK:
2928e709cbdSnorby 			case SHOW_DBNET:
2938e709cbdSnorby 			case SHOW_DBRTR:
29441bcac6bSstsp 			case SHOW_DBINTRA:
2958e709cbdSnorby 			case SHOW_DBSUM:
2968e709cbdSnorby 			case SHOW_DBASBR:
2978e709cbdSnorby 				done = show_db_msg_detail(&imsg);
2988e709cbdSnorby 				break;
2998e709cbdSnorby 			case SHOW_RIB:
3008e709cbdSnorby 				done = show_rib_msg(&imsg);
3018e709cbdSnorby 				break;
3028e709cbdSnorby 			case SHOW_RIB_DTAIL:
3038e709cbdSnorby 				done = show_rib_detail_msg(&imsg);
3048e709cbdSnorby 				break;
3058e709cbdSnorby 			case SHOW_FIB:
3068e709cbdSnorby 				done = show_fib_msg(&imsg);
3078e709cbdSnorby 				break;
3088e709cbdSnorby 			case NONE:
3098e709cbdSnorby 			case FIB:
3108e709cbdSnorby 			case FIB_COUPLE:
3118e709cbdSnorby 			case FIB_DECOUPLE:
312*dd3b9a80Ssthen 			case FIB_RELOAD:
313c3319070Sclaudio 			case LOG_VERBOSE:
314c3319070Sclaudio 			case LOG_BRIEF:
3158e709cbdSnorby 			case RELOAD:
3168e709cbdSnorby 				break;
3178e709cbdSnorby 			}
3188e709cbdSnorby 			imsg_free(&imsg);
3198e709cbdSnorby 		}
3208e709cbdSnorby 	}
3218e709cbdSnorby 	close(ctl_sock);
3228e709cbdSnorby 	free(ibuf);
3238e709cbdSnorby 
3248e709cbdSnorby 	return (0);
3258e709cbdSnorby }
3268e709cbdSnorby 
3278e709cbdSnorby int
show_summary_msg(struct imsg * imsg)3288e709cbdSnorby show_summary_msg(struct imsg *imsg)
3298e709cbdSnorby {
3308e709cbdSnorby 	struct ctl_sum		*sum;
3318e709cbdSnorby 	struct ctl_sum_area	*sumarea;
3328e709cbdSnorby 
3338e709cbdSnorby 	switch (imsg->hdr.type) {
3348e709cbdSnorby 	case IMSG_CTL_SHOW_SUM:
3358e709cbdSnorby 		sum = imsg->data;
3368e709cbdSnorby 		printf("Router ID: %s\n", inet_ntoa(sum->rtr_id));
3378e709cbdSnorby 		printf("Uptime: %s\n", fmt_timeframe_core(sum->uptime));
3388e709cbdSnorby 
3398e709cbdSnorby 		printf("SPF delay is %d sec(s), hold time between two SPFs "
3408e709cbdSnorby 		    "is %d sec(s)\n", sum->spf_delay, sum->spf_hold_time);
3418e709cbdSnorby 		printf("Number of external LSA(s) %d\n", sum->num_ext_lsa);
3428e709cbdSnorby 		printf("Number of areas attached to this router: %d\n",
3438e709cbdSnorby 		    sum->num_area);
3448e709cbdSnorby 		break;
3458e709cbdSnorby 	case IMSG_CTL_SHOW_SUM_AREA:
3468e709cbdSnorby 		sumarea = imsg->data;
3478e709cbdSnorby 		printf("\nArea ID: %s\n", inet_ntoa(sumarea->area));
3488e709cbdSnorby 		printf("  Number of interfaces in this area: %d\n",
3498e709cbdSnorby 		    sumarea->num_iface);
3508e709cbdSnorby 		printf("  Number of fully adjacent neighbors in this "
3518e709cbdSnorby 		    "area: %d\n", sumarea->num_adj_nbr);
3528e709cbdSnorby 		printf("  SPF algorithm executed %d time(s)\n",
3538e709cbdSnorby 		    sumarea->num_spf_calc);
3548e709cbdSnorby 		printf("  Number LSA(s) %d\n", sumarea->num_lsa);
3558e709cbdSnorby 		break;
3568e709cbdSnorby 	case IMSG_CTL_END:
3578e709cbdSnorby 		printf("\n");
3588e709cbdSnorby 		return (1);
3598e709cbdSnorby 	default:
3608e709cbdSnorby 		break;
3618e709cbdSnorby 	}
3628e709cbdSnorby 
3638e709cbdSnorby 	return (0);
3648e709cbdSnorby }
3658e709cbdSnorby 
36618ffdd94Sstsp uint64_t
get_ifms_type(uint8_t if_type)36718ffdd94Sstsp get_ifms_type(uint8_t if_type)
3688e709cbdSnorby {
36918ffdd94Sstsp 	switch (if_type) {
3708e709cbdSnorby 	case IFT_ETHER:
3718e709cbdSnorby 		return (IFM_ETHER);
3728e709cbdSnorby 	case IFT_FDDI:
3738e709cbdSnorby 		return (IFM_FDDI);
3748e709cbdSnorby 	case IFT_CARP:
3758e709cbdSnorby 		return (IFM_CARP);
3768e709cbdSnorby 	case IFT_PPP:
3778e709cbdSnorby 		return (IFM_TDM);
3788e709cbdSnorby 	default:
3798e709cbdSnorby 		return (0);
3808e709cbdSnorby 	}
3818e709cbdSnorby }
3828e709cbdSnorby 
3838e709cbdSnorby int
show_interface_msg(struct imsg * imsg)3848e709cbdSnorby show_interface_msg(struct imsg *imsg)
3858e709cbdSnorby {
3868e709cbdSnorby 	struct ctl_iface	*iface;
3878e709cbdSnorby 	char			*netid;
3888e709cbdSnorby 
3898e709cbdSnorby 	switch (imsg->hdr.type) {
3908e709cbdSnorby 	case IMSG_CTL_SHOW_INTERFACE:
3918e709cbdSnorby 		iface = imsg->data;
3928e709cbdSnorby 
3938e709cbdSnorby 		if (asprintf(&netid, "%s", log_in6addr(&iface->addr)) == -1)
3948e709cbdSnorby 			err(1, NULL);
3951fed8bffSnorby 		printf("%-11s %-29s %-6s %-10s %-10s %s\n",
3968e709cbdSnorby 		    iface->name, netid, if_state_name(iface->state),
3971dfb70a2Sclaudio 		    iface->hello_timer < 0 ? "-" :
3988e709cbdSnorby 		    fmt_timeframe_core(iface->hello_timer),
39918ffdd94Sstsp 		    get_linkstate(iface->if_type, iface->linkstate),
4000f617141Sclaudio 		    fmt_timeframe_core(iface->uptime));
4018e709cbdSnorby 		free(netid);
4028e709cbdSnorby 		break;
4038e709cbdSnorby 	case IMSG_CTL_END:
4048e709cbdSnorby 		printf("\n");
4058e709cbdSnorby 		return (1);
4068e709cbdSnorby 	default:
4078e709cbdSnorby 		break;
4088e709cbdSnorby 	}
4098e709cbdSnorby 
4108e709cbdSnorby 	return (0);
4118e709cbdSnorby }
4128e709cbdSnorby 
4138e709cbdSnorby int
show_interface_detail_msg(struct imsg * imsg)4148e709cbdSnorby show_interface_detail_msg(struct imsg *imsg)
4158e709cbdSnorby {
4168e709cbdSnorby 	struct ctl_iface	*iface;
4178e709cbdSnorby 
4188e709cbdSnorby 	switch (imsg->hdr.type) {
4198e709cbdSnorby 	case IMSG_CTL_SHOW_INTERFACE:
4208e709cbdSnorby 		iface = imsg->data;
4218e709cbdSnorby 		printf("\n");
4228e709cbdSnorby 		printf("Interface %s, line protocol is %s\n",
4238e709cbdSnorby 		    iface->name, print_link(iface->flags));
424ab5e4d03Sclaudio 		printf("  Internet address %s Area %s\n",
425ab5e4d03Sclaudio 		    log_in6addr(&iface->addr), inet_ntoa(iface->area));
42637f8d125Sjca 		printf("  Link type %s, state %s, mtu %d",
42718ffdd94Sstsp 		    get_media_descr(get_ifms_type(iface->if_type)),
42837f8d125Sjca 		    get_linkstate(iface->if_type, iface->linkstate),
42937f8d125Sjca 		    iface->mtu);
430ab5e4d03Sclaudio 		if (iface->linkstate != LINK_STATE_DOWN &&
431ab5e4d03Sclaudio 		    iface->baudrate > 0) {
432ab5e4d03Sclaudio 		    printf(", ");
433ab5e4d03Sclaudio 		    print_baudrate(iface->baudrate);
434ab5e4d03Sclaudio 		}
435ab5e4d03Sclaudio 		printf("\n");
4368e709cbdSnorby 		printf("  Router ID %s, network type %s, cost: %d\n",
4378e709cbdSnorby 		    inet_ntoa(iface->rtr_id),
4388e709cbdSnorby 		    if_type_name(iface->type), iface->metric);
4398e709cbdSnorby 		printf("  Transmit delay is %d sec(s), state %s, priority %d\n",
4408e709cbdSnorby 		    iface->transmit_delay, if_state_name(iface->state),
4418e709cbdSnorby 		    iface->priority);
4427aab4200Snorby 		printf("  Designated Router (ID) %s\n",
4438e709cbdSnorby 		    inet_ntoa(iface->dr_id));
4447aab4200Snorby 		printf("    Interface address %s\n",
4457aab4200Snorby 		    log_in6addr(&iface->dr_addr));
4467aab4200Snorby 		printf("  Backup Designated Router (ID) %s\n",
4478e709cbdSnorby 		    inet_ntoa(iface->bdr_id));
4487aab4200Snorby 		printf("    Interface address %s\n",
4497aab4200Snorby 		    log_in6addr(&iface->bdr_addr));
4508e709cbdSnorby 		printf("  Timer intervals configured, "
4518e709cbdSnorby 		    "hello %d, dead %d, wait %d, retransmit %d\n",
4528e709cbdSnorby 		     iface->hello_interval, iface->dead_interval,
4538e709cbdSnorby 		     iface->dead_interval, iface->rxmt_interval);
4548e709cbdSnorby 		if (iface->passive)
4558e709cbdSnorby 			printf("    Passive interface (No Hellos)\n");
4568e709cbdSnorby 		else if (iface->hello_timer < 0)
4578e709cbdSnorby 			printf("    Hello timer not running\n");
4588e709cbdSnorby 		else
4598e709cbdSnorby 			printf("    Hello timer due in %s\n",
4608e709cbdSnorby 			    fmt_timeframe_core(iface->hello_timer));
4618e709cbdSnorby 		printf("    Uptime %s\n", fmt_timeframe_core(iface->uptime));
4628e709cbdSnorby 		printf("  Neighbor count is %d, adjacent neighbor count is "
4638e709cbdSnorby 		    "%d\n", iface->nbr_cnt, iface->adj_cnt);
4648e709cbdSnorby 		break;
4658e709cbdSnorby 	case IMSG_CTL_END:
4668e709cbdSnorby 		printf("\n");
4678e709cbdSnorby 		return (1);
4688e709cbdSnorby 	default:
4698e709cbdSnorby 		break;
4708e709cbdSnorby 	}
4718e709cbdSnorby 
4728e709cbdSnorby 	return (0);
4738e709cbdSnorby }
4748e709cbdSnorby 
4758e709cbdSnorby const char *
print_link(int state)4768e709cbdSnorby print_link(int state)
4778e709cbdSnorby {
4788e709cbdSnorby 	if (state & IFF_UP)
4798e709cbdSnorby 		return ("UP");
4808e709cbdSnorby 	else
4818e709cbdSnorby 		return ("DOWN");
4828e709cbdSnorby }
4838e709cbdSnorby 
4848e709cbdSnorby #define TF_BUFS	8
4858e709cbdSnorby #define TF_LEN	9
4868e709cbdSnorby 
4878e709cbdSnorby const char *
fmt_timeframe(time_t t)4888e709cbdSnorby fmt_timeframe(time_t t)
4898e709cbdSnorby {
4908e709cbdSnorby 	if (t == 0)
4918e709cbdSnorby 		return ("Never");
4928e709cbdSnorby 	else
4938e709cbdSnorby 		return (fmt_timeframe_core(time(NULL) - t));
4948e709cbdSnorby }
4958e709cbdSnorby 
4968e709cbdSnorby const char *
fmt_timeframe_core(time_t t)4978e709cbdSnorby fmt_timeframe_core(time_t t)
4988e709cbdSnorby {
4998e709cbdSnorby 	char		*buf;
5008e709cbdSnorby 	static char	 tfbuf[TF_BUFS][TF_LEN];	/* ring buffer */
5018e709cbdSnorby 	static int	 idx = 0;
502db93f2f1Sderaadt 	unsigned int	 sec, min, hrs, day, week;
5038e709cbdSnorby 
5048e709cbdSnorby 	if (t == 0)
5058e709cbdSnorby 		return ("00:00:00");
5068e709cbdSnorby 
5078e709cbdSnorby 	buf = tfbuf[idx++];
5088e709cbdSnorby 	if (idx == TF_BUFS)
5098e709cbdSnorby 		idx = 0;
5108e709cbdSnorby 
5118e709cbdSnorby 	week = t;
5128e709cbdSnorby 
5138e709cbdSnorby 	sec = week % 60;
5148e709cbdSnorby 	week /= 60;
5158e709cbdSnorby 	min = week % 60;
5168e709cbdSnorby 	week /= 60;
5178e709cbdSnorby 	hrs = week % 24;
5188e709cbdSnorby 	week /= 24;
5198e709cbdSnorby 	day = week % 7;
5208e709cbdSnorby 	week /= 7;
5218e709cbdSnorby 
5228e709cbdSnorby 	if (week > 0)
5238e709cbdSnorby 		snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs);
5248e709cbdSnorby 	else if (day > 0)
5258e709cbdSnorby 		snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
5268e709cbdSnorby 	else
5278e709cbdSnorby 		snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
5288e709cbdSnorby 
5298e709cbdSnorby 	return (buf);
5308e709cbdSnorby }
5318e709cbdSnorby 
5328e709cbdSnorby const char *
log_id(u_int32_t id)5338e709cbdSnorby log_id(u_int32_t id)
5348e709cbdSnorby {
5358e709cbdSnorby 	static char	buf[48];
5368e709cbdSnorby 	struct in_addr	addr;
5378e709cbdSnorby 
5388e709cbdSnorby 	addr.s_addr = id;
5398e709cbdSnorby 
5408e709cbdSnorby 	if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL)
5418e709cbdSnorby 		return ("?");
5428e709cbdSnorby 	else
5438e709cbdSnorby 		return (buf);
5448e709cbdSnorby }
5458e709cbdSnorby 
5468e709cbdSnorby const char *
log_adv_rtr(u_int32_t adv_rtr)5478e709cbdSnorby log_adv_rtr(u_int32_t adv_rtr)
5488e709cbdSnorby {
5498e709cbdSnorby 	static char	buf[48];
5508e709cbdSnorby 	struct in_addr	addr;
5518e709cbdSnorby 
5528e709cbdSnorby 	addr.s_addr = adv_rtr;
5538e709cbdSnorby 
5548e709cbdSnorby 	if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL)
5558e709cbdSnorby 		return ("?");
5568e709cbdSnorby 	else
5578e709cbdSnorby 		return (buf);
5588e709cbdSnorby }
5598e709cbdSnorby 
5608e709cbdSnorby void
show_database_head(struct in_addr aid,char * ifname,u_int16_t type)561cb01fa27Sclaudio show_database_head(struct in_addr aid, char *ifname, u_int16_t type)
5628e709cbdSnorby {
5638e709cbdSnorby 	char	*header, *format;
564cb01fa27Sclaudio 	int	cleanup = 0;
5658e709cbdSnorby 
566005d568eSclaudio 	switch (ntohs(type)) {
5674fabe8f9Snorby 	case LSA_TYPE_LINK:
5688ea4c735Sclaudio 		format = "Link (Type-8) Link States";
5694fabe8f9Snorby 		break;
5708e709cbdSnorby 	case LSA_TYPE_ROUTER:
5718e709cbdSnorby 		format = "Router Link States";
5728e709cbdSnorby 		break;
5738e709cbdSnorby 	case LSA_TYPE_NETWORK:
5748e709cbdSnorby 		format = "Net Link States";
5758e709cbdSnorby 		break;
5764fabe8f9Snorby 	case LSA_TYPE_INTER_A_PREFIX:
5774fabe8f9Snorby 		format = "Inter Area Prefix Link States";
5788e709cbdSnorby 		break;
5794fabe8f9Snorby 	case LSA_TYPE_INTER_A_ROUTER:
5804fabe8f9Snorby 		format = "Inter Area Router Link States";
5814fabe8f9Snorby 		break;
5824fabe8f9Snorby 	case LSA_TYPE_INTRA_A_PREFIX:
5838ec36425Sstsp 		format = "Intra Area Prefix Link States";
5848e709cbdSnorby 		break;
5858e709cbdSnorby 	case LSA_TYPE_EXTERNAL:
586cb01fa27Sclaudio 		printf("\n%-15s %s\n\n", "", "Type-5 AS External Link States");
587cb01fa27Sclaudio 		return;
5888e709cbdSnorby 	default:
589cb01fa27Sclaudio 		if (asprintf(&format, "LSA type %x", ntohs(type)) == -1)
590cb01fa27Sclaudio 			err(1, NULL);
591cb01fa27Sclaudio 		cleanup = 1;
592cb01fa27Sclaudio 		break;
5938e709cbdSnorby 	}
594cb01fa27Sclaudio 	if (LSA_IS_SCOPE_AREA(ntohs(type))) {
5958e709cbdSnorby 		if (asprintf(&header, "%s (Area %s)", format,
5968e709cbdSnorby 		    inet_ntoa(aid)) == -1)
5978e709cbdSnorby 			err(1, NULL);
598cb01fa27Sclaudio 	} else if (LSA_IS_SCOPE_LLOCAL(ntohs(type))) {
599cb01fa27Sclaudio 		if (asprintf(&header, "%s (Area %s Interface %s)", format,
600cb01fa27Sclaudio 		    inet_ntoa(aid), ifname) == -1)
601cb01fa27Sclaudio 			err(1, NULL);
60273094d71Sbenno 	} else {
60373094d71Sbenno 		if (asprintf(&header, "%s", format) == -1)
60473094d71Sbenno 			err(1, NULL);
605cb01fa27Sclaudio 	}
6068e709cbdSnorby 
6078e709cbdSnorby 	printf("\n%-15s %s\n\n", "", header);
6088e709cbdSnorby 	free(header);
609cb01fa27Sclaudio 	if (cleanup)
610cb01fa27Sclaudio 		free(format);
6118e709cbdSnorby }
6128e709cbdSnorby 
6138e709cbdSnorby int
show_database_msg(struct imsg * imsg)6148e709cbdSnorby show_database_msg(struct imsg *imsg)
6158e709cbdSnorby {
6168e709cbdSnorby 	static struct in_addr	 area_id;
617cb01fa27Sclaudio 	static char		 ifname[IF_NAMESIZE];
6187db04f17Sclaudio 	static u_int16_t	 lasttype;
6198e709cbdSnorby 	struct area		*area;
620cb01fa27Sclaudio 	struct iface		*iface;
6218e709cbdSnorby 	struct lsa_hdr		*lsa;
6228e709cbdSnorby 
6238e709cbdSnorby 	switch (imsg->hdr.type) {
6248e709cbdSnorby 	case IMSG_CTL_SHOW_DATABASE:
6258e709cbdSnorby 	case IMSG_CTL_SHOW_DB_SELF:
6268e709cbdSnorby 		lsa = imsg->data;
6278e709cbdSnorby 		if (lsa->type != lasttype) {
628cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->type);
6298e709cbdSnorby 			printf("%-15s %-15s %-4s %-10s %-8s\n", "Link ID",
6308e709cbdSnorby 			    "Adv Router", "Age", "Seq#", "Checksum");
6318e709cbdSnorby 		}
6328e709cbdSnorby 		printf("%-15s %-15s %-4d 0x%08x 0x%04x\n",
6338e709cbdSnorby 		    log_id(lsa->ls_id), log_adv_rtr(lsa->adv_rtr),
6348e709cbdSnorby 		    ntohs(lsa->age), ntohl(lsa->seq_num),
6358e709cbdSnorby 		    ntohs(lsa->ls_chksum));
6368e709cbdSnorby 		lasttype = lsa->type;
6378e709cbdSnorby 		break;
6388e709cbdSnorby 	case IMSG_CTL_AREA:
6398e709cbdSnorby 		area = imsg->data;
6408e709cbdSnorby 		area_id = area->id;
6418e709cbdSnorby 		lasttype = 0;
6428e709cbdSnorby 		break;
643cb01fa27Sclaudio 	case IMSG_CTL_IFACE:
644cb01fa27Sclaudio 		iface = imsg->data;
645cb01fa27Sclaudio 		strlcpy(ifname, iface->name, sizeof(ifname));
646cb01fa27Sclaudio 		lasttype = 0;
647cb01fa27Sclaudio 		break;
6488e709cbdSnorby 	case IMSG_CTL_END:
6498e709cbdSnorby 		printf("\n");
6508e709cbdSnorby 		return (1);
6518e709cbdSnorby 	default:
6528e709cbdSnorby 		break;
6538e709cbdSnorby 	}
6548e709cbdSnorby 
6558e709cbdSnorby 	return (0);
6568e709cbdSnorby }
6578e709cbdSnorby 
6588e709cbdSnorby char *
print_ls_type(u_int16_t type)6594fabe8f9Snorby print_ls_type(u_int16_t type)
6608e709cbdSnorby {
661005d568eSclaudio 	switch (ntohs(type)) {
6624fabe8f9Snorby 	case LSA_TYPE_LINK:
6634fabe8f9Snorby 		return ("Link");
6648e709cbdSnorby 	case LSA_TYPE_ROUTER:
6658e709cbdSnorby 		return ("Router");
6668e709cbdSnorby 	case LSA_TYPE_NETWORK:
6678e709cbdSnorby 		return ("Network");
6684fabe8f9Snorby 	case LSA_TYPE_INTER_A_PREFIX:
6694fabe8f9Snorby 		return ("Inter Area (Prefix)");
6704fabe8f9Snorby 	case LSA_TYPE_INTER_A_ROUTER:
6714fabe8f9Snorby 		return ("Inter Area (Router)");
6724fabe8f9Snorby 	case LSA_TYPE_INTRA_A_PREFIX:
6734fabe8f9Snorby 		return ("Intra Area (Prefix)");
6748e709cbdSnorby 	case LSA_TYPE_EXTERNAL:
6758e709cbdSnorby 		return ("AS External");
6768e709cbdSnorby 	default:
6778e709cbdSnorby 		return ("Unknown");
6788e709cbdSnorby 	}
6798e709cbdSnorby }
6808e709cbdSnorby 
6818e709cbdSnorby void
show_db_hdr_msg_detail(struct lsa_hdr * lsa)6828e709cbdSnorby show_db_hdr_msg_detail(struct lsa_hdr *lsa)
6838e709cbdSnorby {
6848e709cbdSnorby 	printf("LS age: %d\n", ntohs(lsa->age));
6858e709cbdSnorby 	printf("LS Type: %s\n", print_ls_type(lsa->type));
6868e709cbdSnorby 
687005d568eSclaudio 	switch (ntohs(lsa->type)) {
68889f180e4Sstsp 	case LSA_TYPE_ROUTER:
68989f180e4Sstsp 	case LSA_TYPE_INTER_A_PREFIX:
69089f180e4Sstsp 	case LSA_TYPE_INTER_A_ROUTER:
69189f180e4Sstsp 	case LSA_TYPE_INTRA_A_PREFIX:
69289f180e4Sstsp 	case LSA_TYPE_EXTERNAL:
6934fabe8f9Snorby 		printf("Link State ID: %s\n", log_id(lsa->ls_id));
6944fabe8f9Snorby 		break;
69589f180e4Sstsp 	case LSA_TYPE_LINK:
69689f180e4Sstsp 		printf("Link State ID: %s (Interface ID of Advertising "
69789f180e4Sstsp 		    "Router)\n", log_id(lsa->ls_id));
6988e709cbdSnorby 		break;
6998e709cbdSnorby 	case LSA_TYPE_NETWORK:
70089f180e4Sstsp 		printf("Link State ID: %s (Interface ID of Designated "
70189f180e4Sstsp 		    "Router)\n", log_id(lsa->ls_id));
7028e709cbdSnorby 		break;
7038e709cbdSnorby 	}
7048e709cbdSnorby 
7058e709cbdSnorby 	printf("Advertising Router: %s\n", log_adv_rtr(lsa->adv_rtr));
7068e709cbdSnorby 	printf("LS Seq Number: 0x%08x\n", ntohl(lsa->seq_num));
7078e709cbdSnorby 	printf("Checksum: 0x%04x\n", ntohs(lsa->ls_chksum));
7088e709cbdSnorby 	printf("Length: %d\n", ntohs(lsa->len));
7098e709cbdSnorby }
7108e709cbdSnorby 
7118e709cbdSnorby char *
print_rtr_link_type(u_int8_t type)7128e709cbdSnorby print_rtr_link_type(u_int8_t type)
7138e709cbdSnorby {
7148e709cbdSnorby 	switch (type) {
7158e709cbdSnorby 	case LINK_TYPE_POINTTOPOINT:
7168e709cbdSnorby 		return ("Point-to-Point");
7178e709cbdSnorby 	case LINK_TYPE_TRANSIT_NET:
7188e709cbdSnorby 		return ("Transit Network");
719005d568eSclaudio 	case LINK_TYPE_RESERVED:
720005d568eSclaudio 		return ("Reserved");
7218e709cbdSnorby 	case LINK_TYPE_VIRTUAL:
7228e709cbdSnorby 		return ("Virtual Link");
7238e709cbdSnorby 	default:
7248e709cbdSnorby 		return ("Unknown");
7258e709cbdSnorby 	}
7268e709cbdSnorby }
7278e709cbdSnorby 
7288e709cbdSnorby const char *
print_ospf_flags(u_int8_t opts)7298e709cbdSnorby print_ospf_flags(u_int8_t opts)
7308e709cbdSnorby {
7318e709cbdSnorby 	static char	optbuf[32];
7328e709cbdSnorby 
733aff6ccb8Sclaudio 	snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s",
7348e709cbdSnorby 	    opts & OSPF_RTR_V ? "V" : "-",
7358e709cbdSnorby 	    opts & OSPF_RTR_E ? "E" : "-",
7368e709cbdSnorby 	    opts & OSPF_RTR_B ? "B" : "-");
7378e709cbdSnorby 	return (optbuf);
7388e709cbdSnorby }
7398e709cbdSnorby 
7401aff836dSclaudio const char *
print_asext_flags(u_int32_t opts)7411aff836dSclaudio print_asext_flags(u_int32_t opts)
7421aff836dSclaudio {
7431aff836dSclaudio 	static char	optbuf[32];
7441aff836dSclaudio 
7451aff836dSclaudio 	snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s",
7461aff836dSclaudio 	    opts & LSA_ASEXT_E_FLAG ? "E" : "-",
7471aff836dSclaudio 	    opts & LSA_ASEXT_F_FLAG ? "F" : "-",
7481aff836dSclaudio 	    opts & LSA_ASEXT_T_FLAG ? "T" : "-");
7491aff836dSclaudio 	return (optbuf);
7501aff836dSclaudio }
7511aff836dSclaudio 
7521aff836dSclaudio const char *
print_prefix_opt(u_int8_t opts)7531aff836dSclaudio print_prefix_opt(u_int8_t opts)
7541aff836dSclaudio {
7551aff836dSclaudio 	static char	optbuf[32];
7561aff836dSclaudio 
7571aff836dSclaudio 	if (opts) {
7581aff836dSclaudio 		snprintf(optbuf, sizeof(optbuf),
7591aff836dSclaudio 		    " Options: *|*|*|%s|%s|x|%s|%s",
7601aff836dSclaudio 		    opts & OSPF_PREFIX_DN ? "DN" : "-",
7611aff836dSclaudio 		    opts & OSPF_PREFIX_P ? "P" : "-",
7621aff836dSclaudio 		    opts & OSPF_PREFIX_LA ? "LA" : "-",
7631aff836dSclaudio 		    opts & OSPF_PREFIX_NU ? "NU" : "-");
7641aff836dSclaudio 		return (optbuf);
7651aff836dSclaudio 	}
7661aff836dSclaudio 	return ("");
7671aff836dSclaudio }
7681aff836dSclaudio 
7698e709cbdSnorby int
show_db_msg_detail(struct imsg * imsg)7708e709cbdSnorby show_db_msg_detail(struct imsg *imsg)
7718e709cbdSnorby {
7728e709cbdSnorby 	static struct in_addr	 area_id;
773cb01fa27Sclaudio 	static char		 ifname[IF_NAMESIZE];
774005d568eSclaudio 	static u_int16_t	 lasttype;
7751aff836dSclaudio 	struct in6_addr		 ia6;
7768e709cbdSnorby 	struct in_addr		 addr, data;
7778e709cbdSnorby 	struct area		*area;
778cb01fa27Sclaudio 	struct iface		*iface;
7798e709cbdSnorby 	struct lsa		*lsa;
7808e709cbdSnorby 	struct lsa_rtr_link	*rtr_link;
7810f96e20cSstsp 	struct lsa_net_link	*net_link;
782aeb06b08Sclaudio 	struct lsa_prefix	*prefix;
7838e709cbdSnorby 	struct lsa_asext	*asext;
7841aff836dSclaudio 	u_int32_t		 ext_tag;
7858e709cbdSnorby 	u_int16_t		 i, nlinks, off;
7868e709cbdSnorby 
7878e709cbdSnorby 	/* XXX sanity checks! */
7888e709cbdSnorby 
7898e709cbdSnorby 	switch (imsg->hdr.type) {
7908e709cbdSnorby 	case IMSG_CTL_SHOW_DB_EXT:
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);
7958e709cbdSnorby 
7968e709cbdSnorby 		asext = (struct lsa_asext *)((char *)lsa + sizeof(lsa->hdr));
7978e709cbdSnorby 
7981aff836dSclaudio 		printf("    Flags: %s\n",
7991aff836dSclaudio 		    print_asext_flags(ntohl(lsa->data.asext.metric)));
8001aff836dSclaudio 		printf("    Metric: %d Type: ", ntohl(asext->metric)
8011aff836dSclaudio 		    & LSA_METRIC_MASK);
8028e709cbdSnorby 		if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_E_FLAG)
8038e709cbdSnorby 			printf("2\n");
8048e709cbdSnorby 		else
8058e709cbdSnorby 			printf("1\n");
8068e709cbdSnorby 
8071aff836dSclaudio 		prefix = &asext->prefix;
8081aff836dSclaudio 		bzero(&ia6, sizeof(ia6));
8091aff836dSclaudio 		bcopy(prefix + 1, &ia6, LSA_PREFIXSIZE(prefix->prefixlen));
8101aff836dSclaudio 		printf("    Prefix: %s/%d%s\n", log_in6addr(&ia6),
8111aff836dSclaudio 		    prefix->prefixlen, print_prefix_opt(prefix->options));
8121aff836dSclaudio 
8131aff836dSclaudio 		off = sizeof(*asext) + LSA_PREFIXSIZE(prefix->prefixlen);
8141aff836dSclaudio 		if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_F_FLAG) {
8151aff836dSclaudio 			bcopy((char *)asext + off, &ia6, sizeof(ia6));
8161aff836dSclaudio 			printf("    Forwarding Address: %s\n",
8171aff836dSclaudio 			    log_in6addr(&ia6));
8181aff836dSclaudio 			off += sizeof(ia6);
8191aff836dSclaudio 		}
8201aff836dSclaudio 		if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_T_FLAG) {
8211aff836dSclaudio 			bcopy((char *)asext + off, &ext_tag, sizeof(ext_tag));
8221aff836dSclaudio 			printf("    External Route Tag: %d\n", ntohl(ext_tag));
8231aff836dSclaudio 		}
8241aff836dSclaudio 		printf("\n");
8258e709cbdSnorby 		lasttype = lsa->hdr.type;
8268e709cbdSnorby 		break;
827aeb06b08Sclaudio 	case IMSG_CTL_SHOW_DB_LINK:
828aeb06b08Sclaudio 		lsa = imsg->data;
829aeb06b08Sclaudio 		if (lsa->hdr.type != lasttype)
830aeb06b08Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
831aeb06b08Sclaudio 		show_db_hdr_msg_detail(&lsa->hdr);
8325a54ac3cSclaudio 		printf("Options: %s\n", print_ospf_options(LSA_24_GETLO(
8335a54ac3cSclaudio 		    ntohl(lsa->data.link.opts))));
8345a54ac3cSclaudio 		printf("Link Local Address: %s\n",
8355a54ac3cSclaudio 		    log_in6addr(&lsa->data.link.lladdr));
836aeb06b08Sclaudio 
837aeb06b08Sclaudio 		nlinks = ntohl(lsa->data.link.numprefix);
838aeb06b08Sclaudio 		printf("Number of Prefixes: %d\n", nlinks);
839aeb06b08Sclaudio 		off = sizeof(lsa->hdr) + sizeof(struct lsa_link);
840aeb06b08Sclaudio 
841aeb06b08Sclaudio 		for (i = 0; i < nlinks; i++) {
842aeb06b08Sclaudio 			prefix = (struct lsa_prefix *)((char *)lsa + off);
8435a54ac3cSclaudio 			bzero(&ia6, sizeof(ia6));
8445a54ac3cSclaudio 			bcopy(prefix + 1, &ia6,
8455a54ac3cSclaudio 			    LSA_PREFIXSIZE(prefix->prefixlen));
846aeb06b08Sclaudio 
8471aff836dSclaudio 			printf("    Prefix: %s/%d%s\n", log_in6addr(&ia6),
8481aff836dSclaudio 			    prefix->prefixlen,
8491aff836dSclaudio 			    print_prefix_opt(prefix->options));
850aeb06b08Sclaudio 
85108720e8dSstsp 			off += sizeof(struct lsa_prefix)
85208720e8dSstsp 			    + LSA_PREFIXSIZE(prefix->prefixlen);
853aeb06b08Sclaudio 		}
854aeb06b08Sclaudio 
855aeb06b08Sclaudio 		printf("\n");
856aeb06b08Sclaudio 		lasttype = lsa->hdr.type;
857aeb06b08Sclaudio 		break;
8588e709cbdSnorby 	case IMSG_CTL_SHOW_DB_NET:
8598e709cbdSnorby 		lsa = imsg->data;
8608e709cbdSnorby 		if (lsa->hdr.type != lasttype)
861cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
8628e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
8630bc8b661Sclaudio 		printf("Options: %s\n",
8640bc8b661Sclaudio 		    print_ospf_options(LSA_24_GETLO(ntohl(lsa->data.net.opts))));
8658e709cbdSnorby 
8660f96e20cSstsp 		nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr) -
8670f96e20cSstsp 		    sizeof(struct lsa_net)) / sizeof(struct lsa_net_link);
8680f96e20cSstsp 		net_link = (struct lsa_net_link *)((char *)lsa +
8690f96e20cSstsp 		    sizeof(lsa->hdr) + sizeof(lsa->data.net));
870aeb06b08Sclaudio 		printf("Number of Routers: %d\n", nlinks);
8718e709cbdSnorby 
8728e709cbdSnorby 		for (i = 0; i < nlinks; i++) {
8730f96e20cSstsp 			addr.s_addr = net_link->att_rtr;
8748e709cbdSnorby 			printf("    Attached Router: %s\n", inet_ntoa(addr));
8750f96e20cSstsp 			net_link++;
8768e709cbdSnorby 		}
8778e709cbdSnorby 
8788e709cbdSnorby 		printf("\n");
8798e709cbdSnorby 		lasttype = lsa->hdr.type;
8808e709cbdSnorby 		break;
8818e709cbdSnorby 	case IMSG_CTL_SHOW_DB_RTR:
8828e709cbdSnorby 		lsa = imsg->data;
8838e709cbdSnorby 		if (lsa->hdr.type != lasttype)
884cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
8858e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
8869d28d229Sclaudio 		printf("Flags: %s\n",
887aff6ccb8Sclaudio 		    print_ospf_flags(LSA_24_GETHI(ntohl(lsa->data.rtr.opts))));
8889d28d229Sclaudio 		printf("Options: %s\n",
889aff6ccb8Sclaudio 		    print_ospf_options(LSA_24_GETLO(ntohl(lsa->data.rtr.opts))));
8909d28d229Sclaudio 
8919d28d229Sclaudio 		nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr)
8929d28d229Sclaudio 		    - sizeof(u_int32_t)) / sizeof(struct lsa_rtr_link);
8934091c104Sbluhm 		printf("Number of Links: %d\n\n", nlinks);
8948e709cbdSnorby 
8958e709cbdSnorby 		off = sizeof(lsa->hdr) + sizeof(struct lsa_rtr);
8968e709cbdSnorby 
8978e709cbdSnorby 		for (i = 0; i < nlinks; i++) {
8988e709cbdSnorby 			rtr_link = (struct lsa_rtr_link *)((char *)lsa + off);
8998e709cbdSnorby 
9003ded35dfSstsp 			printf("    Link (Interface ID %s) connected to: %s\n",
9013ded35dfSstsp 			    log_id(rtr_link->iface_id),
9028e709cbdSnorby 			    print_rtr_link_type(rtr_link->type));
9038e709cbdSnorby 
904005d568eSclaudio 			addr.s_addr = rtr_link->nbr_rtr_id;
9053ded35dfSstsp 			data.s_addr = rtr_link->nbr_iface_id;
9068e709cbdSnorby 
9078e709cbdSnorby 			switch (rtr_link->type) {
9088e709cbdSnorby 			case LINK_TYPE_POINTTOPOINT:
9098e709cbdSnorby 			case LINK_TYPE_VIRTUAL:
910005d568eSclaudio 				printf("    Router ID: %s\n", inet_ntoa(addr));
911005d568eSclaudio 				printf("    Interface ID: %s\n",
912005d568eSclaudio 				    inet_ntoa(data));
9138e709cbdSnorby 				break;
9148e709cbdSnorby 			case LINK_TYPE_TRANSIT_NET:
915005d568eSclaudio 				printf("    Designated Router ID: %s\n",
9168e709cbdSnorby 				    inet_ntoa(addr));
917005d568eSclaudio 				printf("    DR Interface ID: %s\n",
9188e709cbdSnorby 				    inet_ntoa(data));
9198e709cbdSnorby 				break;
9208e709cbdSnorby 			default:
921005d568eSclaudio 				printf("    Link ID (Unknown type %d): %s\n",
922005d568eSclaudio 				    rtr_link->type, inet_ntoa(addr));
9238e709cbdSnorby 				printf("    Link Data (Unknown): %s\n",
9248e709cbdSnorby 				    inet_ntoa(data));
9258e709cbdSnorby 				break;
9268e709cbdSnorby 			}
9278e709cbdSnorby 
9288e709cbdSnorby 			printf("    Metric: %d\n\n", ntohs(rtr_link->metric));
9298e709cbdSnorby 
930005d568eSclaudio 			off += sizeof(struct lsa_rtr_link);
9318e709cbdSnorby 		}
9328e709cbdSnorby 
9338e709cbdSnorby 		lasttype = lsa->hdr.type;
9348e709cbdSnorby 		break;
93541bcac6bSstsp 	case IMSG_CTL_SHOW_DB_INTRA:
93641bcac6bSstsp 		lsa = imsg->data;
93741bcac6bSstsp 		if (lsa->hdr.type != lasttype)
93841bcac6bSstsp 			show_database_head(area_id, ifname, lsa->hdr.type);
93941bcac6bSstsp 		show_db_hdr_msg_detail(&lsa->hdr);
94041bcac6bSstsp 		printf("Referenced LS Type: %s\n",
94141bcac6bSstsp 		    print_ls_type(lsa->data.pref_intra.ref_type));
942e0e6f381Sclaudio 		addr.s_addr = lsa->data.pref_intra.ref_ls_id;
94341bcac6bSstsp 		printf("Referenced Link State ID: %s\n", inet_ntoa(addr));
94441bcac6bSstsp 		addr.s_addr = lsa->data.pref_intra.ref_adv_rtr;
94541bcac6bSstsp 		printf("Referenced Advertising Router: %s\n", inet_ntoa(addr));
94641bcac6bSstsp 		nlinks = ntohs(lsa->data.pref_intra.numprefix);
94741bcac6bSstsp 		printf("Number of Prefixes: %d\n", nlinks);
94841bcac6bSstsp 
94941bcac6bSstsp 		off = sizeof(lsa->hdr) + sizeof(struct lsa_intra_prefix);
95041bcac6bSstsp 
95141bcac6bSstsp 		for (i = 0; i < nlinks; i++) {
95241bcac6bSstsp 			prefix = (struct lsa_prefix *)((char *)lsa + off);
95341bcac6bSstsp 			bzero(&ia6, sizeof(ia6));
95441bcac6bSstsp 			bcopy(prefix + 1, &ia6,
95541bcac6bSstsp 			    LSA_PREFIXSIZE(prefix->prefixlen));
95641bcac6bSstsp 
9578e35e101Sremi 			printf("    Prefix: %s/%d%s Metric: %d\n",
9588e35e101Sremi 			    log_in6addr(&ia6), prefix->prefixlen,
9598e35e101Sremi 			    print_prefix_opt(prefix->options),
9608e35e101Sremi 			    ntohs(prefix->metric));
96141bcac6bSstsp 
96208720e8dSstsp 			off += sizeof(struct lsa_prefix)
96308720e8dSstsp 			    + LSA_PREFIXSIZE(prefix->prefixlen);
96441bcac6bSstsp 		}
9659415b30cSstsp 
9669415b30cSstsp 		printf("\n");
9679415b30cSstsp 		lasttype = lsa->hdr.type;
96841bcac6bSstsp 		break;
9698e709cbdSnorby 	case IMSG_CTL_SHOW_DB_SUM:
9708e709cbdSnorby 		lsa = imsg->data;
9718e709cbdSnorby 		if (lsa->hdr.type != lasttype)
972cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
9738e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
974cb01fa27Sclaudio 		printf("Prefix: XXX\n");
975aeb06b08Sclaudio 		printf("Metric: %d\n", ntohl(lsa->data.pref_sum.metric) &
9768e709cbdSnorby 		    LSA_METRIC_MASK);
9778e709cbdSnorby 		lasttype = lsa->hdr.type;
9788e709cbdSnorby 		break;
979cb01fa27Sclaudio 	case IMSG_CTL_SHOW_DB_ASBR:
980cb01fa27Sclaudio 		lsa = imsg->data;
981cb01fa27Sclaudio 		if (lsa->hdr.type != lasttype)
982cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
983cb01fa27Sclaudio 		show_db_hdr_msg_detail(&lsa->hdr);
984cb01fa27Sclaudio 
985cb01fa27Sclaudio 		addr.s_addr = lsa->data.rtr_sum.dest_rtr_id;
986cb01fa27Sclaudio 		printf("Destination Router ID: %s\n", inet_ntoa(addr));
987cb01fa27Sclaudio 		printf("Options: %s\n",
988aeb06b08Sclaudio 		    print_ospf_options(ntohl(lsa->data.rtr_sum.opts)));
989cb01fa27Sclaudio 		printf("Metric: %d\n\n", ntohl(lsa->data.rtr_sum.metric) &
990cb01fa27Sclaudio 		    LSA_METRIC_MASK);
9918e709cbdSnorby 	case IMSG_CTL_AREA:
9928e709cbdSnorby 		area = imsg->data;
9938e709cbdSnorby 		area_id = area->id;
9948e709cbdSnorby 		lasttype = 0;
9958e709cbdSnorby 		break;
996cb01fa27Sclaudio 	case IMSG_CTL_IFACE:
997cb01fa27Sclaudio 		iface = imsg->data;
998cb01fa27Sclaudio 		strlcpy(ifname, iface->name, sizeof(ifname));
999cb01fa27Sclaudio 		lasttype = 0;
1000cb01fa27Sclaudio 		break;
10018e709cbdSnorby 	case IMSG_CTL_END:
10028e709cbdSnorby 		return (1);
10038e709cbdSnorby 	default:
10048e709cbdSnorby 		break;
10058e709cbdSnorby 	}
10068e709cbdSnorby 
10078e709cbdSnorby 	return (0);
10088e709cbdSnorby }
10098e709cbdSnorby 
10108e709cbdSnorby int
show_nbr_msg(struct imsg * imsg)10118e709cbdSnorby show_nbr_msg(struct imsg *imsg)
10128e709cbdSnorby {
10138e709cbdSnorby 	struct ctl_nbr	*nbr;
10148e709cbdSnorby 	char		*state;
10158e709cbdSnorby 
10168e709cbdSnorby 	switch (imsg->hdr.type) {
10178e709cbdSnorby 	case IMSG_CTL_SHOW_NBR:
10188e709cbdSnorby 		nbr = imsg->data;
10198e709cbdSnorby 		if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state),
10208e709cbdSnorby 		    if_state_name(nbr->iface_state)) == -1)
10218e709cbdSnorby 			err(1, NULL);
1022558ada41Snorby 		printf("%-15s %-3d %-12s %-10s", inet_ntoa(nbr->id),
10238e709cbdSnorby 		    nbr->priority, state, fmt_timeframe_core(nbr->dead_timer));
1024558ada41Snorby 		printf("%-11s %s\n", nbr->name,
10258e709cbdSnorby 		    nbr->uptime == 0 ? "-" : fmt_timeframe_core(nbr->uptime));
10268e709cbdSnorby 		free(state);
10278e709cbdSnorby 		break;
10288e709cbdSnorby 	case IMSG_CTL_END:
10298e709cbdSnorby 		printf("\n");
10308e709cbdSnorby 		return (1);
10318e709cbdSnorby 	default:
10328e709cbdSnorby 		break;
10338e709cbdSnorby 	}
10348e709cbdSnorby 
10358e709cbdSnorby 	return (0);
10368e709cbdSnorby }
10378e709cbdSnorby 
10388e709cbdSnorby const char *
print_ospf_options(u_int32_t opts)1039aff6ccb8Sclaudio print_ospf_options(u_int32_t opts)
10408e709cbdSnorby {
10418e709cbdSnorby 	static char	optbuf[32];
10428e709cbdSnorby 
1043aff6ccb8Sclaudio 	snprintf(optbuf, sizeof(optbuf), "*|*|%s|%s|%s|*|%s|%s",
10448e709cbdSnorby 	    opts & OSPF_OPTION_DC ? "DC" : "-",
10458e709cbdSnorby 	    opts & OSPF_OPTION_R ? "R" : "-",
10468e709cbdSnorby 	    opts & OSPF_OPTION_N ? "N" : "-",
10478e709cbdSnorby 	    opts & OSPF_OPTION_E ? "E" : "-",
10488e709cbdSnorby 	    opts & OSPF_OPTION_V6 ? "V6" : "-");
10498e709cbdSnorby 	return (optbuf);
10508e709cbdSnorby }
10518e709cbdSnorby 
10528e709cbdSnorby int
show_nbr_detail_msg(struct imsg * imsg)10538e709cbdSnorby show_nbr_detail_msg(struct imsg *imsg)
10548e709cbdSnorby {
10558e709cbdSnorby 	struct ctl_nbr	*nbr;
10568e709cbdSnorby 
10578e709cbdSnorby 	switch (imsg->hdr.type) {
10588e709cbdSnorby 	case IMSG_CTL_SHOW_NBR:
10598e709cbdSnorby 		nbr = imsg->data;
10608e709cbdSnorby 		printf("\nNeighbor %s, ", inet_ntoa(nbr->id));
10618e709cbdSnorby 		printf("interface address %s\n", log_in6addr(&nbr->addr));
10628e709cbdSnorby 		printf("  Area %s, interface %s\n", inet_ntoa(nbr->area),
10638e709cbdSnorby 		    nbr->name);
10648e709cbdSnorby 		printf("  Neighbor priority is %d, "
10658e709cbdSnorby 		    "State is %s, %d state changes\n",
10668e709cbdSnorby 		    nbr->priority, nbr_state_name(nbr->nbr_state),
10678e709cbdSnorby 		    nbr->state_chng_cnt);
10688e709cbdSnorby 		printf("  DR is %s, ", inet_ntoa(nbr->dr));
10698e709cbdSnorby 		printf("BDR is %s\n", inet_ntoa(nbr->bdr));
10708e709cbdSnorby 		printf("  Options %s\n", print_ospf_options(nbr->options));
10718e709cbdSnorby 		printf("  Dead timer due in %s\n",
10728e709cbdSnorby 		    fmt_timeframe_core(nbr->dead_timer));
10738e709cbdSnorby 		printf("  Uptime %s\n", fmt_timeframe_core(nbr->uptime));
10748e709cbdSnorby 		printf("  Database Summary List %d\n", nbr->db_sum_lst_cnt);
10758e709cbdSnorby 		printf("  Link State Request List %d\n", nbr->ls_req_lst_cnt);
10768e709cbdSnorby 		printf("  Link State Retransmission List %d\n",
10778e709cbdSnorby 		    nbr->ls_retrans_lst_cnt);
10788e709cbdSnorby 		break;
10798e709cbdSnorby 	case IMSG_CTL_END:
10808e709cbdSnorby 		printf("\n");
10818e709cbdSnorby 		return (1);
10828e709cbdSnorby 	default:
10838e709cbdSnorby 		break;
10848e709cbdSnorby 	}
10858e709cbdSnorby 
10868e709cbdSnorby 	return (0);
10878e709cbdSnorby }
10888e709cbdSnorby 
10898e709cbdSnorby int
show_rib_msg(struct imsg * imsg)10908e709cbdSnorby show_rib_msg(struct imsg *imsg)
10918e709cbdSnorby {
10928e709cbdSnorby 	struct ctl_rt	*rt;
10938e709cbdSnorby 	char		*dstnet;
10948e709cbdSnorby 
10958e709cbdSnorby 	switch (imsg->hdr.type) {
10968e709cbdSnorby 	case IMSG_CTL_SHOW_RIB:
10978e709cbdSnorby 		rt = imsg->data;
10988e709cbdSnorby 		switch (rt->d_type) {
10998e709cbdSnorby 		case DT_NET:
11000104e403Sclaudio 			if (asprintf(&dstnet, "%s/%d", log_in6addr(&rt->prefix),
11018e709cbdSnorby 			    rt->prefixlen) == -1)
11028e709cbdSnorby 				err(1, NULL);
11038e709cbdSnorby 			break;
11048e709cbdSnorby 		case DT_RTR:
11058e709cbdSnorby 			if (asprintf(&dstnet, "%s",
11060104e403Sclaudio 			    log_in6addr(&rt->prefix)) == -1)
11078e709cbdSnorby 				err(1, NULL);
11088e709cbdSnorby 			break;
11098e709cbdSnorby 		default:
11108e709cbdSnorby 			errx(1, "Invalid route type");
11118e709cbdSnorby 		}
11128e709cbdSnorby 
111355dcbf22Sdenis 		printf("%-20s %-16s%s %-12s %-9s %-7d %s\n", dstnet,
11140a08a1b1Sclaudio 		    log_in6addr_scope(&rt->nexthop, rt->ifindex),
111555dcbf22Sdenis 		    rt->connected ? "C" : " ", path_type_name(rt->p_type),
111655dcbf22Sdenis 		    dst_type_name(rt->d_type), rt->cost,
11178e709cbdSnorby 		    rt->uptime == 0 ? "-" : fmt_timeframe_core(rt->uptime));
11188e709cbdSnorby 		free(dstnet);
11198e709cbdSnorby 		break;
11208e709cbdSnorby 	case IMSG_CTL_END:
11218e709cbdSnorby 		printf("\n");
11228e709cbdSnorby 		return (1);
11238e709cbdSnorby 	default:
11248e709cbdSnorby 		break;
11258e709cbdSnorby 	}
11268e709cbdSnorby 
11278e709cbdSnorby 	return (0);
11288e709cbdSnorby }
11298e709cbdSnorby 
11308e709cbdSnorby void
show_rib_head(struct in_addr aid,u_int8_t d_type,u_int8_t p_type)11318e709cbdSnorby show_rib_head(struct in_addr aid, u_int8_t d_type, u_int8_t p_type)
11328e709cbdSnorby {
11338e709cbdSnorby 	char	*header, *format, *format2;
11348e709cbdSnorby 
11358e709cbdSnorby 	switch (p_type) {
11368e709cbdSnorby 	case PT_INTRA_AREA:
11378e709cbdSnorby 	case PT_INTER_AREA:
11388e709cbdSnorby 		switch (d_type) {
11398e709cbdSnorby 		case DT_NET:
11408e709cbdSnorby 			format = "Network Routing Table";
11418e709cbdSnorby 			format2 = "";
11428e709cbdSnorby 			break;
11438e709cbdSnorby 		case DT_RTR:
11448e709cbdSnorby 			format = "Router Routing Table";
11458e709cbdSnorby 			format2 = "Type";
11468e709cbdSnorby 			break;
11478e709cbdSnorby 		default:
11488e709cbdSnorby 			errx(1, "unknown route type");
11498e709cbdSnorby 		}
11508e709cbdSnorby 		break;
11518e709cbdSnorby 	case PT_TYPE1_EXT:
11528e709cbdSnorby 	case PT_TYPE2_EXT:
11538e709cbdSnorby 		format = NULL;
11548e709cbdSnorby 		format2 = "Cost 2";
11558e709cbdSnorby 		if ((header = strdup("External Routing Table")) == NULL)
11568e709cbdSnorby 			err(1, NULL);
11578e709cbdSnorby 		break;
11588e709cbdSnorby 	default:
11598e709cbdSnorby 		errx(1, "unknown route type");
11608e709cbdSnorby 	}
11618e709cbdSnorby 
11628e709cbdSnorby 	if (p_type != PT_TYPE1_EXT && p_type != PT_TYPE2_EXT)
11638e709cbdSnorby 		if (asprintf(&header, "%s (Area %s)", format,
11648e709cbdSnorby 		    inet_ntoa(aid)) == -1)
11658e709cbdSnorby 			err(1, NULL);
11668e709cbdSnorby 
11678e709cbdSnorby 	printf("\n%-18s %s\n", "", header);
11688e709cbdSnorby 	free(header);
11698e709cbdSnorby 
11708e709cbdSnorby 	printf("\n%-18s %-15s %-15s %-12s %-7s %-7s\n", "Destination",
11718e709cbdSnorby 	    "Nexthop", "Adv Router", "Path type", "Cost", format2);
11728e709cbdSnorby }
11738e709cbdSnorby 
11748e709cbdSnorby const char *
print_ospf_rtr_flags(u_int8_t opts)11758e709cbdSnorby print_ospf_rtr_flags(u_int8_t opts)
11768e709cbdSnorby {
11778e709cbdSnorby 	static char	optbuf[32];
11788e709cbdSnorby 
11798e709cbdSnorby 	snprintf(optbuf, sizeof(optbuf), "%s%s%s",
11808e709cbdSnorby 	    opts & OSPF_RTR_E ? "AS" : "",
11818e709cbdSnorby 	    opts & OSPF_RTR_E && opts & OSPF_RTR_B ? "+" : "",
11828e709cbdSnorby 	    opts & OSPF_RTR_B ? "ABR" : "");
11838e709cbdSnorby 	return (optbuf);
11848e709cbdSnorby }
11858e709cbdSnorby 
11868e709cbdSnorby int
show_rib_detail_msg(struct imsg * imsg)11878e709cbdSnorby show_rib_detail_msg(struct imsg *imsg)
11888e709cbdSnorby {
11898e709cbdSnorby 	struct ctl_rt		*rt;
11908e709cbdSnorby 	char			*dstnet;
11918e709cbdSnorby 	static u_int8_t		 lasttype;
11928e709cbdSnorby 
11938e709cbdSnorby 	switch (imsg->hdr.type) {
11948e709cbdSnorby 	case IMSG_CTL_SHOW_RIB:
11958e709cbdSnorby 		rt = imsg->data;
11968e709cbdSnorby 
11978e709cbdSnorby 		switch (rt->p_type) {
11988e709cbdSnorby 		case PT_INTRA_AREA:
11998e709cbdSnorby 		case PT_INTER_AREA:
12008e709cbdSnorby 			switch (rt->d_type) {
12018e709cbdSnorby 			case DT_NET:
12028e709cbdSnorby 				if (lasttype != RIB_NET)
12038e709cbdSnorby 					show_rib_head(rt->area, rt->d_type,
12048e709cbdSnorby 					     rt->p_type);
12058e709cbdSnorby 				if (asprintf(&dstnet, "%s/%d",
12060104e403Sclaudio 				    log_in6addr(&rt->prefix),
12070104e403Sclaudio 				    rt->prefixlen) == -1)
12088e709cbdSnorby 					err(1, NULL);
12098e709cbdSnorby 				lasttype = RIB_NET;
12108e709cbdSnorby 				break;
12118e709cbdSnorby 			case DT_RTR:
12128e709cbdSnorby 				if (lasttype != RIB_RTR)
12138e709cbdSnorby 					show_rib_head(rt->area, rt->d_type,
12148e709cbdSnorby 					     rt->p_type);
12158e709cbdSnorby 				if (asprintf(&dstnet, "%s",
12160104e403Sclaudio 				    log_in6addr(&rt->prefix)) == -1)
12178e709cbdSnorby 					err(1, NULL);
12188e709cbdSnorby 				lasttype = RIB_RTR;
12198e709cbdSnorby 				break;
12208e709cbdSnorby 			default:
12218e709cbdSnorby 				errx(1, "unknown route type");
12228e709cbdSnorby 			}
12230104e403Sclaudio 			printf("%-18s %-15s ", dstnet,
12245d8c2b7fSclaudio 			    log_in6addr_scope(&rt->nexthop, rt->ifindex));
12258e709cbdSnorby 			printf("%-15s %-12s %-7d", inet_ntoa(rt->adv_rtr),
12268e709cbdSnorby 			    path_type_name(rt->p_type), rt->cost);
12278e709cbdSnorby 			free(dstnet);
12288e709cbdSnorby 
12298e709cbdSnorby 			if (rt->d_type == DT_RTR)
12308e709cbdSnorby 				printf(" %-7s",
12318e709cbdSnorby 				    print_ospf_rtr_flags(rt->flags));
12328e709cbdSnorby 
12338e709cbdSnorby 			printf("\n");
12348e709cbdSnorby 			break;
12358e709cbdSnorby 		case PT_TYPE1_EXT:
12368e709cbdSnorby 		case PT_TYPE2_EXT:
12378e709cbdSnorby 			if (lasttype != RIB_EXT)
12388e709cbdSnorby 				show_rib_head(rt->area, rt->d_type, rt->p_type);
12398e709cbdSnorby 
12408e709cbdSnorby 			if (asprintf(&dstnet, "%s/%d",
12410104e403Sclaudio 			    log_in6addr(&rt->prefix), rt->prefixlen) == -1)
12428e709cbdSnorby 				err(1, NULL);
12438e709cbdSnorby 
12440104e403Sclaudio 			printf("%-18s %-15s ", dstnet,
12455d8c2b7fSclaudio 			    log_in6addr_scope(&rt->nexthop, rt->ifindex));
12468e709cbdSnorby 			printf("%-15s %-12s %-7d %-7d\n",
12478e709cbdSnorby 			    inet_ntoa(rt->adv_rtr), path_type_name(rt->p_type),
12488e709cbdSnorby 			    rt->cost, rt->cost2);
12498957b20dSstsp 			free(dstnet);
12508e709cbdSnorby 
12518e709cbdSnorby 			lasttype = RIB_EXT;
12528e709cbdSnorby 			break;
12538e709cbdSnorby 		default:
12548e709cbdSnorby 			errx(1, "unknown route type");
12558e709cbdSnorby 		}
12568e709cbdSnorby 		break;
12578e709cbdSnorby 	case IMSG_CTL_AREA:
12588e709cbdSnorby 		break;
12598e709cbdSnorby 	case IMSG_CTL_END:
12608e709cbdSnorby 		printf("\n");
12618e709cbdSnorby 		return (1);
12628e709cbdSnorby 	default:
12638e709cbdSnorby 		break;
12648e709cbdSnorby 	}
12658e709cbdSnorby 
12668e709cbdSnorby 	return (0);
12678e709cbdSnorby }
12688e709cbdSnorby 
12698e709cbdSnorby void
show_fib_head(void)12708e709cbdSnorby show_fib_head(void)
12718e709cbdSnorby {
12728e709cbdSnorby 	printf("flags: * = valid, O = OSPF, C = Connected, S = Static\n");
1273afd0ab5dSfriehm 	printf("%-6s %-4s %-20s %-17s\n",
1274afd0ab5dSfriehm 	    "Flags", "Prio", "Destination", "Nexthop");
12758e709cbdSnorby }
12768e709cbdSnorby 
12778e709cbdSnorby int
show_fib_msg(struct imsg * imsg)12788e709cbdSnorby show_fib_msg(struct imsg *imsg)
12798e709cbdSnorby {
12808e709cbdSnorby 	struct kroute		*k;
12818e709cbdSnorby 	char			*p;
12828e709cbdSnorby 
12838e709cbdSnorby 	switch (imsg->hdr.type) {
12848e709cbdSnorby 	case IMSG_CTL_KROUTE:
12858e709cbdSnorby 		if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute))
12868e709cbdSnorby 			errx(1, "wrong imsg len");
12878e709cbdSnorby 		k = imsg->data;
12888e709cbdSnorby 
12898e709cbdSnorby 		if (k->flags & F_DOWN)
12908e709cbdSnorby 			printf(" ");
12918e709cbdSnorby 		else
12928e709cbdSnorby 			printf("*");
12938e709cbdSnorby 
12948e709cbdSnorby 		if (!(k->flags & F_KERNEL))
12958e709cbdSnorby 			printf("O");
12968e709cbdSnorby 		else if (k->flags & F_CONNECTED)
12978e709cbdSnorby 			printf("C");
12988e709cbdSnorby 		else if (k->flags & F_STATIC)
12998e709cbdSnorby 			printf("S");
13008e709cbdSnorby 		else
13018e709cbdSnorby 			printf(" ");
13028e709cbdSnorby 
13038e709cbdSnorby 		printf("     ");
1304afd0ab5dSfriehm 		printf("%4d ", k->priority);
13050104e403Sclaudio 		if (asprintf(&p, "%s/%u", log_in6addr(&k->prefix),
13060104e403Sclaudio 		    k->prefixlen) == -1)
13078e709cbdSnorby 			err(1, NULL);
13088e709cbdSnorby 		printf("%-20s ", p);
13098e709cbdSnorby 		free(p);
13108e709cbdSnorby 
13110104e403Sclaudio 		if (!IN6_IS_ADDR_UNSPECIFIED(&k->nexthop))
13125d8c2b7fSclaudio 			printf("%s", log_in6addr_scope(&k->nexthop, k->scope));
13138e709cbdSnorby 		else if (k->flags & F_CONNECTED)
13148e709cbdSnorby 			printf("link#%u", k->ifindex);
13158e709cbdSnorby 		printf("\n");
13168e709cbdSnorby 
13178e709cbdSnorby 		break;
13188e709cbdSnorby 	case IMSG_CTL_END:
13198e709cbdSnorby 		printf("\n");
13208e709cbdSnorby 		return (1);
13218e709cbdSnorby 	default:
13228e709cbdSnorby 		break;
13238e709cbdSnorby 	}
13248e709cbdSnorby 
13258e709cbdSnorby 	return (0);
13268e709cbdSnorby }
13278e709cbdSnorby 
13280f617141Sclaudio const struct if_status_description
13290f617141Sclaudio 		if_status_descriptions[] = LINK_STATE_DESCRIPTIONS;
13308e709cbdSnorby const struct ifmedia_description
13318e709cbdSnorby 		ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS;
13328e709cbdSnorby 
13338e709cbdSnorby const char *
get_media_descr(uint64_t media_type)1334e5605ae3Sderaadt get_media_descr(uint64_t media_type)
13358e709cbdSnorby {
13368e709cbdSnorby 	const struct ifmedia_description	*p;
13378e709cbdSnorby 
13388e709cbdSnorby 	for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++)
13398e709cbdSnorby 		if (media_type == p->ifmt_word)
13408e709cbdSnorby 			return (p->ifmt_string);
13418e709cbdSnorby 
13428e709cbdSnorby 	return ("unknown");
13438e709cbdSnorby }
13448e709cbdSnorby 
13458e709cbdSnorby const char *
get_linkstate(uint8_t if_type,int link_state)134618ffdd94Sstsp get_linkstate(uint8_t if_type, int link_state)
13478e709cbdSnorby {
13480f617141Sclaudio 	const struct if_status_description *p;
13490f617141Sclaudio 	static char buf[8];
13508e709cbdSnorby 
13510f617141Sclaudio 	for (p = if_status_descriptions; p->ifs_string != NULL; p++) {
135218ffdd94Sstsp 		if (LINK_STATE_DESC_MATCH(p, if_type, link_state))
13530f617141Sclaudio 			return (p->ifs_string);
13548e709cbdSnorby 	}
13550f617141Sclaudio 	snprintf(buf, sizeof(buf), "[#%d]", link_state);
13560f617141Sclaudio 	return (buf);
13578e709cbdSnorby }
13588e709cbdSnorby 
13598e709cbdSnorby void
print_baudrate(u_int64_t baudrate)13608e709cbdSnorby print_baudrate(u_int64_t baudrate)
13618e709cbdSnorby {
13628e709cbdSnorby 	if (baudrate > IF_Gbps(1))
13638e709cbdSnorby 		printf("%llu GBit/s", baudrate / IF_Gbps(1));
13648e709cbdSnorby 	else if (baudrate > IF_Mbps(1))
13658e709cbdSnorby 		printf("%llu MBit/s", baudrate / IF_Mbps(1));
13668e709cbdSnorby 	else if (baudrate > IF_Kbps(1))
13678e709cbdSnorby 		printf("%llu KBit/s", baudrate / IF_Kbps(1));
13688e709cbdSnorby 	else
13698e709cbdSnorby 		printf("%llu Bit/s", baudrate);
13708e709cbdSnorby }
1371