xref: /openbsd/usr.sbin/ospf6ctl/ospf6ctl.c (revision a18c3fe3)
1*a18c3fe3Sderaadt /*	$OpenBSD: ospf6ctl.c,v 1.42 2015/12/03 17:16:39 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>
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
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
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;
938e709cbdSnorby 	int			 ctl_sock;
94c3319070Sclaudio 	int			 done = 0, verbose = 0;
958e709cbdSnorby 	int			 n;
96c2ca8945Ssthen 	int			 ch;
97c2ca8945Ssthen 	char			*sockname;
98c2ca8945Ssthen 
99c2ca8945Ssthen 	sockname = OSPF6D_SOCKET;
100c2ca8945Ssthen 	while ((ch = getopt(argc, argv, "s:")) != -1) {
101c2ca8945Ssthen 		switch (ch) {
102c2ca8945Ssthen 		case 's':
103c2ca8945Ssthen 			sockname = optarg;
104c2ca8945Ssthen 			break;
105c2ca8945Ssthen 		default:
106c2ca8945Ssthen 			usage();
107c2ca8945Ssthen 			/* NOTREACHED */
108c2ca8945Ssthen 		}
109c2ca8945Ssthen 	}
110c2ca8945Ssthen 	argc -= optind;
111c2ca8945Ssthen 	argv += optind;
1128e709cbdSnorby 
1138e709cbdSnorby 	/* parse options */
114c2ca8945Ssthen 	if ((res = parse(argc, argv)) == NULL)
1158e709cbdSnorby 		exit(1);
1168e709cbdSnorby 
1178e709cbdSnorby 	/* connect to ospf6d control socket */
1188e709cbdSnorby 	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
1198e709cbdSnorby 		err(1, "socket");
1208e709cbdSnorby 
1218e709cbdSnorby 	bzero(&sun, sizeof(sun));
1228e709cbdSnorby 	sun.sun_family = AF_UNIX;
123c2ca8945Ssthen 	strlcpy(sun.sun_path, sockname, sizeof(sun.sun_path));
1248e709cbdSnorby 	if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1)
125c2ca8945Ssthen 		err(1, "connect: %s", sockname);
1268e709cbdSnorby 
127*a18c3fe3Sderaadt 	if (pledge("stdio", NULL) == -1)
128becb4c8cSbenno 		err(1, "pledge");
129becb4c8cSbenno 
1308e709cbdSnorby 	if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
1318e709cbdSnorby 		err(1, NULL);
132f78850efSeric 	imsg_init(ibuf, ctl_sock);
1338e709cbdSnorby 	done = 0;
1348e709cbdSnorby 
1358e709cbdSnorby 	/* process user request */
1368e709cbdSnorby 	switch (res->action) {
1378e709cbdSnorby 	case NONE:
1388e709cbdSnorby 		usage();
1398e709cbdSnorby 		/* not reached */
1408e709cbdSnorby 	case SHOW:
1418e709cbdSnorby 	case SHOW_SUM:
142f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_SUM, 0, 0, -1, NULL, 0);
1438e709cbdSnorby 		break;
1448e709cbdSnorby 	case SHOW_IFACE:
1451fed8bffSnorby 		printf("%-11s %-29s %-6s %-10s %-10s %-8s\n",
1468e709cbdSnorby 		    "Interface", "Address", "State", "HelloTimer", "Linkstate",
1471fed8bffSnorby 		    "Uptime");
148c5ba8b41Sderaadt 		/*FALLTHROUGH*/
1498e709cbdSnorby 	case SHOW_IFACE_DTAIL:
1508e709cbdSnorby 		if (*res->ifname) {
1518e709cbdSnorby 			ifidx = if_nametoindex(res->ifname);
1528e709cbdSnorby 			if (ifidx == 0)
1538e709cbdSnorby 				errx(1, "no such interface %s", res->ifname);
1548e709cbdSnorby 		}
155f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1,
1568e709cbdSnorby 		    &ifidx, sizeof(ifidx));
1578e709cbdSnorby 		break;
1588e709cbdSnorby 	case SHOW_NBR:
159558ada41Snorby 		printf("%-15s %-3s %-12s %-9s %-11s %s\n", "ID", "Pri",
160558ada41Snorby 		    "State", "DeadTime", "Iface","Uptime");
161c5ba8b41Sderaadt 		/*FALLTHROUGH*/
1628e709cbdSnorby 	case SHOW_NBR_DTAIL:
163f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0);
1648e709cbdSnorby 		break;
1658e709cbdSnorby 	case SHOW_DB:
166f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1, NULL, 0);
1678e709cbdSnorby 		break;
1688e709cbdSnorby 	case SHOW_DBBYAREA:
169f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1,
1708e709cbdSnorby 		    &res->addr, sizeof(res->addr));
1718e709cbdSnorby 		break;
1728e709cbdSnorby 	case SHOW_DBEXT:
173f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_EXT, 0, 0, -1, NULL, 0);
1748e709cbdSnorby 		break;
175aeb06b08Sclaudio 	case SHOW_DBLINK:
176f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_LINK, 0, 0, -1, NULL, 0);
177aeb06b08Sclaudio 		break;
1788e709cbdSnorby 	case SHOW_DBNET:
179f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_NET, 0, 0, -1, NULL, 0);
1808e709cbdSnorby 		break;
1818e709cbdSnorby 	case SHOW_DBRTR:
182f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_RTR, 0, 0, -1, NULL, 0);
1838e709cbdSnorby 		break;
18441bcac6bSstsp 	case SHOW_DBINTRA:
185f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_INTRA, 0, 0, -1, NULL, 0);
18641bcac6bSstsp 		break;
1878e709cbdSnorby 	case SHOW_DBSELF:
188f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SELF, 0, 0, -1, NULL, 0);
1898e709cbdSnorby 		break;
1908e709cbdSnorby 	case SHOW_DBSUM:
191f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SUM, 0, 0, -1, NULL, 0);
1928e709cbdSnorby 		break;
1938e709cbdSnorby 	case SHOW_DBASBR:
194f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_ASBR, 0, 0, -1, NULL, 0);
1958e709cbdSnorby 		break;
1968e709cbdSnorby 	case SHOW_RIB:
1978e709cbdSnorby 		printf("%-20s %-17s %-12s %-9s %-7s %-8s\n", "Destination",
1988e709cbdSnorby 		    "Nexthop", "Path Type", "Type", "Cost", "Uptime");
199c5ba8b41Sderaadt 		/*FALLTHROUGH*/
2008e709cbdSnorby 	case SHOW_RIB_DTAIL:
201f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, -1, NULL, 0);
2028e709cbdSnorby 		break;
2038e709cbdSnorby 	case SHOW_FIB:
2040104e403Sclaudio 		if (IN6_IS_ADDR_UNSPECIFIED(&res->addr))
205f78850efSeric 			imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0, -1,
2068e709cbdSnorby 			    &res->flags, sizeof(res->flags));
2078e709cbdSnorby 		else
208f78850efSeric 			imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1,
2098e709cbdSnorby 			    &res->addr, sizeof(res->addr));
2108e709cbdSnorby 		show_fib_head();
2118e709cbdSnorby 		break;
2128e709cbdSnorby 	case FIB:
2138e709cbdSnorby 		errx(1, "fib couple|decouple");
2148e709cbdSnorby 		break;
2158e709cbdSnorby 	case FIB_COUPLE:
216f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, -1, NULL, 0);
2178e709cbdSnorby 		printf("couple request sent.\n");
2188e709cbdSnorby 		done = 1;
2198e709cbdSnorby 		break;
2208e709cbdSnorby 	case FIB_DECOUPLE:
221f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, -1, NULL, 0);
2228e709cbdSnorby 		printf("decouple request sent.\n");
2238e709cbdSnorby 		done = 1;
2248e709cbdSnorby 		break;
225c3319070Sclaudio 	case LOG_VERBOSE:
226c3319070Sclaudio 		verbose = 1;
227c3319070Sclaudio 		/* FALLTHROUGH */
228c3319070Sclaudio 	case LOG_BRIEF:
229c3319070Sclaudio 		imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1,
230c3319070Sclaudio 		    &verbose, sizeof(verbose));
231c3319070Sclaudio 		printf("logging request sent.\n");
232c3319070Sclaudio 		done = 1;
233c3319070Sclaudio 		break;
2348e709cbdSnorby 	case RELOAD:
235f78850efSeric 		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0);
2368e709cbdSnorby 		printf("reload request sent.\n");
2378e709cbdSnorby 		done = 1;
2388e709cbdSnorby 		break;
2398e709cbdSnorby 	}
2408e709cbdSnorby 
2418e709cbdSnorby 	while (ibuf->w.queued)
242c0dbf5cfSsthen 		if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
2438e709cbdSnorby 			err(1, "write error");
2448e709cbdSnorby 
2458e709cbdSnorby 	while (!done) {
2468e709cbdSnorby 		if ((n = imsg_read(ibuf)) == -1)
2478e709cbdSnorby 			errx(1, "imsg_read error");
2488e709cbdSnorby 		if (n == 0)
2498e709cbdSnorby 			errx(1, "pipe closed");
2508e709cbdSnorby 
2518e709cbdSnorby 		while (!done) {
2528e709cbdSnorby 			if ((n = imsg_get(ibuf, &imsg)) == -1)
2538e709cbdSnorby 				errx(1, "imsg_get error");
2548e709cbdSnorby 			if (n == 0)
2558e709cbdSnorby 				break;
2568e709cbdSnorby 			switch (res->action) {
2578e709cbdSnorby 			case SHOW:
2588e709cbdSnorby 			case SHOW_SUM:
2598e709cbdSnorby 				done = show_summary_msg(&imsg);
2608e709cbdSnorby 				break;
2618e709cbdSnorby 			case SHOW_IFACE:
2628e709cbdSnorby 				done = show_interface_msg(&imsg);
2638e709cbdSnorby 				break;
2648e709cbdSnorby 			case SHOW_IFACE_DTAIL:
2658e709cbdSnorby 				done = show_interface_detail_msg(&imsg);
2668e709cbdSnorby 				break;
2678e709cbdSnorby 			case SHOW_NBR:
2688e709cbdSnorby 				done = show_nbr_msg(&imsg);
2698e709cbdSnorby 				break;
2708e709cbdSnorby 			case SHOW_NBR_DTAIL:
2718e709cbdSnorby 				done = show_nbr_detail_msg(&imsg);
2728e709cbdSnorby 				break;
2738e709cbdSnorby 			case SHOW_DB:
2748e709cbdSnorby 			case SHOW_DBBYAREA:
2758e709cbdSnorby 			case SHOW_DBSELF:
2768e709cbdSnorby 				done = show_database_msg(&imsg);
2778e709cbdSnorby 				break;
2788e709cbdSnorby 			case SHOW_DBEXT:
279aeb06b08Sclaudio 			case SHOW_DBLINK:
2808e709cbdSnorby 			case SHOW_DBNET:
2818e709cbdSnorby 			case SHOW_DBRTR:
28241bcac6bSstsp 			case SHOW_DBINTRA:
2838e709cbdSnorby 			case SHOW_DBSUM:
2848e709cbdSnorby 			case SHOW_DBASBR:
2858e709cbdSnorby 				done = show_db_msg_detail(&imsg);
2868e709cbdSnorby 				break;
2878e709cbdSnorby 			case SHOW_RIB:
2888e709cbdSnorby 				done = show_rib_msg(&imsg);
2898e709cbdSnorby 				break;
2908e709cbdSnorby 			case SHOW_RIB_DTAIL:
2918e709cbdSnorby 				done = show_rib_detail_msg(&imsg);
2928e709cbdSnorby 				break;
2938e709cbdSnorby 			case SHOW_FIB:
2948e709cbdSnorby 				done = show_fib_msg(&imsg);
2958e709cbdSnorby 				break;
2968e709cbdSnorby 			case NONE:
2978e709cbdSnorby 			case FIB:
2988e709cbdSnorby 			case FIB_COUPLE:
2998e709cbdSnorby 			case FIB_DECOUPLE:
300c3319070Sclaudio 			case LOG_VERBOSE:
301c3319070Sclaudio 			case LOG_BRIEF:
3028e709cbdSnorby 			case RELOAD:
3038e709cbdSnorby 				break;
3048e709cbdSnorby 			}
3058e709cbdSnorby 			imsg_free(&imsg);
3068e709cbdSnorby 		}
3078e709cbdSnorby 	}
3088e709cbdSnorby 	close(ctl_sock);
3098e709cbdSnorby 	free(ibuf);
3108e709cbdSnorby 
3118e709cbdSnorby 	return (0);
3128e709cbdSnorby }
3138e709cbdSnorby 
3148e709cbdSnorby int
3158e709cbdSnorby show_summary_msg(struct imsg *imsg)
3168e709cbdSnorby {
3178e709cbdSnorby 	struct ctl_sum		*sum;
3188e709cbdSnorby 	struct ctl_sum_area	*sumarea;
3198e709cbdSnorby 
3208e709cbdSnorby 	switch (imsg->hdr.type) {
3218e709cbdSnorby 	case IMSG_CTL_SHOW_SUM:
3228e709cbdSnorby 		sum = imsg->data;
3238e709cbdSnorby 		printf("Router ID: %s\n", inet_ntoa(sum->rtr_id));
3248e709cbdSnorby 		printf("Uptime: %s\n", fmt_timeframe_core(sum->uptime));
3258e709cbdSnorby 
3268e709cbdSnorby 		printf("SPF delay is %d sec(s), hold time between two SPFs "
3278e709cbdSnorby 		    "is %d sec(s)\n", sum->spf_delay, sum->spf_hold_time);
3288e709cbdSnorby 		printf("Number of external LSA(s) %d\n", sum->num_ext_lsa);
3298e709cbdSnorby 		printf("Number of areas attached to this router: %d\n",
3308e709cbdSnorby 		    sum->num_area);
3318e709cbdSnorby 		break;
3328e709cbdSnorby 	case IMSG_CTL_SHOW_SUM_AREA:
3338e709cbdSnorby 		sumarea = imsg->data;
3348e709cbdSnorby 		printf("\nArea ID: %s\n", inet_ntoa(sumarea->area));
3358e709cbdSnorby 		printf("  Number of interfaces in this area: %d\n",
3368e709cbdSnorby 		    sumarea->num_iface);
3378e709cbdSnorby 		printf("  Number of fully adjacent neighbors in this "
3388e709cbdSnorby 		    "area: %d\n", sumarea->num_adj_nbr);
3398e709cbdSnorby 		printf("  SPF algorithm executed %d time(s)\n",
3408e709cbdSnorby 		    sumarea->num_spf_calc);
3418e709cbdSnorby 		printf("  Number LSA(s) %d\n", sumarea->num_lsa);
3428e709cbdSnorby 		break;
3438e709cbdSnorby 	case IMSG_CTL_END:
3448e709cbdSnorby 		printf("\n");
3458e709cbdSnorby 		return (1);
3468e709cbdSnorby 	default:
3478e709cbdSnorby 		break;
3488e709cbdSnorby 	}
3498e709cbdSnorby 
3508e709cbdSnorby 	return (0);
3518e709cbdSnorby }
3528e709cbdSnorby 
35318ffdd94Sstsp uint64_t
35418ffdd94Sstsp get_ifms_type(uint8_t if_type)
3558e709cbdSnorby {
35618ffdd94Sstsp 	switch (if_type) {
3578e709cbdSnorby 	case IFT_ETHER:
3588e709cbdSnorby 		return (IFM_ETHER);
3598e709cbdSnorby 	case IFT_FDDI:
3608e709cbdSnorby 		return (IFM_FDDI);
3618e709cbdSnorby 	case IFT_CARP:
3628e709cbdSnorby 		return (IFM_CARP);
3638e709cbdSnorby 	case IFT_PPP:
3648e709cbdSnorby 		return (IFM_TDM);
3658e709cbdSnorby 	default:
3668e709cbdSnorby 		return (0);
3678e709cbdSnorby 	}
3688e709cbdSnorby }
3698e709cbdSnorby 
3708e709cbdSnorby int
3718e709cbdSnorby show_interface_msg(struct imsg *imsg)
3728e709cbdSnorby {
3738e709cbdSnorby 	struct ctl_iface	*iface;
3748e709cbdSnorby 	char			*netid;
3758e709cbdSnorby 
3768e709cbdSnorby 	switch (imsg->hdr.type) {
3778e709cbdSnorby 	case IMSG_CTL_SHOW_INTERFACE:
3788e709cbdSnorby 		iface = imsg->data;
3798e709cbdSnorby 
3808e709cbdSnorby 		if (asprintf(&netid, "%s", log_in6addr(&iface->addr)) == -1)
3818e709cbdSnorby 			err(1, NULL);
3821fed8bffSnorby 		printf("%-11s %-29s %-6s %-10s %-10s %s\n",
3838e709cbdSnorby 		    iface->name, netid, if_state_name(iface->state),
3848e709cbdSnorby 		    fmt_timeframe_core(iface->hello_timer),
38518ffdd94Sstsp 		    get_linkstate(iface->if_type, iface->linkstate),
3860f617141Sclaudio 		    fmt_timeframe_core(iface->uptime));
3878e709cbdSnorby 		free(netid);
3888e709cbdSnorby 		break;
3898e709cbdSnorby 	case IMSG_CTL_END:
3908e709cbdSnorby 		printf("\n");
3918e709cbdSnorby 		return (1);
3928e709cbdSnorby 	default:
3938e709cbdSnorby 		break;
3948e709cbdSnorby 	}
3958e709cbdSnorby 
3968e709cbdSnorby 	return (0);
3978e709cbdSnorby }
3988e709cbdSnorby 
3998e709cbdSnorby int
4008e709cbdSnorby show_interface_detail_msg(struct imsg *imsg)
4018e709cbdSnorby {
4028e709cbdSnorby 	struct ctl_iface	*iface;
4038e709cbdSnorby 
4048e709cbdSnorby 	switch (imsg->hdr.type) {
4058e709cbdSnorby 	case IMSG_CTL_SHOW_INTERFACE:
4068e709cbdSnorby 		iface = imsg->data;
4078e709cbdSnorby 		printf("\n");
4088e709cbdSnorby 		printf("Interface %s, line protocol is %s\n",
4098e709cbdSnorby 		    iface->name, print_link(iface->flags));
410ab5e4d03Sclaudio 		printf("  Internet address %s Area %s\n",
411ab5e4d03Sclaudio 		    log_in6addr(&iface->addr), inet_ntoa(iface->area));
412ab5e4d03Sclaudio 		printf("  Link type %s, state %s",
41318ffdd94Sstsp 		    get_media_descr(get_ifms_type(iface->if_type)),
41418ffdd94Sstsp 		    get_linkstate(iface->if_type, iface->linkstate));
415ab5e4d03Sclaudio 		if (iface->linkstate != LINK_STATE_DOWN &&
416ab5e4d03Sclaudio 		    iface->baudrate > 0) {
417ab5e4d03Sclaudio 		    printf(", ");
418ab5e4d03Sclaudio 		    print_baudrate(iface->baudrate);
419ab5e4d03Sclaudio 		}
420ab5e4d03Sclaudio 		printf("\n");
4218e709cbdSnorby 		printf("  Router ID %s, network type %s, cost: %d\n",
4228e709cbdSnorby 		    inet_ntoa(iface->rtr_id),
4238e709cbdSnorby 		    if_type_name(iface->type), iface->metric);
4248e709cbdSnorby 		printf("  Transmit delay is %d sec(s), state %s, priority %d\n",
4258e709cbdSnorby 		    iface->transmit_delay, if_state_name(iface->state),
4268e709cbdSnorby 		    iface->priority);
4277aab4200Snorby 		printf("  Designated Router (ID) %s\n",
4288e709cbdSnorby 		    inet_ntoa(iface->dr_id));
4297aab4200Snorby 		printf("    Interface address %s\n",
4307aab4200Snorby 		    log_in6addr(&iface->dr_addr));
4317aab4200Snorby 		printf("  Backup Designated Router (ID) %s\n",
4328e709cbdSnorby 		    inet_ntoa(iface->bdr_id));
4337aab4200Snorby 		printf("    Interface address %s\n",
4347aab4200Snorby 		    log_in6addr(&iface->bdr_addr));
4358e709cbdSnorby 		printf("  Timer intervals configured, "
4368e709cbdSnorby 		    "hello %d, dead %d, wait %d, retransmit %d\n",
4378e709cbdSnorby 		     iface->hello_interval, iface->dead_interval,
4388e709cbdSnorby 		     iface->dead_interval, iface->rxmt_interval);
4398e709cbdSnorby 		if (iface->passive)
4408e709cbdSnorby 			printf("    Passive interface (No Hellos)\n");
4418e709cbdSnorby 		else if (iface->hello_timer < 0)
4428e709cbdSnorby 			printf("    Hello timer not running\n");
4438e709cbdSnorby 		else
4448e709cbdSnorby 			printf("    Hello timer due in %s\n",
4458e709cbdSnorby 			    fmt_timeframe_core(iface->hello_timer));
4468e709cbdSnorby 		printf("    Uptime %s\n", fmt_timeframe_core(iface->uptime));
4478e709cbdSnorby 		printf("  Neighbor count is %d, adjacent neighbor count is "
4488e709cbdSnorby 		    "%d\n", iface->nbr_cnt, iface->adj_cnt);
4498e709cbdSnorby 		break;
4508e709cbdSnorby 	case IMSG_CTL_END:
4518e709cbdSnorby 		printf("\n");
4528e709cbdSnorby 		return (1);
4538e709cbdSnorby 	default:
4548e709cbdSnorby 		break;
4558e709cbdSnorby 	}
4568e709cbdSnorby 
4578e709cbdSnorby 	return (0);
4588e709cbdSnorby }
4598e709cbdSnorby 
4608e709cbdSnorby const char *
4618e709cbdSnorby print_link(int state)
4628e709cbdSnorby {
4638e709cbdSnorby 	if (state & IFF_UP)
4648e709cbdSnorby 		return ("UP");
4658e709cbdSnorby 	else
4668e709cbdSnorby 		return ("DOWN");
4678e709cbdSnorby }
4688e709cbdSnorby 
4698e709cbdSnorby #define TF_BUFS	8
4708e709cbdSnorby #define TF_LEN	9
4718e709cbdSnorby 
4728e709cbdSnorby const char *
4738e709cbdSnorby fmt_timeframe(time_t t)
4748e709cbdSnorby {
4758e709cbdSnorby 	if (t == 0)
4768e709cbdSnorby 		return ("Never");
4778e709cbdSnorby 	else
4788e709cbdSnorby 		return (fmt_timeframe_core(time(NULL) - t));
4798e709cbdSnorby }
4808e709cbdSnorby 
4818e709cbdSnorby const char *
4828e709cbdSnorby fmt_timeframe_core(time_t t)
4838e709cbdSnorby {
4848e709cbdSnorby 	char		*buf;
4858e709cbdSnorby 	static char	 tfbuf[TF_BUFS][TF_LEN];	/* ring buffer */
4868e709cbdSnorby 	static int	 idx = 0;
487db93f2f1Sderaadt 	unsigned int	 sec, min, hrs, day, week;
4888e709cbdSnorby 
4898e709cbdSnorby 	if (t == 0)
4908e709cbdSnorby 		return ("00:00:00");
4918e709cbdSnorby 
4928e709cbdSnorby 	buf = tfbuf[idx++];
4938e709cbdSnorby 	if (idx == TF_BUFS)
4948e709cbdSnorby 		idx = 0;
4958e709cbdSnorby 
4968e709cbdSnorby 	week = t;
4978e709cbdSnorby 
4988e709cbdSnorby 	sec = week % 60;
4998e709cbdSnorby 	week /= 60;
5008e709cbdSnorby 	min = week % 60;
5018e709cbdSnorby 	week /= 60;
5028e709cbdSnorby 	hrs = week % 24;
5038e709cbdSnorby 	week /= 24;
5048e709cbdSnorby 	day = week % 7;
5058e709cbdSnorby 	week /= 7;
5068e709cbdSnorby 
5078e709cbdSnorby 	if (week > 0)
5088e709cbdSnorby 		snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs);
5098e709cbdSnorby 	else if (day > 0)
5108e709cbdSnorby 		snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
5118e709cbdSnorby 	else
5128e709cbdSnorby 		snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
5138e709cbdSnorby 
5148e709cbdSnorby 	return (buf);
5158e709cbdSnorby }
5168e709cbdSnorby 
5178e709cbdSnorby const char *
5188e709cbdSnorby log_id(u_int32_t id)
5198e709cbdSnorby {
5208e709cbdSnorby 	static char	buf[48];
5218e709cbdSnorby 	struct in_addr	addr;
5228e709cbdSnorby 
5238e709cbdSnorby 	addr.s_addr = id;
5248e709cbdSnorby 
5258e709cbdSnorby 	if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL)
5268e709cbdSnorby 		return ("?");
5278e709cbdSnorby 	else
5288e709cbdSnorby 		return (buf);
5298e709cbdSnorby }
5308e709cbdSnorby 
5318e709cbdSnorby const char *
5328e709cbdSnorby log_adv_rtr(u_int32_t adv_rtr)
5338e709cbdSnorby {
5348e709cbdSnorby 	static char	buf[48];
5358e709cbdSnorby 	struct in_addr	addr;
5368e709cbdSnorby 
5378e709cbdSnorby 	addr.s_addr = adv_rtr;
5388e709cbdSnorby 
5398e709cbdSnorby 	if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL)
5408e709cbdSnorby 		return ("?");
5418e709cbdSnorby 	else
5428e709cbdSnorby 		return (buf);
5438e709cbdSnorby }
5448e709cbdSnorby 
5458e709cbdSnorby void
546cb01fa27Sclaudio show_database_head(struct in_addr aid, char *ifname, u_int16_t type)
5478e709cbdSnorby {
5488e709cbdSnorby 	char	*header, *format;
549cb01fa27Sclaudio 	int	cleanup = 0;
5508e709cbdSnorby 
551005d568eSclaudio 	switch (ntohs(type)) {
5524fabe8f9Snorby 	case LSA_TYPE_LINK:
5538ea4c735Sclaudio 		format = "Link (Type-8) Link States";
5544fabe8f9Snorby 		break;
5558e709cbdSnorby 	case LSA_TYPE_ROUTER:
5568e709cbdSnorby 		format = "Router Link States";
5578e709cbdSnorby 		break;
5588e709cbdSnorby 	case LSA_TYPE_NETWORK:
5598e709cbdSnorby 		format = "Net Link States";
5608e709cbdSnorby 		break;
5614fabe8f9Snorby 	case LSA_TYPE_INTER_A_PREFIX:
5624fabe8f9Snorby 		format = "Inter Area Prefix Link States";
5638e709cbdSnorby 		break;
5644fabe8f9Snorby 	case LSA_TYPE_INTER_A_ROUTER:
5654fabe8f9Snorby 		format = "Inter Area Router Link States";
5664fabe8f9Snorby 		break;
5674fabe8f9Snorby 	case LSA_TYPE_INTRA_A_PREFIX:
5688ec36425Sstsp 		format = "Intra Area Prefix Link States";
5698e709cbdSnorby 		break;
5708e709cbdSnorby 	case LSA_TYPE_EXTERNAL:
571cb01fa27Sclaudio 		printf("\n%-15s %s\n\n", "", "Type-5 AS External Link States");
572cb01fa27Sclaudio 		return;
5738e709cbdSnorby 	default:
574cb01fa27Sclaudio 		if (asprintf(&format, "LSA type %x", ntohs(type)) == -1)
575cb01fa27Sclaudio 			err(1, NULL);
576cb01fa27Sclaudio 		cleanup = 1;
577cb01fa27Sclaudio 		break;
5788e709cbdSnorby 	}
579cb01fa27Sclaudio 	if (LSA_IS_SCOPE_AREA(ntohs(type))) {
5808e709cbdSnorby 		if (asprintf(&header, "%s (Area %s)", format,
5818e709cbdSnorby 		    inet_ntoa(aid)) == -1)
5828e709cbdSnorby 			err(1, NULL);
583cb01fa27Sclaudio 	} else if (LSA_IS_SCOPE_LLOCAL(ntohs(type))) {
584cb01fa27Sclaudio 		if (asprintf(&header, "%s (Area %s Interface %s)", format,
585cb01fa27Sclaudio 		    inet_ntoa(aid), ifname) == -1)
586cb01fa27Sclaudio 			err(1, NULL);
587cb01fa27Sclaudio 	}
5888e709cbdSnorby 
5898e709cbdSnorby 	printf("\n%-15s %s\n\n", "", header);
5908e709cbdSnorby 	free(header);
591cb01fa27Sclaudio 	if (cleanup)
592cb01fa27Sclaudio 		free(format);
5938e709cbdSnorby }
5948e709cbdSnorby 
5958e709cbdSnorby int
5968e709cbdSnorby show_database_msg(struct imsg *imsg)
5978e709cbdSnorby {
5988e709cbdSnorby 	static struct in_addr	 area_id;
599cb01fa27Sclaudio 	static char		 ifname[IF_NAMESIZE];
6007db04f17Sclaudio 	static u_int16_t	 lasttype;
6018e709cbdSnorby 	struct area		*area;
602cb01fa27Sclaudio 	struct iface		*iface;
6038e709cbdSnorby 	struct lsa_hdr		*lsa;
6048e709cbdSnorby 
6058e709cbdSnorby 	switch (imsg->hdr.type) {
6068e709cbdSnorby 	case IMSG_CTL_SHOW_DATABASE:
6078e709cbdSnorby 	case IMSG_CTL_SHOW_DB_SELF:
6088e709cbdSnorby 		lsa = imsg->data;
6098e709cbdSnorby 		if (lsa->type != lasttype) {
610cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->type);
6118e709cbdSnorby 			printf("%-15s %-15s %-4s %-10s %-8s\n", "Link ID",
6128e709cbdSnorby 			    "Adv Router", "Age", "Seq#", "Checksum");
6138e709cbdSnorby 		}
6148e709cbdSnorby 		printf("%-15s %-15s %-4d 0x%08x 0x%04x\n",
6158e709cbdSnorby 		    log_id(lsa->ls_id), log_adv_rtr(lsa->adv_rtr),
6168e709cbdSnorby 		    ntohs(lsa->age), ntohl(lsa->seq_num),
6178e709cbdSnorby 		    ntohs(lsa->ls_chksum));
6188e709cbdSnorby 		lasttype = lsa->type;
6198e709cbdSnorby 		break;
6208e709cbdSnorby 	case IMSG_CTL_AREA:
6218e709cbdSnorby 		area = imsg->data;
6228e709cbdSnorby 		area_id = area->id;
6238e709cbdSnorby 		lasttype = 0;
6248e709cbdSnorby 		break;
625cb01fa27Sclaudio 	case IMSG_CTL_IFACE:
626cb01fa27Sclaudio 		iface = imsg->data;
627cb01fa27Sclaudio 		strlcpy(ifname, iface->name, sizeof(ifname));
628cb01fa27Sclaudio 		lasttype = 0;
629cb01fa27Sclaudio 		break;
6308e709cbdSnorby 	case IMSG_CTL_END:
6318e709cbdSnorby 		printf("\n");
6328e709cbdSnorby 		return (1);
6338e709cbdSnorby 	default:
6348e709cbdSnorby 		break;
6358e709cbdSnorby 	}
6368e709cbdSnorby 
6378e709cbdSnorby 	return (0);
6388e709cbdSnorby }
6398e709cbdSnorby 
6408e709cbdSnorby char *
6414fabe8f9Snorby print_ls_type(u_int16_t type)
6428e709cbdSnorby {
643005d568eSclaudio 	switch (ntohs(type)) {
6444fabe8f9Snorby 	case LSA_TYPE_LINK:
6454fabe8f9Snorby 		return ("Link");
6468e709cbdSnorby 	case LSA_TYPE_ROUTER:
6478e709cbdSnorby 		return ("Router");
6488e709cbdSnorby 	case LSA_TYPE_NETWORK:
6498e709cbdSnorby 		return ("Network");
6504fabe8f9Snorby 	case LSA_TYPE_INTER_A_PREFIX:
6514fabe8f9Snorby 		return ("Inter Area (Prefix)");
6524fabe8f9Snorby 	case LSA_TYPE_INTER_A_ROUTER:
6534fabe8f9Snorby 		return ("Inter Area (Router)");
6544fabe8f9Snorby 	case LSA_TYPE_INTRA_A_PREFIX:
6554fabe8f9Snorby 		return ("Intra Area (Prefix)");
6568e709cbdSnorby 	case LSA_TYPE_EXTERNAL:
6578e709cbdSnorby 		return ("AS External");
6588e709cbdSnorby 	default:
6598e709cbdSnorby 		return ("Unknown");
6608e709cbdSnorby 	}
6618e709cbdSnorby }
6628e709cbdSnorby 
6638e709cbdSnorby void
6648e709cbdSnorby show_db_hdr_msg_detail(struct lsa_hdr *lsa)
6658e709cbdSnorby {
6668e709cbdSnorby 	printf("LS age: %d\n", ntohs(lsa->age));
6678e709cbdSnorby 	printf("LS Type: %s\n", print_ls_type(lsa->type));
6688e709cbdSnorby 
669005d568eSclaudio 	switch (ntohs(lsa->type)) {
67089f180e4Sstsp 	case LSA_TYPE_ROUTER:
67189f180e4Sstsp 	case LSA_TYPE_INTER_A_PREFIX:
67289f180e4Sstsp 	case LSA_TYPE_INTER_A_ROUTER:
67389f180e4Sstsp 	case LSA_TYPE_INTRA_A_PREFIX:
67489f180e4Sstsp 	case LSA_TYPE_EXTERNAL:
6754fabe8f9Snorby 		printf("Link State ID: %s\n", log_id(lsa->ls_id));
6764fabe8f9Snorby 		break;
67789f180e4Sstsp 	case LSA_TYPE_LINK:
67889f180e4Sstsp 		printf("Link State ID: %s (Interface ID of Advertising "
67989f180e4Sstsp 		    "Router)\n", log_id(lsa->ls_id));
6808e709cbdSnorby 		break;
6818e709cbdSnorby 	case LSA_TYPE_NETWORK:
68289f180e4Sstsp 		printf("Link State ID: %s (Interface ID of Designated "
68389f180e4Sstsp 		    "Router)\n", log_id(lsa->ls_id));
6848e709cbdSnorby 		break;
6858e709cbdSnorby 	}
6868e709cbdSnorby 
6878e709cbdSnorby 	printf("Advertising Router: %s\n", log_adv_rtr(lsa->adv_rtr));
6888e709cbdSnorby 	printf("LS Seq Number: 0x%08x\n", ntohl(lsa->seq_num));
6898e709cbdSnorby 	printf("Checksum: 0x%04x\n", ntohs(lsa->ls_chksum));
6908e709cbdSnorby 	printf("Length: %d\n", ntohs(lsa->len));
6918e709cbdSnorby }
6928e709cbdSnorby 
6938e709cbdSnorby char *
6948e709cbdSnorby print_rtr_link_type(u_int8_t type)
6958e709cbdSnorby {
6968e709cbdSnorby 	switch (type) {
6978e709cbdSnorby 	case LINK_TYPE_POINTTOPOINT:
6988e709cbdSnorby 		return ("Point-to-Point");
6998e709cbdSnorby 	case LINK_TYPE_TRANSIT_NET:
7008e709cbdSnorby 		return ("Transit Network");
701005d568eSclaudio 	case LINK_TYPE_RESERVED:
702005d568eSclaudio 		return ("Reserved");
7038e709cbdSnorby 	case LINK_TYPE_VIRTUAL:
7048e709cbdSnorby 		return ("Virtual Link");
7058e709cbdSnorby 	default:
7068e709cbdSnorby 		return ("Unknown");
7078e709cbdSnorby 	}
7088e709cbdSnorby }
7098e709cbdSnorby 
7108e709cbdSnorby const char *
7118e709cbdSnorby print_ospf_flags(u_int8_t opts)
7128e709cbdSnorby {
7138e709cbdSnorby 	static char	optbuf[32];
7148e709cbdSnorby 
715aff6ccb8Sclaudio 	snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s",
7168e709cbdSnorby 	    opts & OSPF_RTR_V ? "V" : "-",
7178e709cbdSnorby 	    opts & OSPF_RTR_E ? "E" : "-",
7188e709cbdSnorby 	    opts & OSPF_RTR_B ? "B" : "-");
7198e709cbdSnorby 	return (optbuf);
7208e709cbdSnorby }
7218e709cbdSnorby 
7221aff836dSclaudio const char *
7231aff836dSclaudio print_asext_flags(u_int32_t opts)
7241aff836dSclaudio {
7251aff836dSclaudio 	static char	optbuf[32];
7261aff836dSclaudio 
7271aff836dSclaudio 	snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s",
7281aff836dSclaudio 	    opts & LSA_ASEXT_E_FLAG ? "E" : "-",
7291aff836dSclaudio 	    opts & LSA_ASEXT_F_FLAG ? "F" : "-",
7301aff836dSclaudio 	    opts & LSA_ASEXT_T_FLAG ? "T" : "-");
7311aff836dSclaudio 	return (optbuf);
7321aff836dSclaudio }
7331aff836dSclaudio 
7341aff836dSclaudio const char *
7351aff836dSclaudio print_prefix_opt(u_int8_t opts)
7361aff836dSclaudio {
7371aff836dSclaudio 	static char	optbuf[32];
7381aff836dSclaudio 
7391aff836dSclaudio 	if (opts) {
7401aff836dSclaudio 		snprintf(optbuf, sizeof(optbuf),
7411aff836dSclaudio 		    " Options: *|*|*|%s|%s|x|%s|%s",
7421aff836dSclaudio 		    opts & OSPF_PREFIX_DN ? "DN" : "-",
7431aff836dSclaudio 		    opts & OSPF_PREFIX_P ? "P" : "-",
7441aff836dSclaudio 		    opts & OSPF_PREFIX_LA ? "LA" : "-",
7451aff836dSclaudio 		    opts & OSPF_PREFIX_NU ? "NU" : "-");
7461aff836dSclaudio 		return (optbuf);
7471aff836dSclaudio 	}
7481aff836dSclaudio 	return ("");
7491aff836dSclaudio }
7501aff836dSclaudio 
7518e709cbdSnorby int
7528e709cbdSnorby show_db_msg_detail(struct imsg *imsg)
7538e709cbdSnorby {
7548e709cbdSnorby 	static struct in_addr	 area_id;
755cb01fa27Sclaudio 	static char		 ifname[IF_NAMESIZE];
756005d568eSclaudio 	static u_int16_t	 lasttype;
7571aff836dSclaudio 	struct in6_addr		 ia6;
7588e709cbdSnorby 	struct in_addr		 addr, data;
7598e709cbdSnorby 	struct area		*area;
760cb01fa27Sclaudio 	struct iface		*iface;
7618e709cbdSnorby 	struct lsa		*lsa;
7628e709cbdSnorby 	struct lsa_rtr_link	*rtr_link;
7630f96e20cSstsp 	struct lsa_net_link	*net_link;
764aeb06b08Sclaudio 	struct lsa_prefix	*prefix;
7658e709cbdSnorby 	struct lsa_asext	*asext;
7661aff836dSclaudio 	u_int32_t		 ext_tag;
7678e709cbdSnorby 	u_int16_t		 i, nlinks, off;
7688e709cbdSnorby 
7698e709cbdSnorby 	/* XXX sanity checks! */
7708e709cbdSnorby 
7718e709cbdSnorby 	switch (imsg->hdr.type) {
7728e709cbdSnorby 	case IMSG_CTL_SHOW_DB_EXT:
7738e709cbdSnorby 		lsa = imsg->data;
7748e709cbdSnorby 		if (lsa->hdr.type != lasttype)
775cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
7768e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
7778e709cbdSnorby 
7788e709cbdSnorby 		asext = (struct lsa_asext *)((char *)lsa + sizeof(lsa->hdr));
7798e709cbdSnorby 
7801aff836dSclaudio 		printf("    Flags: %s\n",
7811aff836dSclaudio 		    print_asext_flags(ntohl(lsa->data.asext.metric)));
7821aff836dSclaudio 		printf("    Metric: %d Type: ", ntohl(asext->metric)
7831aff836dSclaudio 		    & LSA_METRIC_MASK);
7848e709cbdSnorby 		if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_E_FLAG)
7858e709cbdSnorby 			printf("2\n");
7868e709cbdSnorby 		else
7878e709cbdSnorby 			printf("1\n");
7888e709cbdSnorby 
7891aff836dSclaudio 		prefix = &asext->prefix;
7901aff836dSclaudio 		bzero(&ia6, sizeof(ia6));
7911aff836dSclaudio 		bcopy(prefix + 1, &ia6, LSA_PREFIXSIZE(prefix->prefixlen));
7921aff836dSclaudio 		printf("    Prefix: %s/%d%s\n", log_in6addr(&ia6),
7931aff836dSclaudio 		    prefix->prefixlen, print_prefix_opt(prefix->options));
7941aff836dSclaudio 
7951aff836dSclaudio 		off = sizeof(*asext) + LSA_PREFIXSIZE(prefix->prefixlen);
7961aff836dSclaudio 		if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_F_FLAG) {
7971aff836dSclaudio 			bcopy((char *)asext + off, &ia6, sizeof(ia6));
7981aff836dSclaudio 			printf("    Forwarding Address: %s\n",
7991aff836dSclaudio 			    log_in6addr(&ia6));
8001aff836dSclaudio 			off += sizeof(ia6);
8011aff836dSclaudio 		}
8021aff836dSclaudio 		if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_T_FLAG) {
8031aff836dSclaudio 			bcopy((char *)asext + off, &ext_tag, sizeof(ext_tag));
8041aff836dSclaudio 			printf("    External Route Tag: %d\n", ntohl(ext_tag));
8051aff836dSclaudio 		}
8061aff836dSclaudio 		printf("\n");
8078e709cbdSnorby 		lasttype = lsa->hdr.type;
8088e709cbdSnorby 		break;
809aeb06b08Sclaudio 	case IMSG_CTL_SHOW_DB_LINK:
810aeb06b08Sclaudio 		lsa = imsg->data;
811aeb06b08Sclaudio 		if (lsa->hdr.type != lasttype)
812aeb06b08Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
813aeb06b08Sclaudio 		show_db_hdr_msg_detail(&lsa->hdr);
8145a54ac3cSclaudio 		printf("Options: %s\n", print_ospf_options(LSA_24_GETLO(
8155a54ac3cSclaudio 		    ntohl(lsa->data.link.opts))));
8165a54ac3cSclaudio 		printf("Link Local Address: %s\n",
8175a54ac3cSclaudio 		    log_in6addr(&lsa->data.link.lladdr));
818aeb06b08Sclaudio 
819aeb06b08Sclaudio 		nlinks = ntohl(lsa->data.link.numprefix);
820aeb06b08Sclaudio 		printf("Number of Prefixes: %d\n", nlinks);
821aeb06b08Sclaudio 		off = sizeof(lsa->hdr) + sizeof(struct lsa_link);
822aeb06b08Sclaudio 
823aeb06b08Sclaudio 		for (i = 0; i < nlinks; i++) {
824aeb06b08Sclaudio 			prefix = (struct lsa_prefix *)((char *)lsa + off);
8255a54ac3cSclaudio 			bzero(&ia6, sizeof(ia6));
8265a54ac3cSclaudio 			bcopy(prefix + 1, &ia6,
8275a54ac3cSclaudio 			    LSA_PREFIXSIZE(prefix->prefixlen));
828aeb06b08Sclaudio 
8291aff836dSclaudio 			printf("    Prefix: %s/%d%s\n", log_in6addr(&ia6),
8301aff836dSclaudio 			    prefix->prefixlen,
8311aff836dSclaudio 			    print_prefix_opt(prefix->options));
832aeb06b08Sclaudio 
83308720e8dSstsp 			off += sizeof(struct lsa_prefix)
83408720e8dSstsp 			    + LSA_PREFIXSIZE(prefix->prefixlen);
835aeb06b08Sclaudio 		}
836aeb06b08Sclaudio 
837aeb06b08Sclaudio 		printf("\n");
838aeb06b08Sclaudio 		lasttype = lsa->hdr.type;
839aeb06b08Sclaudio 		break;
8408e709cbdSnorby 	case IMSG_CTL_SHOW_DB_NET:
8418e709cbdSnorby 		lsa = imsg->data;
8428e709cbdSnorby 		if (lsa->hdr.type != lasttype)
843cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
8448e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
8450bc8b661Sclaudio 		printf("Options: %s\n",
8460bc8b661Sclaudio 		    print_ospf_options(LSA_24_GETLO(ntohl(lsa->data.net.opts))));
8478e709cbdSnorby 
8480f96e20cSstsp 		nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr) -
8490f96e20cSstsp 		    sizeof(struct lsa_net)) / sizeof(struct lsa_net_link);
8500f96e20cSstsp 		net_link = (struct lsa_net_link *)((char *)lsa +
8510f96e20cSstsp 		    sizeof(lsa->hdr) + sizeof(lsa->data.net));
852aeb06b08Sclaudio 		printf("Number of Routers: %d\n", nlinks);
8538e709cbdSnorby 
8548e709cbdSnorby 		for (i = 0; i < nlinks; i++) {
8550f96e20cSstsp 			addr.s_addr = net_link->att_rtr;
8568e709cbdSnorby 			printf("    Attached Router: %s\n", inet_ntoa(addr));
8570f96e20cSstsp 			net_link++;
8588e709cbdSnorby 		}
8598e709cbdSnorby 
8608e709cbdSnorby 		printf("\n");
8618e709cbdSnorby 		lasttype = lsa->hdr.type;
8628e709cbdSnorby 		break;
8638e709cbdSnorby 	case IMSG_CTL_SHOW_DB_RTR:
8648e709cbdSnorby 		lsa = imsg->data;
8658e709cbdSnorby 		if (lsa->hdr.type != lasttype)
866cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
8678e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
8689d28d229Sclaudio 		printf("Flags: %s\n",
869aff6ccb8Sclaudio 		    print_ospf_flags(LSA_24_GETHI(ntohl(lsa->data.rtr.opts))));
8709d28d229Sclaudio 		printf("Options: %s\n",
871aff6ccb8Sclaudio 		    print_ospf_options(LSA_24_GETLO(ntohl(lsa->data.rtr.opts))));
8729d28d229Sclaudio 
8739d28d229Sclaudio 		nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr)
8749d28d229Sclaudio 		    - sizeof(u_int32_t)) / sizeof(struct lsa_rtr_link);
8754091c104Sbluhm 		printf("Number of Links: %d\n\n", nlinks);
8768e709cbdSnorby 
8778e709cbdSnorby 		off = sizeof(lsa->hdr) + sizeof(struct lsa_rtr);
8788e709cbdSnorby 
8798e709cbdSnorby 		for (i = 0; i < nlinks; i++) {
8808e709cbdSnorby 			rtr_link = (struct lsa_rtr_link *)((char *)lsa + off);
8818e709cbdSnorby 
8823ded35dfSstsp 			printf("    Link (Interface ID %s) connected to: %s\n",
8833ded35dfSstsp 			    log_id(rtr_link->iface_id),
8848e709cbdSnorby 			    print_rtr_link_type(rtr_link->type));
8858e709cbdSnorby 
886005d568eSclaudio 			addr.s_addr = rtr_link->nbr_rtr_id;
8873ded35dfSstsp 			data.s_addr = rtr_link->nbr_iface_id;
8888e709cbdSnorby 
8898e709cbdSnorby 			switch (rtr_link->type) {
8908e709cbdSnorby 			case LINK_TYPE_POINTTOPOINT:
8918e709cbdSnorby 			case LINK_TYPE_VIRTUAL:
892005d568eSclaudio 				printf("    Router ID: %s\n", inet_ntoa(addr));
893005d568eSclaudio 				printf("    Interface ID: %s\n",
894005d568eSclaudio 				    inet_ntoa(data));
8958e709cbdSnorby 				break;
8968e709cbdSnorby 			case LINK_TYPE_TRANSIT_NET:
897005d568eSclaudio 				printf("    Designated Router ID: %s\n",
8988e709cbdSnorby 				    inet_ntoa(addr));
899005d568eSclaudio 				printf("    DR Interface ID: %s\n",
9008e709cbdSnorby 				    inet_ntoa(data));
9018e709cbdSnorby 				break;
9028e709cbdSnorby 			default:
903005d568eSclaudio 				printf("    Link ID (Unknown type %d): %s\n",
904005d568eSclaudio 				    rtr_link->type, inet_ntoa(addr));
9058e709cbdSnorby 				printf("    Link Data (Unknown): %s\n",
9068e709cbdSnorby 				    inet_ntoa(data));
9078e709cbdSnorby 				break;
9088e709cbdSnorby 			}
9098e709cbdSnorby 
9108e709cbdSnorby 			printf("    Metric: %d\n\n", ntohs(rtr_link->metric));
9118e709cbdSnorby 
912005d568eSclaudio 			off += sizeof(struct lsa_rtr_link);
9138e709cbdSnorby 		}
9148e709cbdSnorby 
9158e709cbdSnorby 		lasttype = lsa->hdr.type;
9168e709cbdSnorby 		break;
91741bcac6bSstsp 	case IMSG_CTL_SHOW_DB_INTRA:
91841bcac6bSstsp 		lsa = imsg->data;
91941bcac6bSstsp 		if (lsa->hdr.type != lasttype)
92041bcac6bSstsp 			show_database_head(area_id, ifname, lsa->hdr.type);
92141bcac6bSstsp 		show_db_hdr_msg_detail(&lsa->hdr);
92241bcac6bSstsp 		printf("Referenced LS Type: %s\n",
92341bcac6bSstsp 		    print_ls_type(lsa->data.pref_intra.ref_type));
924e0e6f381Sclaudio 		addr.s_addr = lsa->data.pref_intra.ref_ls_id;
92541bcac6bSstsp 		printf("Referenced Link State ID: %s\n", inet_ntoa(addr));
92641bcac6bSstsp 		addr.s_addr = lsa->data.pref_intra.ref_adv_rtr;
92741bcac6bSstsp 		printf("Referenced Advertising Router: %s\n", inet_ntoa(addr));
92841bcac6bSstsp 		nlinks = ntohs(lsa->data.pref_intra.numprefix);
92941bcac6bSstsp 		printf("Number of Prefixes: %d\n", nlinks);
93041bcac6bSstsp 
93141bcac6bSstsp 		off = sizeof(lsa->hdr) + sizeof(struct lsa_intra_prefix);
93241bcac6bSstsp 
93341bcac6bSstsp 		for (i = 0; i < nlinks; i++) {
93441bcac6bSstsp 			prefix = (struct lsa_prefix *)((char *)lsa + off);
93541bcac6bSstsp 			bzero(&ia6, sizeof(ia6));
93641bcac6bSstsp 			bcopy(prefix + 1, &ia6,
93741bcac6bSstsp 			    LSA_PREFIXSIZE(prefix->prefixlen));
93841bcac6bSstsp 
9391aff836dSclaudio 			printf("    Prefix: %s/%d%s\n", log_in6addr(&ia6),
9401aff836dSclaudio 			    prefix->prefixlen,
9411aff836dSclaudio 			    print_prefix_opt(prefix->options));
94241bcac6bSstsp 
94308720e8dSstsp 			off += sizeof(struct lsa_prefix)
94408720e8dSstsp 			    + LSA_PREFIXSIZE(prefix->prefixlen);
94541bcac6bSstsp 		}
9469415b30cSstsp 
9479415b30cSstsp 		printf("\n");
9489415b30cSstsp 		lasttype = lsa->hdr.type;
94941bcac6bSstsp 		break;
9508e709cbdSnorby 	case IMSG_CTL_SHOW_DB_SUM:
9518e709cbdSnorby 		lsa = imsg->data;
9528e709cbdSnorby 		if (lsa->hdr.type != lasttype)
953cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
9548e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
955cb01fa27Sclaudio 		printf("Prefix: XXX\n");
956aeb06b08Sclaudio 		printf("Metric: %d\n", ntohl(lsa->data.pref_sum.metric) &
9578e709cbdSnorby 		    LSA_METRIC_MASK);
9588e709cbdSnorby 		lasttype = lsa->hdr.type;
9598e709cbdSnorby 		break;
960cb01fa27Sclaudio 	case IMSG_CTL_SHOW_DB_ASBR:
961cb01fa27Sclaudio 		lsa = imsg->data;
962cb01fa27Sclaudio 		if (lsa->hdr.type != lasttype)
963cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
964cb01fa27Sclaudio 		show_db_hdr_msg_detail(&lsa->hdr);
965cb01fa27Sclaudio 
966cb01fa27Sclaudio 		addr.s_addr = lsa->data.rtr_sum.dest_rtr_id;
967cb01fa27Sclaudio 		printf("Destination Router ID: %s\n", inet_ntoa(addr));
968cb01fa27Sclaudio 		printf("Options: %s\n",
969aeb06b08Sclaudio 		    print_ospf_options(ntohl(lsa->data.rtr_sum.opts)));
970cb01fa27Sclaudio 		printf("Metric: %d\n\n", ntohl(lsa->data.rtr_sum.metric) &
971cb01fa27Sclaudio 		    LSA_METRIC_MASK);
9728e709cbdSnorby 	case IMSG_CTL_AREA:
9738e709cbdSnorby 		area = imsg->data;
9748e709cbdSnorby 		area_id = area->id;
9758e709cbdSnorby 		lasttype = 0;
9768e709cbdSnorby 		break;
977cb01fa27Sclaudio 	case IMSG_CTL_IFACE:
978cb01fa27Sclaudio 		iface = imsg->data;
979cb01fa27Sclaudio 		strlcpy(ifname, iface->name, sizeof(ifname));
980cb01fa27Sclaudio 		lasttype = 0;
981cb01fa27Sclaudio 		break;
9828e709cbdSnorby 	case IMSG_CTL_END:
9838e709cbdSnorby 		return (1);
9848e709cbdSnorby 	default:
9858e709cbdSnorby 		break;
9868e709cbdSnorby 	}
9878e709cbdSnorby 
9888e709cbdSnorby 	return (0);
9898e709cbdSnorby }
9908e709cbdSnorby 
9918e709cbdSnorby int
9928e709cbdSnorby show_nbr_msg(struct imsg *imsg)
9938e709cbdSnorby {
9948e709cbdSnorby 	struct ctl_nbr	*nbr;
9958e709cbdSnorby 	char		*state;
9968e709cbdSnorby 
9978e709cbdSnorby 	switch (imsg->hdr.type) {
9988e709cbdSnorby 	case IMSG_CTL_SHOW_NBR:
9998e709cbdSnorby 		nbr = imsg->data;
10008e709cbdSnorby 		if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state),
10018e709cbdSnorby 		    if_state_name(nbr->iface_state)) == -1)
10028e709cbdSnorby 			err(1, NULL);
1003558ada41Snorby 		printf("%-15s %-3d %-12s %-10s", inet_ntoa(nbr->id),
10048e709cbdSnorby 		    nbr->priority, state, fmt_timeframe_core(nbr->dead_timer));
1005558ada41Snorby 		printf("%-11s %s\n", nbr->name,
10068e709cbdSnorby 		    nbr->uptime == 0 ? "-" : fmt_timeframe_core(nbr->uptime));
10078e709cbdSnorby 		free(state);
10088e709cbdSnorby 		break;
10098e709cbdSnorby 	case IMSG_CTL_END:
10108e709cbdSnorby 		printf("\n");
10118e709cbdSnorby 		return (1);
10128e709cbdSnorby 	default:
10138e709cbdSnorby 		break;
10148e709cbdSnorby 	}
10158e709cbdSnorby 
10168e709cbdSnorby 	return (0);
10178e709cbdSnorby }
10188e709cbdSnorby 
10198e709cbdSnorby const char *
1020aff6ccb8Sclaudio print_ospf_options(u_int32_t opts)
10218e709cbdSnorby {
10228e709cbdSnorby 	static char	optbuf[32];
10238e709cbdSnorby 
1024aff6ccb8Sclaudio 	snprintf(optbuf, sizeof(optbuf), "*|*|%s|%s|%s|*|%s|%s",
10258e709cbdSnorby 	    opts & OSPF_OPTION_DC ? "DC" : "-",
10268e709cbdSnorby 	    opts & OSPF_OPTION_R ? "R" : "-",
10278e709cbdSnorby 	    opts & OSPF_OPTION_N ? "N" : "-",
10288e709cbdSnorby 	    opts & OSPF_OPTION_E ? "E" : "-",
10298e709cbdSnorby 	    opts & OSPF_OPTION_V6 ? "V6" : "-");
10308e709cbdSnorby 	return (optbuf);
10318e709cbdSnorby }
10328e709cbdSnorby 
10338e709cbdSnorby int
10348e709cbdSnorby show_nbr_detail_msg(struct imsg *imsg)
10358e709cbdSnorby {
10368e709cbdSnorby 	struct ctl_nbr	*nbr;
10378e709cbdSnorby 
10388e709cbdSnorby 	switch (imsg->hdr.type) {
10398e709cbdSnorby 	case IMSG_CTL_SHOW_NBR:
10408e709cbdSnorby 		nbr = imsg->data;
10418e709cbdSnorby 		printf("\nNeighbor %s, ", inet_ntoa(nbr->id));
10428e709cbdSnorby 		printf("interface address %s\n", log_in6addr(&nbr->addr));
10438e709cbdSnorby 		printf("  Area %s, interface %s\n", inet_ntoa(nbr->area),
10448e709cbdSnorby 		    nbr->name);
10458e709cbdSnorby 		printf("  Neighbor priority is %d, "
10468e709cbdSnorby 		    "State is %s, %d state changes\n",
10478e709cbdSnorby 		    nbr->priority, nbr_state_name(nbr->nbr_state),
10488e709cbdSnorby 		    nbr->state_chng_cnt);
10498e709cbdSnorby 		printf("  DR is %s, ", inet_ntoa(nbr->dr));
10508e709cbdSnorby 		printf("BDR is %s\n", inet_ntoa(nbr->bdr));
10518e709cbdSnorby 		printf("  Options %s\n", print_ospf_options(nbr->options));
10528e709cbdSnorby 		printf("  Dead timer due in %s\n",
10538e709cbdSnorby 		    fmt_timeframe_core(nbr->dead_timer));
10548e709cbdSnorby 		printf("  Uptime %s\n", fmt_timeframe_core(nbr->uptime));
10558e709cbdSnorby 		printf("  Database Summary List %d\n", nbr->db_sum_lst_cnt);
10568e709cbdSnorby 		printf("  Link State Request List %d\n", nbr->ls_req_lst_cnt);
10578e709cbdSnorby 		printf("  Link State Retransmission List %d\n",
10588e709cbdSnorby 		    nbr->ls_retrans_lst_cnt);
10598e709cbdSnorby 		break;
10608e709cbdSnorby 	case IMSG_CTL_END:
10618e709cbdSnorby 		printf("\n");
10628e709cbdSnorby 		return (1);
10638e709cbdSnorby 	default:
10648e709cbdSnorby 		break;
10658e709cbdSnorby 	}
10668e709cbdSnorby 
10678e709cbdSnorby 	return (0);
10688e709cbdSnorby }
10698e709cbdSnorby 
10708e709cbdSnorby int
10718e709cbdSnorby show_rib_msg(struct imsg *imsg)
10728e709cbdSnorby {
10738e709cbdSnorby 	struct ctl_rt	*rt;
10748e709cbdSnorby 	char		*dstnet;
10758e709cbdSnorby 
10768e709cbdSnorby 	switch (imsg->hdr.type) {
10778e709cbdSnorby 	case IMSG_CTL_SHOW_RIB:
10788e709cbdSnorby 		rt = imsg->data;
10798e709cbdSnorby 		switch (rt->d_type) {
10808e709cbdSnorby 		case DT_NET:
10810104e403Sclaudio 			if (asprintf(&dstnet, "%s/%d", log_in6addr(&rt->prefix),
10828e709cbdSnorby 			    rt->prefixlen) == -1)
10838e709cbdSnorby 				err(1, NULL);
10848e709cbdSnorby 			break;
10858e709cbdSnorby 		case DT_RTR:
10868e709cbdSnorby 			if (asprintf(&dstnet, "%s",
10870104e403Sclaudio 			    log_in6addr(&rt->prefix)) == -1)
10888e709cbdSnorby 				err(1, NULL);
10898e709cbdSnorby 			break;
10908e709cbdSnorby 		default:
10918e709cbdSnorby 			errx(1, "Invalid route type");
10928e709cbdSnorby 		}
10938e709cbdSnorby 
10948e709cbdSnorby 		printf("%-20s %-17s %-12s %-9s %-7d %s\n", dstnet,
10950a08a1b1Sclaudio 		    log_in6addr_scope(&rt->nexthop, rt->ifindex),
10960a08a1b1Sclaudio 		    path_type_name(rt->p_type), dst_type_name(rt->d_type),
10970a08a1b1Sclaudio 		    rt->cost,
10988e709cbdSnorby 		    rt->uptime == 0 ? "-" : fmt_timeframe_core(rt->uptime));
10998e709cbdSnorby 		free(dstnet);
11008e709cbdSnorby 		break;
11018e709cbdSnorby 	case IMSG_CTL_END:
11028e709cbdSnorby 		printf("\n");
11038e709cbdSnorby 		return (1);
11048e709cbdSnorby 	default:
11058e709cbdSnorby 		break;
11068e709cbdSnorby 	}
11078e709cbdSnorby 
11088e709cbdSnorby 	return (0);
11098e709cbdSnorby }
11108e709cbdSnorby 
11118e709cbdSnorby void
11128e709cbdSnorby show_rib_head(struct in_addr aid, u_int8_t d_type, u_int8_t p_type)
11138e709cbdSnorby {
11148e709cbdSnorby 	char	*header, *format, *format2;
11158e709cbdSnorby 
11168e709cbdSnorby 	switch (p_type) {
11178e709cbdSnorby 	case PT_INTRA_AREA:
11188e709cbdSnorby 	case PT_INTER_AREA:
11198e709cbdSnorby 		switch (d_type) {
11208e709cbdSnorby 		case DT_NET:
11218e709cbdSnorby 			format = "Network Routing Table";
11228e709cbdSnorby 			format2 = "";
11238e709cbdSnorby 			break;
11248e709cbdSnorby 		case DT_RTR:
11258e709cbdSnorby 			format = "Router Routing Table";
11268e709cbdSnorby 			format2 = "Type";
11278e709cbdSnorby 			break;
11288e709cbdSnorby 		default:
11298e709cbdSnorby 			errx(1, "unknown route type");
11308e709cbdSnorby 		}
11318e709cbdSnorby 		break;
11328e709cbdSnorby 	case PT_TYPE1_EXT:
11338e709cbdSnorby 	case PT_TYPE2_EXT:
11348e709cbdSnorby 		format = NULL;
11358e709cbdSnorby 		format2 = "Cost 2";
11368e709cbdSnorby 		if ((header = strdup("External Routing Table")) == NULL)
11378e709cbdSnorby 			err(1, NULL);
11388e709cbdSnorby 		break;
11398e709cbdSnorby 	default:
11408e709cbdSnorby 		errx(1, "unknown route type");
11418e709cbdSnorby 	}
11428e709cbdSnorby 
11438e709cbdSnorby 	if (p_type != PT_TYPE1_EXT && p_type != PT_TYPE2_EXT)
11448e709cbdSnorby 		if (asprintf(&header, "%s (Area %s)", format,
11458e709cbdSnorby 		    inet_ntoa(aid)) == -1)
11468e709cbdSnorby 			err(1, NULL);
11478e709cbdSnorby 
11488e709cbdSnorby 	printf("\n%-18s %s\n", "", header);
11498e709cbdSnorby 	free(header);
11508e709cbdSnorby 
11518e709cbdSnorby 	printf("\n%-18s %-15s %-15s %-12s %-7s %-7s\n", "Destination",
11528e709cbdSnorby 	    "Nexthop", "Adv Router", "Path type", "Cost", format2);
11538e709cbdSnorby }
11548e709cbdSnorby 
11558e709cbdSnorby const char *
11568e709cbdSnorby print_ospf_rtr_flags(u_int8_t opts)
11578e709cbdSnorby {
11588e709cbdSnorby 	static char	optbuf[32];
11598e709cbdSnorby 
11608e709cbdSnorby 	snprintf(optbuf, sizeof(optbuf), "%s%s%s",
11618e709cbdSnorby 	    opts & OSPF_RTR_E ? "AS" : "",
11628e709cbdSnorby 	    opts & OSPF_RTR_E && opts & OSPF_RTR_B ? "+" : "",
11638e709cbdSnorby 	    opts & OSPF_RTR_B ? "ABR" : "");
11648e709cbdSnorby 	return (optbuf);
11658e709cbdSnorby }
11668e709cbdSnorby 
11678e709cbdSnorby int
11688e709cbdSnorby show_rib_detail_msg(struct imsg *imsg)
11698e709cbdSnorby {
11708e709cbdSnorby 	static struct in_addr	 area_id;
11718e709cbdSnorby 	struct ctl_rt		*rt;
11728e709cbdSnorby 	struct area		*area;
11738e709cbdSnorby 	char			*dstnet;
11748e709cbdSnorby 	static u_int8_t		 lasttype;
11758e709cbdSnorby 
11768e709cbdSnorby 	switch (imsg->hdr.type) {
11778e709cbdSnorby 	case IMSG_CTL_SHOW_RIB:
11788e709cbdSnorby 		rt = imsg->data;
11798e709cbdSnorby 
11808e709cbdSnorby 		switch (rt->p_type) {
11818e709cbdSnorby 		case PT_INTRA_AREA:
11828e709cbdSnorby 		case PT_INTER_AREA:
11838e709cbdSnorby 			switch (rt->d_type) {
11848e709cbdSnorby 			case DT_NET:
11858e709cbdSnorby 				if (lasttype != RIB_NET)
11868e709cbdSnorby 					show_rib_head(rt->area, rt->d_type,
11878e709cbdSnorby 					     rt->p_type);
11888e709cbdSnorby 				if (asprintf(&dstnet, "%s/%d",
11890104e403Sclaudio 				    log_in6addr(&rt->prefix),
11900104e403Sclaudio 				    rt->prefixlen) == -1)
11918e709cbdSnorby 					err(1, NULL);
11928e709cbdSnorby 				lasttype = RIB_NET;
11938e709cbdSnorby 				break;
11948e709cbdSnorby 			case DT_RTR:
11958e709cbdSnorby 				if (lasttype != RIB_RTR)
11968e709cbdSnorby 					show_rib_head(rt->area, rt->d_type,
11978e709cbdSnorby 					     rt->p_type);
11988e709cbdSnorby 				if (asprintf(&dstnet, "%s",
11990104e403Sclaudio 				    log_in6addr(&rt->prefix)) == -1)
12008e709cbdSnorby 					err(1, NULL);
12018e709cbdSnorby 				lasttype = RIB_RTR;
12028e709cbdSnorby 				break;
12038e709cbdSnorby 			default:
12048e709cbdSnorby 				errx(1, "unknown route type");
12058e709cbdSnorby 			}
12060104e403Sclaudio 			printf("%-18s %-15s ", dstnet,
12075d8c2b7fSclaudio 			    log_in6addr_scope(&rt->nexthop, rt->ifindex));
12088e709cbdSnorby 			printf("%-15s %-12s %-7d", inet_ntoa(rt->adv_rtr),
12098e709cbdSnorby 			    path_type_name(rt->p_type), rt->cost);
12108e709cbdSnorby 			free(dstnet);
12118e709cbdSnorby 
12128e709cbdSnorby 			if (rt->d_type == DT_RTR)
12138e709cbdSnorby 				printf(" %-7s",
12148e709cbdSnorby 				    print_ospf_rtr_flags(rt->flags));
12158e709cbdSnorby 
12168e709cbdSnorby 			printf("\n");
12178e709cbdSnorby 			break;
12188e709cbdSnorby 		case PT_TYPE1_EXT:
12198e709cbdSnorby 		case PT_TYPE2_EXT:
12208e709cbdSnorby 			if (lasttype != RIB_EXT)
12218e709cbdSnorby 				show_rib_head(rt->area, rt->d_type, rt->p_type);
12228e709cbdSnorby 
12238e709cbdSnorby 			if (asprintf(&dstnet, "%s/%d",
12240104e403Sclaudio 			    log_in6addr(&rt->prefix), rt->prefixlen) == -1)
12258e709cbdSnorby 				err(1, NULL);
12268e709cbdSnorby 
12270104e403Sclaudio 			printf("%-18s %-15s ", dstnet,
12285d8c2b7fSclaudio 			    log_in6addr_scope(&rt->nexthop, rt->ifindex));
12298e709cbdSnorby 			printf("%-15s %-12s %-7d %-7d\n",
12308e709cbdSnorby 			    inet_ntoa(rt->adv_rtr), path_type_name(rt->p_type),
12318e709cbdSnorby 			    rt->cost, rt->cost2);
12328957b20dSstsp 			free(dstnet);
12338e709cbdSnorby 
12348e709cbdSnorby 			lasttype = RIB_EXT;
12358e709cbdSnorby 			break;
12368e709cbdSnorby 		default:
12378e709cbdSnorby 			errx(1, "unknown route type");
12388e709cbdSnorby 		}
12398e709cbdSnorby 		break;
12408e709cbdSnorby 	case IMSG_CTL_AREA:
12418e709cbdSnorby 		area = imsg->data;
12428e709cbdSnorby 		area_id = area->id;
12438e709cbdSnorby 		break;
12448e709cbdSnorby 	case IMSG_CTL_END:
12458e709cbdSnorby 		printf("\n");
12468e709cbdSnorby 		return (1);
12478e709cbdSnorby 	default:
12488e709cbdSnorby 		break;
12498e709cbdSnorby 	}
12508e709cbdSnorby 
12518e709cbdSnorby 	return (0);
12528e709cbdSnorby }
12538e709cbdSnorby 
12548e709cbdSnorby void
12558e709cbdSnorby show_fib_head(void)
12568e709cbdSnorby {
12578e709cbdSnorby 	printf("flags: * = valid, O = OSPF, C = Connected, S = Static\n");
12588e709cbdSnorby 	printf("%-6s %-20s %-17s\n", "Flags", "Destination", "Nexthop");
12598e709cbdSnorby }
12608e709cbdSnorby 
12618e709cbdSnorby int
12628e709cbdSnorby show_fib_msg(struct imsg *imsg)
12638e709cbdSnorby {
12648e709cbdSnorby 	struct kroute		*k;
12658e709cbdSnorby 	char			*p;
12668e709cbdSnorby 
12678e709cbdSnorby 	switch (imsg->hdr.type) {
12688e709cbdSnorby 	case IMSG_CTL_KROUTE:
12698e709cbdSnorby 		if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute))
12708e709cbdSnorby 			errx(1, "wrong imsg len");
12718e709cbdSnorby 		k = imsg->data;
12728e709cbdSnorby 
12738e709cbdSnorby 		if (k->flags & F_DOWN)
12748e709cbdSnorby 			printf(" ");
12758e709cbdSnorby 		else
12768e709cbdSnorby 			printf("*");
12778e709cbdSnorby 
12788e709cbdSnorby 		if (!(k->flags & F_KERNEL))
12798e709cbdSnorby 			printf("O");
12808e709cbdSnorby 		else if (k->flags & F_CONNECTED)
12818e709cbdSnorby 			printf("C");
12828e709cbdSnorby 		else if (k->flags & F_STATIC)
12838e709cbdSnorby 			printf("S");
12848e709cbdSnorby 		else
12858e709cbdSnorby 			printf(" ");
12868e709cbdSnorby 
12878e709cbdSnorby 		printf("     ");
12880104e403Sclaudio 		if (asprintf(&p, "%s/%u", log_in6addr(&k->prefix),
12890104e403Sclaudio 		    k->prefixlen) == -1)
12908e709cbdSnorby 			err(1, NULL);
12918e709cbdSnorby 		printf("%-20s ", p);
12928e709cbdSnorby 		free(p);
12938e709cbdSnorby 
12940104e403Sclaudio 		if (!IN6_IS_ADDR_UNSPECIFIED(&k->nexthop))
12955d8c2b7fSclaudio 			printf("%s", log_in6addr_scope(&k->nexthop, k->scope));
12968e709cbdSnorby 		else if (k->flags & F_CONNECTED)
12978e709cbdSnorby 			printf("link#%u", k->ifindex);
12988e709cbdSnorby 		printf("\n");
12998e709cbdSnorby 
13008e709cbdSnorby 		break;
13018e709cbdSnorby 	case IMSG_CTL_END:
13028e709cbdSnorby 		printf("\n");
13038e709cbdSnorby 		return (1);
13048e709cbdSnorby 	default:
13058e709cbdSnorby 		break;
13068e709cbdSnorby 	}
13078e709cbdSnorby 
13088e709cbdSnorby 	return (0);
13098e709cbdSnorby }
13108e709cbdSnorby 
13110f617141Sclaudio const struct if_status_description
13120f617141Sclaudio 		if_status_descriptions[] = LINK_STATE_DESCRIPTIONS;
13138e709cbdSnorby const struct ifmedia_description
13148e709cbdSnorby 		ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS;
13158e709cbdSnorby 
13168e709cbdSnorby const char *
1317e5605ae3Sderaadt get_media_descr(uint64_t media_type)
13188e709cbdSnorby {
13198e709cbdSnorby 	const struct ifmedia_description	*p;
13208e709cbdSnorby 
13218e709cbdSnorby 	for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++)
13228e709cbdSnorby 		if (media_type == p->ifmt_word)
13238e709cbdSnorby 			return (p->ifmt_string);
13248e709cbdSnorby 
13258e709cbdSnorby 	return ("unknown");
13268e709cbdSnorby }
13278e709cbdSnorby 
13288e709cbdSnorby const char *
132918ffdd94Sstsp get_linkstate(uint8_t if_type, int link_state)
13308e709cbdSnorby {
13310f617141Sclaudio 	const struct if_status_description *p;
13320f617141Sclaudio 	static char buf[8];
13338e709cbdSnorby 
13340f617141Sclaudio 	for (p = if_status_descriptions; p->ifs_string != NULL; p++) {
133518ffdd94Sstsp 		if (LINK_STATE_DESC_MATCH(p, if_type, link_state))
13360f617141Sclaudio 			return (p->ifs_string);
13378e709cbdSnorby 	}
13380f617141Sclaudio 	snprintf(buf, sizeof(buf), "[#%d]", link_state);
13390f617141Sclaudio 	return (buf);
13408e709cbdSnorby }
13418e709cbdSnorby 
13428e709cbdSnorby void
13438e709cbdSnorby print_baudrate(u_int64_t baudrate)
13448e709cbdSnorby {
13458e709cbdSnorby 	if (baudrate > IF_Gbps(1))
13468e709cbdSnorby 		printf("%llu GBit/s", baudrate / IF_Gbps(1));
13478e709cbdSnorby 	else if (baudrate > IF_Mbps(1))
13488e709cbdSnorby 		printf("%llu MBit/s", baudrate / IF_Mbps(1));
13498e709cbdSnorby 	else if (baudrate > IF_Kbps(1))
13508e709cbdSnorby 		printf("%llu KBit/s", baudrate / IF_Kbps(1));
13518e709cbdSnorby 	else
13528e709cbdSnorby 		printf("%llu Bit/s", baudrate);
13538e709cbdSnorby }
1354