xref: /openbsd/usr.sbin/ospf6ctl/ospf6ctl.c (revision 73094d71)
1*73094d71Sbenno /*	$OpenBSD: ospf6ctl.c,v 1.46 2017/08/12 22:09:54 benno 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 
127a18c3fe3Sderaadt 	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) {
246262992b2Sclaudio 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
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));
41237f8d125Sjca 		printf("  Link type %s, state %s, mtu %d",
41318ffdd94Sstsp 		    get_media_descr(get_ifms_type(iface->if_type)),
41437f8d125Sjca 		    get_linkstate(iface->if_type, iface->linkstate),
41537f8d125Sjca 		    iface->mtu);
416ab5e4d03Sclaudio 		if (iface->linkstate != LINK_STATE_DOWN &&
417ab5e4d03Sclaudio 		    iface->baudrate > 0) {
418ab5e4d03Sclaudio 		    printf(", ");
419ab5e4d03Sclaudio 		    print_baudrate(iface->baudrate);
420ab5e4d03Sclaudio 		}
421ab5e4d03Sclaudio 		printf("\n");
4228e709cbdSnorby 		printf("  Router ID %s, network type %s, cost: %d\n",
4238e709cbdSnorby 		    inet_ntoa(iface->rtr_id),
4248e709cbdSnorby 		    if_type_name(iface->type), iface->metric);
4258e709cbdSnorby 		printf("  Transmit delay is %d sec(s), state %s, priority %d\n",
4268e709cbdSnorby 		    iface->transmit_delay, if_state_name(iface->state),
4278e709cbdSnorby 		    iface->priority);
4287aab4200Snorby 		printf("  Designated Router (ID) %s\n",
4298e709cbdSnorby 		    inet_ntoa(iface->dr_id));
4307aab4200Snorby 		printf("    Interface address %s\n",
4317aab4200Snorby 		    log_in6addr(&iface->dr_addr));
4327aab4200Snorby 		printf("  Backup Designated Router (ID) %s\n",
4338e709cbdSnorby 		    inet_ntoa(iface->bdr_id));
4347aab4200Snorby 		printf("    Interface address %s\n",
4357aab4200Snorby 		    log_in6addr(&iface->bdr_addr));
4368e709cbdSnorby 		printf("  Timer intervals configured, "
4378e709cbdSnorby 		    "hello %d, dead %d, wait %d, retransmit %d\n",
4388e709cbdSnorby 		     iface->hello_interval, iface->dead_interval,
4398e709cbdSnorby 		     iface->dead_interval, iface->rxmt_interval);
4408e709cbdSnorby 		if (iface->passive)
4418e709cbdSnorby 			printf("    Passive interface (No Hellos)\n");
4428e709cbdSnorby 		else if (iface->hello_timer < 0)
4438e709cbdSnorby 			printf("    Hello timer not running\n");
4448e709cbdSnorby 		else
4458e709cbdSnorby 			printf("    Hello timer due in %s\n",
4468e709cbdSnorby 			    fmt_timeframe_core(iface->hello_timer));
4478e709cbdSnorby 		printf("    Uptime %s\n", fmt_timeframe_core(iface->uptime));
4488e709cbdSnorby 		printf("  Neighbor count is %d, adjacent neighbor count is "
4498e709cbdSnorby 		    "%d\n", iface->nbr_cnt, iface->adj_cnt);
4508e709cbdSnorby 		break;
4518e709cbdSnorby 	case IMSG_CTL_END:
4528e709cbdSnorby 		printf("\n");
4538e709cbdSnorby 		return (1);
4548e709cbdSnorby 	default:
4558e709cbdSnorby 		break;
4568e709cbdSnorby 	}
4578e709cbdSnorby 
4588e709cbdSnorby 	return (0);
4598e709cbdSnorby }
4608e709cbdSnorby 
4618e709cbdSnorby const char *
4628e709cbdSnorby print_link(int state)
4638e709cbdSnorby {
4648e709cbdSnorby 	if (state & IFF_UP)
4658e709cbdSnorby 		return ("UP");
4668e709cbdSnorby 	else
4678e709cbdSnorby 		return ("DOWN");
4688e709cbdSnorby }
4698e709cbdSnorby 
4708e709cbdSnorby #define TF_BUFS	8
4718e709cbdSnorby #define TF_LEN	9
4728e709cbdSnorby 
4738e709cbdSnorby const char *
4748e709cbdSnorby fmt_timeframe(time_t t)
4758e709cbdSnorby {
4768e709cbdSnorby 	if (t == 0)
4778e709cbdSnorby 		return ("Never");
4788e709cbdSnorby 	else
4798e709cbdSnorby 		return (fmt_timeframe_core(time(NULL) - t));
4808e709cbdSnorby }
4818e709cbdSnorby 
4828e709cbdSnorby const char *
4838e709cbdSnorby fmt_timeframe_core(time_t t)
4848e709cbdSnorby {
4858e709cbdSnorby 	char		*buf;
4868e709cbdSnorby 	static char	 tfbuf[TF_BUFS][TF_LEN];	/* ring buffer */
4878e709cbdSnorby 	static int	 idx = 0;
488db93f2f1Sderaadt 	unsigned int	 sec, min, hrs, day, week;
4898e709cbdSnorby 
4908e709cbdSnorby 	if (t == 0)
4918e709cbdSnorby 		return ("00:00:00");
4928e709cbdSnorby 
4938e709cbdSnorby 	buf = tfbuf[idx++];
4948e709cbdSnorby 	if (idx == TF_BUFS)
4958e709cbdSnorby 		idx = 0;
4968e709cbdSnorby 
4978e709cbdSnorby 	week = t;
4988e709cbdSnorby 
4998e709cbdSnorby 	sec = week % 60;
5008e709cbdSnorby 	week /= 60;
5018e709cbdSnorby 	min = week % 60;
5028e709cbdSnorby 	week /= 60;
5038e709cbdSnorby 	hrs = week % 24;
5048e709cbdSnorby 	week /= 24;
5058e709cbdSnorby 	day = week % 7;
5068e709cbdSnorby 	week /= 7;
5078e709cbdSnorby 
5088e709cbdSnorby 	if (week > 0)
5098e709cbdSnorby 		snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs);
5108e709cbdSnorby 	else if (day > 0)
5118e709cbdSnorby 		snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
5128e709cbdSnorby 	else
5138e709cbdSnorby 		snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
5148e709cbdSnorby 
5158e709cbdSnorby 	return (buf);
5168e709cbdSnorby }
5178e709cbdSnorby 
5188e709cbdSnorby const char *
5198e709cbdSnorby log_id(u_int32_t id)
5208e709cbdSnorby {
5218e709cbdSnorby 	static char	buf[48];
5228e709cbdSnorby 	struct in_addr	addr;
5238e709cbdSnorby 
5248e709cbdSnorby 	addr.s_addr = id;
5258e709cbdSnorby 
5268e709cbdSnorby 	if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL)
5278e709cbdSnorby 		return ("?");
5288e709cbdSnorby 	else
5298e709cbdSnorby 		return (buf);
5308e709cbdSnorby }
5318e709cbdSnorby 
5328e709cbdSnorby const char *
5338e709cbdSnorby log_adv_rtr(u_int32_t adv_rtr)
5348e709cbdSnorby {
5358e709cbdSnorby 	static char	buf[48];
5368e709cbdSnorby 	struct in_addr	addr;
5378e709cbdSnorby 
5388e709cbdSnorby 	addr.s_addr = adv_rtr;
5398e709cbdSnorby 
5408e709cbdSnorby 	if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL)
5418e709cbdSnorby 		return ("?");
5428e709cbdSnorby 	else
5438e709cbdSnorby 		return (buf);
5448e709cbdSnorby }
5458e709cbdSnorby 
5468e709cbdSnorby void
547cb01fa27Sclaudio show_database_head(struct in_addr aid, char *ifname, u_int16_t type)
5488e709cbdSnorby {
5498e709cbdSnorby 	char	*header, *format;
550cb01fa27Sclaudio 	int	cleanup = 0;
5518e709cbdSnorby 
552005d568eSclaudio 	switch (ntohs(type)) {
5534fabe8f9Snorby 	case LSA_TYPE_LINK:
5548ea4c735Sclaudio 		format = "Link (Type-8) Link States";
5554fabe8f9Snorby 		break;
5568e709cbdSnorby 	case LSA_TYPE_ROUTER:
5578e709cbdSnorby 		format = "Router Link States";
5588e709cbdSnorby 		break;
5598e709cbdSnorby 	case LSA_TYPE_NETWORK:
5608e709cbdSnorby 		format = "Net Link States";
5618e709cbdSnorby 		break;
5624fabe8f9Snorby 	case LSA_TYPE_INTER_A_PREFIX:
5634fabe8f9Snorby 		format = "Inter Area Prefix Link States";
5648e709cbdSnorby 		break;
5654fabe8f9Snorby 	case LSA_TYPE_INTER_A_ROUTER:
5664fabe8f9Snorby 		format = "Inter Area Router Link States";
5674fabe8f9Snorby 		break;
5684fabe8f9Snorby 	case LSA_TYPE_INTRA_A_PREFIX:
5698ec36425Sstsp 		format = "Intra Area Prefix Link States";
5708e709cbdSnorby 		break;
5718e709cbdSnorby 	case LSA_TYPE_EXTERNAL:
572cb01fa27Sclaudio 		printf("\n%-15s %s\n\n", "", "Type-5 AS External Link States");
573cb01fa27Sclaudio 		return;
5748e709cbdSnorby 	default:
575cb01fa27Sclaudio 		if (asprintf(&format, "LSA type %x", ntohs(type)) == -1)
576cb01fa27Sclaudio 			err(1, NULL);
577cb01fa27Sclaudio 		cleanup = 1;
578cb01fa27Sclaudio 		break;
5798e709cbdSnorby 	}
580cb01fa27Sclaudio 	if (LSA_IS_SCOPE_AREA(ntohs(type))) {
5818e709cbdSnorby 		if (asprintf(&header, "%s (Area %s)", format,
5828e709cbdSnorby 		    inet_ntoa(aid)) == -1)
5838e709cbdSnorby 			err(1, NULL);
584cb01fa27Sclaudio 	} else if (LSA_IS_SCOPE_LLOCAL(ntohs(type))) {
585cb01fa27Sclaudio 		if (asprintf(&header, "%s (Area %s Interface %s)", format,
586cb01fa27Sclaudio 		    inet_ntoa(aid), ifname) == -1)
587cb01fa27Sclaudio 			err(1, NULL);
588*73094d71Sbenno 	} else {
589*73094d71Sbenno 		if (asprintf(&header, "%s", format) == -1)
590*73094d71Sbenno 			err(1, NULL);
591cb01fa27Sclaudio 	}
5928e709cbdSnorby 
5938e709cbdSnorby 	printf("\n%-15s %s\n\n", "", header);
5948e709cbdSnorby 	free(header);
595cb01fa27Sclaudio 	if (cleanup)
596cb01fa27Sclaudio 		free(format);
5978e709cbdSnorby }
5988e709cbdSnorby 
5998e709cbdSnorby int
6008e709cbdSnorby show_database_msg(struct imsg *imsg)
6018e709cbdSnorby {
6028e709cbdSnorby 	static struct in_addr	 area_id;
603cb01fa27Sclaudio 	static char		 ifname[IF_NAMESIZE];
6047db04f17Sclaudio 	static u_int16_t	 lasttype;
6058e709cbdSnorby 	struct area		*area;
606cb01fa27Sclaudio 	struct iface		*iface;
6078e709cbdSnorby 	struct lsa_hdr		*lsa;
6088e709cbdSnorby 
6098e709cbdSnorby 	switch (imsg->hdr.type) {
6108e709cbdSnorby 	case IMSG_CTL_SHOW_DATABASE:
6118e709cbdSnorby 	case IMSG_CTL_SHOW_DB_SELF:
6128e709cbdSnorby 		lsa = imsg->data;
6138e709cbdSnorby 		if (lsa->type != lasttype) {
614cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->type);
6158e709cbdSnorby 			printf("%-15s %-15s %-4s %-10s %-8s\n", "Link ID",
6168e709cbdSnorby 			    "Adv Router", "Age", "Seq#", "Checksum");
6178e709cbdSnorby 		}
6188e709cbdSnorby 		printf("%-15s %-15s %-4d 0x%08x 0x%04x\n",
6198e709cbdSnorby 		    log_id(lsa->ls_id), log_adv_rtr(lsa->adv_rtr),
6208e709cbdSnorby 		    ntohs(lsa->age), ntohl(lsa->seq_num),
6218e709cbdSnorby 		    ntohs(lsa->ls_chksum));
6228e709cbdSnorby 		lasttype = lsa->type;
6238e709cbdSnorby 		break;
6248e709cbdSnorby 	case IMSG_CTL_AREA:
6258e709cbdSnorby 		area = imsg->data;
6268e709cbdSnorby 		area_id = area->id;
6278e709cbdSnorby 		lasttype = 0;
6288e709cbdSnorby 		break;
629cb01fa27Sclaudio 	case IMSG_CTL_IFACE:
630cb01fa27Sclaudio 		iface = imsg->data;
631cb01fa27Sclaudio 		strlcpy(ifname, iface->name, sizeof(ifname));
632cb01fa27Sclaudio 		lasttype = 0;
633cb01fa27Sclaudio 		break;
6348e709cbdSnorby 	case IMSG_CTL_END:
6358e709cbdSnorby 		printf("\n");
6368e709cbdSnorby 		return (1);
6378e709cbdSnorby 	default:
6388e709cbdSnorby 		break;
6398e709cbdSnorby 	}
6408e709cbdSnorby 
6418e709cbdSnorby 	return (0);
6428e709cbdSnorby }
6438e709cbdSnorby 
6448e709cbdSnorby char *
6454fabe8f9Snorby print_ls_type(u_int16_t type)
6468e709cbdSnorby {
647005d568eSclaudio 	switch (ntohs(type)) {
6484fabe8f9Snorby 	case LSA_TYPE_LINK:
6494fabe8f9Snorby 		return ("Link");
6508e709cbdSnorby 	case LSA_TYPE_ROUTER:
6518e709cbdSnorby 		return ("Router");
6528e709cbdSnorby 	case LSA_TYPE_NETWORK:
6538e709cbdSnorby 		return ("Network");
6544fabe8f9Snorby 	case LSA_TYPE_INTER_A_PREFIX:
6554fabe8f9Snorby 		return ("Inter Area (Prefix)");
6564fabe8f9Snorby 	case LSA_TYPE_INTER_A_ROUTER:
6574fabe8f9Snorby 		return ("Inter Area (Router)");
6584fabe8f9Snorby 	case LSA_TYPE_INTRA_A_PREFIX:
6594fabe8f9Snorby 		return ("Intra Area (Prefix)");
6608e709cbdSnorby 	case LSA_TYPE_EXTERNAL:
6618e709cbdSnorby 		return ("AS External");
6628e709cbdSnorby 	default:
6638e709cbdSnorby 		return ("Unknown");
6648e709cbdSnorby 	}
6658e709cbdSnorby }
6668e709cbdSnorby 
6678e709cbdSnorby void
6688e709cbdSnorby show_db_hdr_msg_detail(struct lsa_hdr *lsa)
6698e709cbdSnorby {
6708e709cbdSnorby 	printf("LS age: %d\n", ntohs(lsa->age));
6718e709cbdSnorby 	printf("LS Type: %s\n", print_ls_type(lsa->type));
6728e709cbdSnorby 
673005d568eSclaudio 	switch (ntohs(lsa->type)) {
67489f180e4Sstsp 	case LSA_TYPE_ROUTER:
67589f180e4Sstsp 	case LSA_TYPE_INTER_A_PREFIX:
67689f180e4Sstsp 	case LSA_TYPE_INTER_A_ROUTER:
67789f180e4Sstsp 	case LSA_TYPE_INTRA_A_PREFIX:
67889f180e4Sstsp 	case LSA_TYPE_EXTERNAL:
6794fabe8f9Snorby 		printf("Link State ID: %s\n", log_id(lsa->ls_id));
6804fabe8f9Snorby 		break;
68189f180e4Sstsp 	case LSA_TYPE_LINK:
68289f180e4Sstsp 		printf("Link State ID: %s (Interface ID of Advertising "
68389f180e4Sstsp 		    "Router)\n", log_id(lsa->ls_id));
6848e709cbdSnorby 		break;
6858e709cbdSnorby 	case LSA_TYPE_NETWORK:
68689f180e4Sstsp 		printf("Link State ID: %s (Interface ID of Designated "
68789f180e4Sstsp 		    "Router)\n", log_id(lsa->ls_id));
6888e709cbdSnorby 		break;
6898e709cbdSnorby 	}
6908e709cbdSnorby 
6918e709cbdSnorby 	printf("Advertising Router: %s\n", log_adv_rtr(lsa->adv_rtr));
6928e709cbdSnorby 	printf("LS Seq Number: 0x%08x\n", ntohl(lsa->seq_num));
6938e709cbdSnorby 	printf("Checksum: 0x%04x\n", ntohs(lsa->ls_chksum));
6948e709cbdSnorby 	printf("Length: %d\n", ntohs(lsa->len));
6958e709cbdSnorby }
6968e709cbdSnorby 
6978e709cbdSnorby char *
6988e709cbdSnorby print_rtr_link_type(u_int8_t type)
6998e709cbdSnorby {
7008e709cbdSnorby 	switch (type) {
7018e709cbdSnorby 	case LINK_TYPE_POINTTOPOINT:
7028e709cbdSnorby 		return ("Point-to-Point");
7038e709cbdSnorby 	case LINK_TYPE_TRANSIT_NET:
7048e709cbdSnorby 		return ("Transit Network");
705005d568eSclaudio 	case LINK_TYPE_RESERVED:
706005d568eSclaudio 		return ("Reserved");
7078e709cbdSnorby 	case LINK_TYPE_VIRTUAL:
7088e709cbdSnorby 		return ("Virtual Link");
7098e709cbdSnorby 	default:
7108e709cbdSnorby 		return ("Unknown");
7118e709cbdSnorby 	}
7128e709cbdSnorby }
7138e709cbdSnorby 
7148e709cbdSnorby const char *
7158e709cbdSnorby print_ospf_flags(u_int8_t opts)
7168e709cbdSnorby {
7178e709cbdSnorby 	static char	optbuf[32];
7188e709cbdSnorby 
719aff6ccb8Sclaudio 	snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s",
7208e709cbdSnorby 	    opts & OSPF_RTR_V ? "V" : "-",
7218e709cbdSnorby 	    opts & OSPF_RTR_E ? "E" : "-",
7228e709cbdSnorby 	    opts & OSPF_RTR_B ? "B" : "-");
7238e709cbdSnorby 	return (optbuf);
7248e709cbdSnorby }
7258e709cbdSnorby 
7261aff836dSclaudio const char *
7271aff836dSclaudio print_asext_flags(u_int32_t opts)
7281aff836dSclaudio {
7291aff836dSclaudio 	static char	optbuf[32];
7301aff836dSclaudio 
7311aff836dSclaudio 	snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s",
7321aff836dSclaudio 	    opts & LSA_ASEXT_E_FLAG ? "E" : "-",
7331aff836dSclaudio 	    opts & LSA_ASEXT_F_FLAG ? "F" : "-",
7341aff836dSclaudio 	    opts & LSA_ASEXT_T_FLAG ? "T" : "-");
7351aff836dSclaudio 	return (optbuf);
7361aff836dSclaudio }
7371aff836dSclaudio 
7381aff836dSclaudio const char *
7391aff836dSclaudio print_prefix_opt(u_int8_t opts)
7401aff836dSclaudio {
7411aff836dSclaudio 	static char	optbuf[32];
7421aff836dSclaudio 
7431aff836dSclaudio 	if (opts) {
7441aff836dSclaudio 		snprintf(optbuf, sizeof(optbuf),
7451aff836dSclaudio 		    " Options: *|*|*|%s|%s|x|%s|%s",
7461aff836dSclaudio 		    opts & OSPF_PREFIX_DN ? "DN" : "-",
7471aff836dSclaudio 		    opts & OSPF_PREFIX_P ? "P" : "-",
7481aff836dSclaudio 		    opts & OSPF_PREFIX_LA ? "LA" : "-",
7491aff836dSclaudio 		    opts & OSPF_PREFIX_NU ? "NU" : "-");
7501aff836dSclaudio 		return (optbuf);
7511aff836dSclaudio 	}
7521aff836dSclaudio 	return ("");
7531aff836dSclaudio }
7541aff836dSclaudio 
7558e709cbdSnorby int
7568e709cbdSnorby show_db_msg_detail(struct imsg *imsg)
7578e709cbdSnorby {
7588e709cbdSnorby 	static struct in_addr	 area_id;
759cb01fa27Sclaudio 	static char		 ifname[IF_NAMESIZE];
760005d568eSclaudio 	static u_int16_t	 lasttype;
7611aff836dSclaudio 	struct in6_addr		 ia6;
7628e709cbdSnorby 	struct in_addr		 addr, data;
7638e709cbdSnorby 	struct area		*area;
764cb01fa27Sclaudio 	struct iface		*iface;
7658e709cbdSnorby 	struct lsa		*lsa;
7668e709cbdSnorby 	struct lsa_rtr_link	*rtr_link;
7670f96e20cSstsp 	struct lsa_net_link	*net_link;
768aeb06b08Sclaudio 	struct lsa_prefix	*prefix;
7698e709cbdSnorby 	struct lsa_asext	*asext;
7701aff836dSclaudio 	u_int32_t		 ext_tag;
7718e709cbdSnorby 	u_int16_t		 i, nlinks, off;
7728e709cbdSnorby 
7738e709cbdSnorby 	/* XXX sanity checks! */
7748e709cbdSnorby 
7758e709cbdSnorby 	switch (imsg->hdr.type) {
7768e709cbdSnorby 	case IMSG_CTL_SHOW_DB_EXT:
7778e709cbdSnorby 		lsa = imsg->data;
7788e709cbdSnorby 		if (lsa->hdr.type != lasttype)
779cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
7808e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
7818e709cbdSnorby 
7828e709cbdSnorby 		asext = (struct lsa_asext *)((char *)lsa + sizeof(lsa->hdr));
7838e709cbdSnorby 
7841aff836dSclaudio 		printf("    Flags: %s\n",
7851aff836dSclaudio 		    print_asext_flags(ntohl(lsa->data.asext.metric)));
7861aff836dSclaudio 		printf("    Metric: %d Type: ", ntohl(asext->metric)
7871aff836dSclaudio 		    & LSA_METRIC_MASK);
7888e709cbdSnorby 		if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_E_FLAG)
7898e709cbdSnorby 			printf("2\n");
7908e709cbdSnorby 		else
7918e709cbdSnorby 			printf("1\n");
7928e709cbdSnorby 
7931aff836dSclaudio 		prefix = &asext->prefix;
7941aff836dSclaudio 		bzero(&ia6, sizeof(ia6));
7951aff836dSclaudio 		bcopy(prefix + 1, &ia6, LSA_PREFIXSIZE(prefix->prefixlen));
7961aff836dSclaudio 		printf("    Prefix: %s/%d%s\n", log_in6addr(&ia6),
7971aff836dSclaudio 		    prefix->prefixlen, print_prefix_opt(prefix->options));
7981aff836dSclaudio 
7991aff836dSclaudio 		off = sizeof(*asext) + LSA_PREFIXSIZE(prefix->prefixlen);
8001aff836dSclaudio 		if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_F_FLAG) {
8011aff836dSclaudio 			bcopy((char *)asext + off, &ia6, sizeof(ia6));
8021aff836dSclaudio 			printf("    Forwarding Address: %s\n",
8031aff836dSclaudio 			    log_in6addr(&ia6));
8041aff836dSclaudio 			off += sizeof(ia6);
8051aff836dSclaudio 		}
8061aff836dSclaudio 		if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_T_FLAG) {
8071aff836dSclaudio 			bcopy((char *)asext + off, &ext_tag, sizeof(ext_tag));
8081aff836dSclaudio 			printf("    External Route Tag: %d\n", ntohl(ext_tag));
8091aff836dSclaudio 		}
8101aff836dSclaudio 		printf("\n");
8118e709cbdSnorby 		lasttype = lsa->hdr.type;
8128e709cbdSnorby 		break;
813aeb06b08Sclaudio 	case IMSG_CTL_SHOW_DB_LINK:
814aeb06b08Sclaudio 		lsa = imsg->data;
815aeb06b08Sclaudio 		if (lsa->hdr.type != lasttype)
816aeb06b08Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
817aeb06b08Sclaudio 		show_db_hdr_msg_detail(&lsa->hdr);
8185a54ac3cSclaudio 		printf("Options: %s\n", print_ospf_options(LSA_24_GETLO(
8195a54ac3cSclaudio 		    ntohl(lsa->data.link.opts))));
8205a54ac3cSclaudio 		printf("Link Local Address: %s\n",
8215a54ac3cSclaudio 		    log_in6addr(&lsa->data.link.lladdr));
822aeb06b08Sclaudio 
823aeb06b08Sclaudio 		nlinks = ntohl(lsa->data.link.numprefix);
824aeb06b08Sclaudio 		printf("Number of Prefixes: %d\n", nlinks);
825aeb06b08Sclaudio 		off = sizeof(lsa->hdr) + sizeof(struct lsa_link);
826aeb06b08Sclaudio 
827aeb06b08Sclaudio 		for (i = 0; i < nlinks; i++) {
828aeb06b08Sclaudio 			prefix = (struct lsa_prefix *)((char *)lsa + off);
8295a54ac3cSclaudio 			bzero(&ia6, sizeof(ia6));
8305a54ac3cSclaudio 			bcopy(prefix + 1, &ia6,
8315a54ac3cSclaudio 			    LSA_PREFIXSIZE(prefix->prefixlen));
832aeb06b08Sclaudio 
8331aff836dSclaudio 			printf("    Prefix: %s/%d%s\n", log_in6addr(&ia6),
8341aff836dSclaudio 			    prefix->prefixlen,
8351aff836dSclaudio 			    print_prefix_opt(prefix->options));
836aeb06b08Sclaudio 
83708720e8dSstsp 			off += sizeof(struct lsa_prefix)
83808720e8dSstsp 			    + LSA_PREFIXSIZE(prefix->prefixlen);
839aeb06b08Sclaudio 		}
840aeb06b08Sclaudio 
841aeb06b08Sclaudio 		printf("\n");
842aeb06b08Sclaudio 		lasttype = lsa->hdr.type;
843aeb06b08Sclaudio 		break;
8448e709cbdSnorby 	case IMSG_CTL_SHOW_DB_NET:
8458e709cbdSnorby 		lsa = imsg->data;
8468e709cbdSnorby 		if (lsa->hdr.type != lasttype)
847cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
8488e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
8490bc8b661Sclaudio 		printf("Options: %s\n",
8500bc8b661Sclaudio 		    print_ospf_options(LSA_24_GETLO(ntohl(lsa->data.net.opts))));
8518e709cbdSnorby 
8520f96e20cSstsp 		nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr) -
8530f96e20cSstsp 		    sizeof(struct lsa_net)) / sizeof(struct lsa_net_link);
8540f96e20cSstsp 		net_link = (struct lsa_net_link *)((char *)lsa +
8550f96e20cSstsp 		    sizeof(lsa->hdr) + sizeof(lsa->data.net));
856aeb06b08Sclaudio 		printf("Number of Routers: %d\n", nlinks);
8578e709cbdSnorby 
8588e709cbdSnorby 		for (i = 0; i < nlinks; i++) {
8590f96e20cSstsp 			addr.s_addr = net_link->att_rtr;
8608e709cbdSnorby 			printf("    Attached Router: %s\n", inet_ntoa(addr));
8610f96e20cSstsp 			net_link++;
8628e709cbdSnorby 		}
8638e709cbdSnorby 
8648e709cbdSnorby 		printf("\n");
8658e709cbdSnorby 		lasttype = lsa->hdr.type;
8668e709cbdSnorby 		break;
8678e709cbdSnorby 	case IMSG_CTL_SHOW_DB_RTR:
8688e709cbdSnorby 		lsa = imsg->data;
8698e709cbdSnorby 		if (lsa->hdr.type != lasttype)
870cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
8718e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
8729d28d229Sclaudio 		printf("Flags: %s\n",
873aff6ccb8Sclaudio 		    print_ospf_flags(LSA_24_GETHI(ntohl(lsa->data.rtr.opts))));
8749d28d229Sclaudio 		printf("Options: %s\n",
875aff6ccb8Sclaudio 		    print_ospf_options(LSA_24_GETLO(ntohl(lsa->data.rtr.opts))));
8769d28d229Sclaudio 
8779d28d229Sclaudio 		nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr)
8789d28d229Sclaudio 		    - sizeof(u_int32_t)) / sizeof(struct lsa_rtr_link);
8794091c104Sbluhm 		printf("Number of Links: %d\n\n", nlinks);
8808e709cbdSnorby 
8818e709cbdSnorby 		off = sizeof(lsa->hdr) + sizeof(struct lsa_rtr);
8828e709cbdSnorby 
8838e709cbdSnorby 		for (i = 0; i < nlinks; i++) {
8848e709cbdSnorby 			rtr_link = (struct lsa_rtr_link *)((char *)lsa + off);
8858e709cbdSnorby 
8863ded35dfSstsp 			printf("    Link (Interface ID %s) connected to: %s\n",
8873ded35dfSstsp 			    log_id(rtr_link->iface_id),
8888e709cbdSnorby 			    print_rtr_link_type(rtr_link->type));
8898e709cbdSnorby 
890005d568eSclaudio 			addr.s_addr = rtr_link->nbr_rtr_id;
8913ded35dfSstsp 			data.s_addr = rtr_link->nbr_iface_id;
8928e709cbdSnorby 
8938e709cbdSnorby 			switch (rtr_link->type) {
8948e709cbdSnorby 			case LINK_TYPE_POINTTOPOINT:
8958e709cbdSnorby 			case LINK_TYPE_VIRTUAL:
896005d568eSclaudio 				printf("    Router ID: %s\n", inet_ntoa(addr));
897005d568eSclaudio 				printf("    Interface ID: %s\n",
898005d568eSclaudio 				    inet_ntoa(data));
8998e709cbdSnorby 				break;
9008e709cbdSnorby 			case LINK_TYPE_TRANSIT_NET:
901005d568eSclaudio 				printf("    Designated Router ID: %s\n",
9028e709cbdSnorby 				    inet_ntoa(addr));
903005d568eSclaudio 				printf("    DR Interface ID: %s\n",
9048e709cbdSnorby 				    inet_ntoa(data));
9058e709cbdSnorby 				break;
9068e709cbdSnorby 			default:
907005d568eSclaudio 				printf("    Link ID (Unknown type %d): %s\n",
908005d568eSclaudio 				    rtr_link->type, inet_ntoa(addr));
9098e709cbdSnorby 				printf("    Link Data (Unknown): %s\n",
9108e709cbdSnorby 				    inet_ntoa(data));
9118e709cbdSnorby 				break;
9128e709cbdSnorby 			}
9138e709cbdSnorby 
9148e709cbdSnorby 			printf("    Metric: %d\n\n", ntohs(rtr_link->metric));
9158e709cbdSnorby 
916005d568eSclaudio 			off += sizeof(struct lsa_rtr_link);
9178e709cbdSnorby 		}
9188e709cbdSnorby 
9198e709cbdSnorby 		lasttype = lsa->hdr.type;
9208e709cbdSnorby 		break;
92141bcac6bSstsp 	case IMSG_CTL_SHOW_DB_INTRA:
92241bcac6bSstsp 		lsa = imsg->data;
92341bcac6bSstsp 		if (lsa->hdr.type != lasttype)
92441bcac6bSstsp 			show_database_head(area_id, ifname, lsa->hdr.type);
92541bcac6bSstsp 		show_db_hdr_msg_detail(&lsa->hdr);
92641bcac6bSstsp 		printf("Referenced LS Type: %s\n",
92741bcac6bSstsp 		    print_ls_type(lsa->data.pref_intra.ref_type));
928e0e6f381Sclaudio 		addr.s_addr = lsa->data.pref_intra.ref_ls_id;
92941bcac6bSstsp 		printf("Referenced Link State ID: %s\n", inet_ntoa(addr));
93041bcac6bSstsp 		addr.s_addr = lsa->data.pref_intra.ref_adv_rtr;
93141bcac6bSstsp 		printf("Referenced Advertising Router: %s\n", inet_ntoa(addr));
93241bcac6bSstsp 		nlinks = ntohs(lsa->data.pref_intra.numprefix);
93341bcac6bSstsp 		printf("Number of Prefixes: %d\n", nlinks);
93441bcac6bSstsp 
93541bcac6bSstsp 		off = sizeof(lsa->hdr) + sizeof(struct lsa_intra_prefix);
93641bcac6bSstsp 
93741bcac6bSstsp 		for (i = 0; i < nlinks; i++) {
93841bcac6bSstsp 			prefix = (struct lsa_prefix *)((char *)lsa + off);
93941bcac6bSstsp 			bzero(&ia6, sizeof(ia6));
94041bcac6bSstsp 			bcopy(prefix + 1, &ia6,
94141bcac6bSstsp 			    LSA_PREFIXSIZE(prefix->prefixlen));
94241bcac6bSstsp 
9431aff836dSclaudio 			printf("    Prefix: %s/%d%s\n", log_in6addr(&ia6),
9441aff836dSclaudio 			    prefix->prefixlen,
9451aff836dSclaudio 			    print_prefix_opt(prefix->options));
94641bcac6bSstsp 
94708720e8dSstsp 			off += sizeof(struct lsa_prefix)
94808720e8dSstsp 			    + LSA_PREFIXSIZE(prefix->prefixlen);
94941bcac6bSstsp 		}
9509415b30cSstsp 
9519415b30cSstsp 		printf("\n");
9529415b30cSstsp 		lasttype = lsa->hdr.type;
95341bcac6bSstsp 		break;
9548e709cbdSnorby 	case IMSG_CTL_SHOW_DB_SUM:
9558e709cbdSnorby 		lsa = imsg->data;
9568e709cbdSnorby 		if (lsa->hdr.type != lasttype)
957cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
9588e709cbdSnorby 		show_db_hdr_msg_detail(&lsa->hdr);
959cb01fa27Sclaudio 		printf("Prefix: XXX\n");
960aeb06b08Sclaudio 		printf("Metric: %d\n", ntohl(lsa->data.pref_sum.metric) &
9618e709cbdSnorby 		    LSA_METRIC_MASK);
9628e709cbdSnorby 		lasttype = lsa->hdr.type;
9638e709cbdSnorby 		break;
964cb01fa27Sclaudio 	case IMSG_CTL_SHOW_DB_ASBR:
965cb01fa27Sclaudio 		lsa = imsg->data;
966cb01fa27Sclaudio 		if (lsa->hdr.type != lasttype)
967cb01fa27Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
968cb01fa27Sclaudio 		show_db_hdr_msg_detail(&lsa->hdr);
969cb01fa27Sclaudio 
970cb01fa27Sclaudio 		addr.s_addr = lsa->data.rtr_sum.dest_rtr_id;
971cb01fa27Sclaudio 		printf("Destination Router ID: %s\n", inet_ntoa(addr));
972cb01fa27Sclaudio 		printf("Options: %s\n",
973aeb06b08Sclaudio 		    print_ospf_options(ntohl(lsa->data.rtr_sum.opts)));
974cb01fa27Sclaudio 		printf("Metric: %d\n\n", ntohl(lsa->data.rtr_sum.metric) &
975cb01fa27Sclaudio 		    LSA_METRIC_MASK);
9768e709cbdSnorby 	case IMSG_CTL_AREA:
9778e709cbdSnorby 		area = imsg->data;
9788e709cbdSnorby 		area_id = area->id;
9798e709cbdSnorby 		lasttype = 0;
9808e709cbdSnorby 		break;
981cb01fa27Sclaudio 	case IMSG_CTL_IFACE:
982cb01fa27Sclaudio 		iface = imsg->data;
983cb01fa27Sclaudio 		strlcpy(ifname, iface->name, sizeof(ifname));
984cb01fa27Sclaudio 		lasttype = 0;
985cb01fa27Sclaudio 		break;
9868e709cbdSnorby 	case IMSG_CTL_END:
9878e709cbdSnorby 		return (1);
9888e709cbdSnorby 	default:
9898e709cbdSnorby 		break;
9908e709cbdSnorby 	}
9918e709cbdSnorby 
9928e709cbdSnorby 	return (0);
9938e709cbdSnorby }
9948e709cbdSnorby 
9958e709cbdSnorby int
9968e709cbdSnorby show_nbr_msg(struct imsg *imsg)
9978e709cbdSnorby {
9988e709cbdSnorby 	struct ctl_nbr	*nbr;
9998e709cbdSnorby 	char		*state;
10008e709cbdSnorby 
10018e709cbdSnorby 	switch (imsg->hdr.type) {
10028e709cbdSnorby 	case IMSG_CTL_SHOW_NBR:
10038e709cbdSnorby 		nbr = imsg->data;
10048e709cbdSnorby 		if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state),
10058e709cbdSnorby 		    if_state_name(nbr->iface_state)) == -1)
10068e709cbdSnorby 			err(1, NULL);
1007558ada41Snorby 		printf("%-15s %-3d %-12s %-10s", inet_ntoa(nbr->id),
10088e709cbdSnorby 		    nbr->priority, state, fmt_timeframe_core(nbr->dead_timer));
1009558ada41Snorby 		printf("%-11s %s\n", nbr->name,
10108e709cbdSnorby 		    nbr->uptime == 0 ? "-" : fmt_timeframe_core(nbr->uptime));
10118e709cbdSnorby 		free(state);
10128e709cbdSnorby 		break;
10138e709cbdSnorby 	case IMSG_CTL_END:
10148e709cbdSnorby 		printf("\n");
10158e709cbdSnorby 		return (1);
10168e709cbdSnorby 	default:
10178e709cbdSnorby 		break;
10188e709cbdSnorby 	}
10198e709cbdSnorby 
10208e709cbdSnorby 	return (0);
10218e709cbdSnorby }
10228e709cbdSnorby 
10238e709cbdSnorby const char *
1024aff6ccb8Sclaudio print_ospf_options(u_int32_t opts)
10258e709cbdSnorby {
10268e709cbdSnorby 	static char	optbuf[32];
10278e709cbdSnorby 
1028aff6ccb8Sclaudio 	snprintf(optbuf, sizeof(optbuf), "*|*|%s|%s|%s|*|%s|%s",
10298e709cbdSnorby 	    opts & OSPF_OPTION_DC ? "DC" : "-",
10308e709cbdSnorby 	    opts & OSPF_OPTION_R ? "R" : "-",
10318e709cbdSnorby 	    opts & OSPF_OPTION_N ? "N" : "-",
10328e709cbdSnorby 	    opts & OSPF_OPTION_E ? "E" : "-",
10338e709cbdSnorby 	    opts & OSPF_OPTION_V6 ? "V6" : "-");
10348e709cbdSnorby 	return (optbuf);
10358e709cbdSnorby }
10368e709cbdSnorby 
10378e709cbdSnorby int
10388e709cbdSnorby show_nbr_detail_msg(struct imsg *imsg)
10398e709cbdSnorby {
10408e709cbdSnorby 	struct ctl_nbr	*nbr;
10418e709cbdSnorby 
10428e709cbdSnorby 	switch (imsg->hdr.type) {
10438e709cbdSnorby 	case IMSG_CTL_SHOW_NBR:
10448e709cbdSnorby 		nbr = imsg->data;
10458e709cbdSnorby 		printf("\nNeighbor %s, ", inet_ntoa(nbr->id));
10468e709cbdSnorby 		printf("interface address %s\n", log_in6addr(&nbr->addr));
10478e709cbdSnorby 		printf("  Area %s, interface %s\n", inet_ntoa(nbr->area),
10488e709cbdSnorby 		    nbr->name);
10498e709cbdSnorby 		printf("  Neighbor priority is %d, "
10508e709cbdSnorby 		    "State is %s, %d state changes\n",
10518e709cbdSnorby 		    nbr->priority, nbr_state_name(nbr->nbr_state),
10528e709cbdSnorby 		    nbr->state_chng_cnt);
10538e709cbdSnorby 		printf("  DR is %s, ", inet_ntoa(nbr->dr));
10548e709cbdSnorby 		printf("BDR is %s\n", inet_ntoa(nbr->bdr));
10558e709cbdSnorby 		printf("  Options %s\n", print_ospf_options(nbr->options));
10568e709cbdSnorby 		printf("  Dead timer due in %s\n",
10578e709cbdSnorby 		    fmt_timeframe_core(nbr->dead_timer));
10588e709cbdSnorby 		printf("  Uptime %s\n", fmt_timeframe_core(nbr->uptime));
10598e709cbdSnorby 		printf("  Database Summary List %d\n", nbr->db_sum_lst_cnt);
10608e709cbdSnorby 		printf("  Link State Request List %d\n", nbr->ls_req_lst_cnt);
10618e709cbdSnorby 		printf("  Link State Retransmission List %d\n",
10628e709cbdSnorby 		    nbr->ls_retrans_lst_cnt);
10638e709cbdSnorby 		break;
10648e709cbdSnorby 	case IMSG_CTL_END:
10658e709cbdSnorby 		printf("\n");
10668e709cbdSnorby 		return (1);
10678e709cbdSnorby 	default:
10688e709cbdSnorby 		break;
10698e709cbdSnorby 	}
10708e709cbdSnorby 
10718e709cbdSnorby 	return (0);
10728e709cbdSnorby }
10738e709cbdSnorby 
10748e709cbdSnorby int
10758e709cbdSnorby show_rib_msg(struct imsg *imsg)
10768e709cbdSnorby {
10778e709cbdSnorby 	struct ctl_rt	*rt;
10788e709cbdSnorby 	char		*dstnet;
10798e709cbdSnorby 
10808e709cbdSnorby 	switch (imsg->hdr.type) {
10818e709cbdSnorby 	case IMSG_CTL_SHOW_RIB:
10828e709cbdSnorby 		rt = imsg->data;
10838e709cbdSnorby 		switch (rt->d_type) {
10848e709cbdSnorby 		case DT_NET:
10850104e403Sclaudio 			if (asprintf(&dstnet, "%s/%d", log_in6addr(&rt->prefix),
10868e709cbdSnorby 			    rt->prefixlen) == -1)
10878e709cbdSnorby 				err(1, NULL);
10888e709cbdSnorby 			break;
10898e709cbdSnorby 		case DT_RTR:
10908e709cbdSnorby 			if (asprintf(&dstnet, "%s",
10910104e403Sclaudio 			    log_in6addr(&rt->prefix)) == -1)
10928e709cbdSnorby 				err(1, NULL);
10938e709cbdSnorby 			break;
10948e709cbdSnorby 		default:
10958e709cbdSnorby 			errx(1, "Invalid route type");
10968e709cbdSnorby 		}
10978e709cbdSnorby 
10988e709cbdSnorby 		printf("%-20s %-17s %-12s %-9s %-7d %s\n", dstnet,
10990a08a1b1Sclaudio 		    log_in6addr_scope(&rt->nexthop, rt->ifindex),
11000a08a1b1Sclaudio 		    path_type_name(rt->p_type), dst_type_name(rt->d_type),
11010a08a1b1Sclaudio 		    rt->cost,
11028e709cbdSnorby 		    rt->uptime == 0 ? "-" : fmt_timeframe_core(rt->uptime));
11038e709cbdSnorby 		free(dstnet);
11048e709cbdSnorby 		break;
11058e709cbdSnorby 	case IMSG_CTL_END:
11068e709cbdSnorby 		printf("\n");
11078e709cbdSnorby 		return (1);
11088e709cbdSnorby 	default:
11098e709cbdSnorby 		break;
11108e709cbdSnorby 	}
11118e709cbdSnorby 
11128e709cbdSnorby 	return (0);
11138e709cbdSnorby }
11148e709cbdSnorby 
11158e709cbdSnorby void
11168e709cbdSnorby show_rib_head(struct in_addr aid, u_int8_t d_type, u_int8_t p_type)
11178e709cbdSnorby {
11188e709cbdSnorby 	char	*header, *format, *format2;
11198e709cbdSnorby 
11208e709cbdSnorby 	switch (p_type) {
11218e709cbdSnorby 	case PT_INTRA_AREA:
11228e709cbdSnorby 	case PT_INTER_AREA:
11238e709cbdSnorby 		switch (d_type) {
11248e709cbdSnorby 		case DT_NET:
11258e709cbdSnorby 			format = "Network Routing Table";
11268e709cbdSnorby 			format2 = "";
11278e709cbdSnorby 			break;
11288e709cbdSnorby 		case DT_RTR:
11298e709cbdSnorby 			format = "Router Routing Table";
11308e709cbdSnorby 			format2 = "Type";
11318e709cbdSnorby 			break;
11328e709cbdSnorby 		default:
11338e709cbdSnorby 			errx(1, "unknown route type");
11348e709cbdSnorby 		}
11358e709cbdSnorby 		break;
11368e709cbdSnorby 	case PT_TYPE1_EXT:
11378e709cbdSnorby 	case PT_TYPE2_EXT:
11388e709cbdSnorby 		format = NULL;
11398e709cbdSnorby 		format2 = "Cost 2";
11408e709cbdSnorby 		if ((header = strdup("External Routing Table")) == NULL)
11418e709cbdSnorby 			err(1, NULL);
11428e709cbdSnorby 		break;
11438e709cbdSnorby 	default:
11448e709cbdSnorby 		errx(1, "unknown route type");
11458e709cbdSnorby 	}
11468e709cbdSnorby 
11478e709cbdSnorby 	if (p_type != PT_TYPE1_EXT && p_type != PT_TYPE2_EXT)
11488e709cbdSnorby 		if (asprintf(&header, "%s (Area %s)", format,
11498e709cbdSnorby 		    inet_ntoa(aid)) == -1)
11508e709cbdSnorby 			err(1, NULL);
11518e709cbdSnorby 
11528e709cbdSnorby 	printf("\n%-18s %s\n", "", header);
11538e709cbdSnorby 	free(header);
11548e709cbdSnorby 
11558e709cbdSnorby 	printf("\n%-18s %-15s %-15s %-12s %-7s %-7s\n", "Destination",
11568e709cbdSnorby 	    "Nexthop", "Adv Router", "Path type", "Cost", format2);
11578e709cbdSnorby }
11588e709cbdSnorby 
11598e709cbdSnorby const char *
11608e709cbdSnorby print_ospf_rtr_flags(u_int8_t opts)
11618e709cbdSnorby {
11628e709cbdSnorby 	static char	optbuf[32];
11638e709cbdSnorby 
11648e709cbdSnorby 	snprintf(optbuf, sizeof(optbuf), "%s%s%s",
11658e709cbdSnorby 	    opts & OSPF_RTR_E ? "AS" : "",
11668e709cbdSnorby 	    opts & OSPF_RTR_E && opts & OSPF_RTR_B ? "+" : "",
11678e709cbdSnorby 	    opts & OSPF_RTR_B ? "ABR" : "");
11688e709cbdSnorby 	return (optbuf);
11698e709cbdSnorby }
11708e709cbdSnorby 
11718e709cbdSnorby int
11728e709cbdSnorby show_rib_detail_msg(struct imsg *imsg)
11738e709cbdSnorby {
11748e709cbdSnorby 	static struct in_addr	 area_id;
11758e709cbdSnorby 	struct ctl_rt		*rt;
11768e709cbdSnorby 	struct area		*area;
11778e709cbdSnorby 	char			*dstnet;
11788e709cbdSnorby 	static u_int8_t		 lasttype;
11798e709cbdSnorby 
11808e709cbdSnorby 	switch (imsg->hdr.type) {
11818e709cbdSnorby 	case IMSG_CTL_SHOW_RIB:
11828e709cbdSnorby 		rt = imsg->data;
11838e709cbdSnorby 
11848e709cbdSnorby 		switch (rt->p_type) {
11858e709cbdSnorby 		case PT_INTRA_AREA:
11868e709cbdSnorby 		case PT_INTER_AREA:
11878e709cbdSnorby 			switch (rt->d_type) {
11888e709cbdSnorby 			case DT_NET:
11898e709cbdSnorby 				if (lasttype != RIB_NET)
11908e709cbdSnorby 					show_rib_head(rt->area, rt->d_type,
11918e709cbdSnorby 					     rt->p_type);
11928e709cbdSnorby 				if (asprintf(&dstnet, "%s/%d",
11930104e403Sclaudio 				    log_in6addr(&rt->prefix),
11940104e403Sclaudio 				    rt->prefixlen) == -1)
11958e709cbdSnorby 					err(1, NULL);
11968e709cbdSnorby 				lasttype = RIB_NET;
11978e709cbdSnorby 				break;
11988e709cbdSnorby 			case DT_RTR:
11998e709cbdSnorby 				if (lasttype != RIB_RTR)
12008e709cbdSnorby 					show_rib_head(rt->area, rt->d_type,
12018e709cbdSnorby 					     rt->p_type);
12028e709cbdSnorby 				if (asprintf(&dstnet, "%s",
12030104e403Sclaudio 				    log_in6addr(&rt->prefix)) == -1)
12048e709cbdSnorby 					err(1, NULL);
12058e709cbdSnorby 				lasttype = RIB_RTR;
12068e709cbdSnorby 				break;
12078e709cbdSnorby 			default:
12088e709cbdSnorby 				errx(1, "unknown route type");
12098e709cbdSnorby 			}
12100104e403Sclaudio 			printf("%-18s %-15s ", dstnet,
12115d8c2b7fSclaudio 			    log_in6addr_scope(&rt->nexthop, rt->ifindex));
12128e709cbdSnorby 			printf("%-15s %-12s %-7d", inet_ntoa(rt->adv_rtr),
12138e709cbdSnorby 			    path_type_name(rt->p_type), rt->cost);
12148e709cbdSnorby 			free(dstnet);
12158e709cbdSnorby 
12168e709cbdSnorby 			if (rt->d_type == DT_RTR)
12178e709cbdSnorby 				printf(" %-7s",
12188e709cbdSnorby 				    print_ospf_rtr_flags(rt->flags));
12198e709cbdSnorby 
12208e709cbdSnorby 			printf("\n");
12218e709cbdSnorby 			break;
12228e709cbdSnorby 		case PT_TYPE1_EXT:
12238e709cbdSnorby 		case PT_TYPE2_EXT:
12248e709cbdSnorby 			if (lasttype != RIB_EXT)
12258e709cbdSnorby 				show_rib_head(rt->area, rt->d_type, rt->p_type);
12268e709cbdSnorby 
12278e709cbdSnorby 			if (asprintf(&dstnet, "%s/%d",
12280104e403Sclaudio 			    log_in6addr(&rt->prefix), rt->prefixlen) == -1)
12298e709cbdSnorby 				err(1, NULL);
12308e709cbdSnorby 
12310104e403Sclaudio 			printf("%-18s %-15s ", dstnet,
12325d8c2b7fSclaudio 			    log_in6addr_scope(&rt->nexthop, rt->ifindex));
12338e709cbdSnorby 			printf("%-15s %-12s %-7d %-7d\n",
12348e709cbdSnorby 			    inet_ntoa(rt->adv_rtr), path_type_name(rt->p_type),
12358e709cbdSnorby 			    rt->cost, rt->cost2);
12368957b20dSstsp 			free(dstnet);
12378e709cbdSnorby 
12388e709cbdSnorby 			lasttype = RIB_EXT;
12398e709cbdSnorby 			break;
12408e709cbdSnorby 		default:
12418e709cbdSnorby 			errx(1, "unknown route type");
12428e709cbdSnorby 		}
12438e709cbdSnorby 		break;
12448e709cbdSnorby 	case IMSG_CTL_AREA:
12458e709cbdSnorby 		area = imsg->data;
12468e709cbdSnorby 		area_id = area->id;
12478e709cbdSnorby 		break;
12488e709cbdSnorby 	case IMSG_CTL_END:
12498e709cbdSnorby 		printf("\n");
12508e709cbdSnorby 		return (1);
12518e709cbdSnorby 	default:
12528e709cbdSnorby 		break;
12538e709cbdSnorby 	}
12548e709cbdSnorby 
12558e709cbdSnorby 	return (0);
12568e709cbdSnorby }
12578e709cbdSnorby 
12588e709cbdSnorby void
12598e709cbdSnorby show_fib_head(void)
12608e709cbdSnorby {
12618e709cbdSnorby 	printf("flags: * = valid, O = OSPF, C = Connected, S = Static\n");
1262afd0ab5dSfriehm 	printf("%-6s %-4s %-20s %-17s\n",
1263afd0ab5dSfriehm 	    "Flags", "Prio", "Destination", "Nexthop");
12648e709cbdSnorby }
12658e709cbdSnorby 
12668e709cbdSnorby int
12678e709cbdSnorby show_fib_msg(struct imsg *imsg)
12688e709cbdSnorby {
12698e709cbdSnorby 	struct kroute		*k;
12708e709cbdSnorby 	char			*p;
12718e709cbdSnorby 
12728e709cbdSnorby 	switch (imsg->hdr.type) {
12738e709cbdSnorby 	case IMSG_CTL_KROUTE:
12748e709cbdSnorby 		if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute))
12758e709cbdSnorby 			errx(1, "wrong imsg len");
12768e709cbdSnorby 		k = imsg->data;
12778e709cbdSnorby 
12788e709cbdSnorby 		if (k->flags & F_DOWN)
12798e709cbdSnorby 			printf(" ");
12808e709cbdSnorby 		else
12818e709cbdSnorby 			printf("*");
12828e709cbdSnorby 
12838e709cbdSnorby 		if (!(k->flags & F_KERNEL))
12848e709cbdSnorby 			printf("O");
12858e709cbdSnorby 		else if (k->flags & F_CONNECTED)
12868e709cbdSnorby 			printf("C");
12878e709cbdSnorby 		else if (k->flags & F_STATIC)
12888e709cbdSnorby 			printf("S");
12898e709cbdSnorby 		else
12908e709cbdSnorby 			printf(" ");
12918e709cbdSnorby 
12928e709cbdSnorby 		printf("     ");
1293afd0ab5dSfriehm 		printf("%4d ", k->priority);
12940104e403Sclaudio 		if (asprintf(&p, "%s/%u", log_in6addr(&k->prefix),
12950104e403Sclaudio 		    k->prefixlen) == -1)
12968e709cbdSnorby 			err(1, NULL);
12978e709cbdSnorby 		printf("%-20s ", p);
12988e709cbdSnorby 		free(p);
12998e709cbdSnorby 
13000104e403Sclaudio 		if (!IN6_IS_ADDR_UNSPECIFIED(&k->nexthop))
13015d8c2b7fSclaudio 			printf("%s", log_in6addr_scope(&k->nexthop, k->scope));
13028e709cbdSnorby 		else if (k->flags & F_CONNECTED)
13038e709cbdSnorby 			printf("link#%u", k->ifindex);
13048e709cbdSnorby 		printf("\n");
13058e709cbdSnorby 
13068e709cbdSnorby 		break;
13078e709cbdSnorby 	case IMSG_CTL_END:
13088e709cbdSnorby 		printf("\n");
13098e709cbdSnorby 		return (1);
13108e709cbdSnorby 	default:
13118e709cbdSnorby 		break;
13128e709cbdSnorby 	}
13138e709cbdSnorby 
13148e709cbdSnorby 	return (0);
13158e709cbdSnorby }
13168e709cbdSnorby 
13170f617141Sclaudio const struct if_status_description
13180f617141Sclaudio 		if_status_descriptions[] = LINK_STATE_DESCRIPTIONS;
13198e709cbdSnorby const struct ifmedia_description
13208e709cbdSnorby 		ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS;
13218e709cbdSnorby 
13228e709cbdSnorby const char *
1323e5605ae3Sderaadt get_media_descr(uint64_t media_type)
13248e709cbdSnorby {
13258e709cbdSnorby 	const struct ifmedia_description	*p;
13268e709cbdSnorby 
13278e709cbdSnorby 	for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++)
13288e709cbdSnorby 		if (media_type == p->ifmt_word)
13298e709cbdSnorby 			return (p->ifmt_string);
13308e709cbdSnorby 
13318e709cbdSnorby 	return ("unknown");
13328e709cbdSnorby }
13338e709cbdSnorby 
13348e709cbdSnorby const char *
133518ffdd94Sstsp get_linkstate(uint8_t if_type, int link_state)
13368e709cbdSnorby {
13370f617141Sclaudio 	const struct if_status_description *p;
13380f617141Sclaudio 	static char buf[8];
13398e709cbdSnorby 
13400f617141Sclaudio 	for (p = if_status_descriptions; p->ifs_string != NULL; p++) {
134118ffdd94Sstsp 		if (LINK_STATE_DESC_MATCH(p, if_type, link_state))
13420f617141Sclaudio 			return (p->ifs_string);
13438e709cbdSnorby 	}
13440f617141Sclaudio 	snprintf(buf, sizeof(buf), "[#%d]", link_state);
13450f617141Sclaudio 	return (buf);
13468e709cbdSnorby }
13478e709cbdSnorby 
13488e709cbdSnorby void
13498e709cbdSnorby print_baudrate(u_int64_t baudrate)
13508e709cbdSnorby {
13518e709cbdSnorby 	if (baudrate > IF_Gbps(1))
13528e709cbdSnorby 		printf("%llu GBit/s", baudrate / IF_Gbps(1));
13538e709cbdSnorby 	else if (baudrate > IF_Mbps(1))
13548e709cbdSnorby 		printf("%llu MBit/s", baudrate / IF_Mbps(1));
13558e709cbdSnorby 	else if (baudrate > IF_Kbps(1))
13568e709cbdSnorby 		printf("%llu KBit/s", baudrate / IF_Kbps(1));
13578e709cbdSnorby 	else
13588e709cbdSnorby 		printf("%llu Bit/s", baudrate);
13598e709cbdSnorby }
1360