xref: /openbsd/usr.sbin/ospfctl/ospfctl.c (revision 035b0708)
1*035b0708Sgilles /*	$OpenBSD: ospfctl.c,v 1.57 2013/04/09 14:51:33 gilles Exp $ */
2b49634deSclaudio 
3b49634deSclaudio /*
4b49634deSclaudio  * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
537355230Snorby  * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
6b49634deSclaudio  * Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
7b49634deSclaudio  *
8b49634deSclaudio  * Permission to use, copy, modify, and distribute this software for any
9b49634deSclaudio  * purpose with or without fee is hereby granted, provided that the above
10b49634deSclaudio  * copyright notice and this permission notice appear in all copies.
11b49634deSclaudio  *
12b49634deSclaudio  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13b49634deSclaudio  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14b49634deSclaudio  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15b49634deSclaudio  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16b49634deSclaudio  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17b49634deSclaudio  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18b49634deSclaudio  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19b49634deSclaudio  */
20b49634deSclaudio 
21b49634deSclaudio #include <sys/types.h>
22b49634deSclaudio #include <sys/socket.h>
23b49634deSclaudio #include <sys/un.h>
24b49634deSclaudio #include <netinet/in.h>
25b49634deSclaudio #include <arpa/inet.h>
26c47b7f65Sclaudio #include <net/if_media.h>
27c47b7f65Sclaudio #include <net/if_types.h>
28b49634deSclaudio 
29b49634deSclaudio #include <err.h>
30b49634deSclaudio #include <stdio.h>
31b49634deSclaudio #include <stdlib.h>
32b49634deSclaudio #include <string.h>
33b49634deSclaudio #include <unistd.h>
34b49634deSclaudio 
35b49634deSclaudio #include "ospf.h"
36b49634deSclaudio #include "ospfd.h"
37b49634deSclaudio #include "ospfe.h"
38b49634deSclaudio #include "parser.h"
39b49634deSclaudio 
40cbb557dbShenning __dead void	 usage(void);
4159df52c7Snorby int		 show_summary_msg(struct imsg *);
423caca30dSnorby int		 get_ifms_type(int);
43b49634deSclaudio int		 show_interface_msg(struct imsg *);
4412bb42a0Snorby int		 show_interface_detail_msg(struct imsg *);
45b49634deSclaudio const char	*print_link(int);
46b49634deSclaudio const char	*fmt_timeframe(time_t t);
47b49634deSclaudio const char	*fmt_timeframe_core(time_t t);
48b49634deSclaudio const char	*log_id(u_int32_t );
49b49634deSclaudio const char	*log_adv_rtr(u_int32_t);
5097494e25Sclaudio void		 show_database_head(struct in_addr, char *, u_int8_t);
51b49634deSclaudio int		 show_database_msg(struct imsg *);
5232286112Snorby char		*print_ls_type(u_int8_t);
5332286112Snorby void		 show_db_hdr_msg_detail(struct lsa_hdr *);
5432286112Snorby char		*print_rtr_link_type(u_int8_t);
5532286112Snorby const char	*print_ospf_flags(u_int8_t);
5632286112Snorby int		 show_db_msg_detail(struct imsg *imsg);
57b49634deSclaudio int		 show_nbr_msg(struct imsg *);
58b49634deSclaudio const char	*print_ospf_options(u_int8_t);
59b49634deSclaudio int		 show_nbr_detail_msg(struct imsg *);
6037355230Snorby int		 show_rib_msg(struct imsg *);
6137355230Snorby void		 show_rib_head(struct in_addr, u_int8_t, u_int8_t);
6291e3b0aeSnorby const char	*print_ospf_rtr_flags(u_int8_t);
6337355230Snorby int		 show_rib_detail_msg(struct imsg *);
64c47b7f65Sclaudio void		 show_fib_head(void);
65c47b7f65Sclaudio int		 show_fib_msg(struct imsg *);
66c47b7f65Sclaudio void		 show_interface_head(void);
67c47b7f65Sclaudio const char *	 get_media_descr(int);
68c47b7f65Sclaudio const char *	 get_linkstate(int, int);
6956babc06Sclaudio void		 print_baudrate(u_int64_t);
70c47b7f65Sclaudio int		 show_fib_interface_msg(struct imsg *);
71b49634deSclaudio 
72b49634deSclaudio struct imsgbuf	*ibuf;
73b49634deSclaudio 
74cbb557dbShenning __dead void
75b49634deSclaudio usage(void)
76b49634deSclaudio {
77b49634deSclaudio 	extern char *__progname;
78b49634deSclaudio 
79d1b94773Sreyk 	fprintf(stderr, "usage: %s [-s socket] command [argument ...]\n",
80d1b94773Sreyk 	    __progname);
81b49634deSclaudio 	exit(1);
82b49634deSclaudio }
83b49634deSclaudio 
84b49634deSclaudio int
85b49634deSclaudio main(int argc, char *argv[])
86b49634deSclaudio {
87b49634deSclaudio 	struct sockaddr_un	 sun;
88b49634deSclaudio 	struct parse_result	*res;
89b49634deSclaudio 	struct imsg		 imsg;
90b49634deSclaudio 	unsigned int		 ifidx = 0;
91b49634deSclaudio 	int			 ctl_sock;
92b49634deSclaudio 	int			 done = 0;
93c3319070Sclaudio 	int			 n, verbose = 0;
94d1b94773Sreyk 	int			 ch;
95d1b94773Sreyk 	char			*sockname;
96d1b94773Sreyk 
97d1b94773Sreyk 	sockname = OSPFD_SOCKET;
98d1b94773Sreyk 	while ((ch = getopt(argc, argv, "s:")) != -1) {
99d1b94773Sreyk 		switch (ch) {
100d1b94773Sreyk 		case 's':
101d1b94773Sreyk 			sockname = optarg;
102d1b94773Sreyk 			break;
103d1b94773Sreyk 		default:
104d1b94773Sreyk 			usage();
105d1b94773Sreyk 			/* NOTREACHED */
106d1b94773Sreyk 		}
107d1b94773Sreyk 	}
108d1b94773Sreyk 	argc -= optind;
109d1b94773Sreyk 	argv += optind;
110b49634deSclaudio 
111b49634deSclaudio 	/* parse options */
112d1b94773Sreyk 	if ((res = parse(argc, argv)) == NULL)
113b49634deSclaudio 		exit(1);
114b49634deSclaudio 
115b49634deSclaudio 	/* connect to ospfd control socket */
116b49634deSclaudio 	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
117b49634deSclaudio 		err(1, "socket");
118b49634deSclaudio 
119b49634deSclaudio 	bzero(&sun, sizeof(sun));
120b49634deSclaudio 	sun.sun_family = AF_UNIX;
121d1b94773Sreyk 
122d1b94773Sreyk 	strlcpy(sun.sun_path, sockname, sizeof(sun.sun_path));
123b49634deSclaudio 	if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1)
124d1b94773Sreyk 		err(1, "connect: %s", sockname);
125b49634deSclaudio 
126b49634deSclaudio 	if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
127d2141824Sstevesk 		err(1, NULL);
1287b4c0c10Seric 	imsg_init(ibuf, ctl_sock);
129b49634deSclaudio 	done = 0;
130b49634deSclaudio 
131b49634deSclaudio 	/* process user request */
132b49634deSclaudio 	switch (res->action) {
133b49634deSclaudio 	case NONE:
134b49634deSclaudio 		usage();
135b49634deSclaudio 		/* not reached */
136b49634deSclaudio 	case SHOW:
13759df52c7Snorby 	case SHOW_SUM:
1387f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_SUM, 0, 0, -1, NULL, 0);
139b49634deSclaudio 		break;
140b49634deSclaudio 	case SHOW_IFACE:
14112bb42a0Snorby 		printf("%-11s %-18s %-6s %-10s %-10s %-8s %3s %3s\n",
14212bb42a0Snorby 		    "Interface", "Address", "State", "HelloTimer", "Linkstate",
14312bb42a0Snorby 		    "Uptime", "nc", "ac");
144c5ba8b41Sderaadt 		/*FALLTHROUGH*/
14512bb42a0Snorby 	case SHOW_IFACE_DTAIL:
146b49634deSclaudio 		if (*res->ifname) {
147b49634deSclaudio 			ifidx = if_nametoindex(res->ifname);
148b49634deSclaudio 			if (ifidx == 0)
149b49634deSclaudio 				errx(1, "no such interface %s", res->ifname);
150b49634deSclaudio 		}
1517f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1,
152b49634deSclaudio 		    &ifidx, sizeof(ifidx));
153b49634deSclaudio 		break;
154b49634deSclaudio 	case SHOW_NBR:
155129e6b5fSnorby 		printf("%-15s %-3s %-12s %-8s %-15s %-9s %s\n", "ID", "Pri",
156129e6b5fSnorby 		    "State", "DeadTime", "Address", "Iface","Uptime");
157c5ba8b41Sderaadt 		/*FALLTHROUGH*/
158b49634deSclaudio 	case SHOW_NBR_DTAIL:
1597f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0);
160b49634deSclaudio 		break;
161b49634deSclaudio 	case SHOW_DB:
1627f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1, NULL, 0);
163b49634deSclaudio 		break;
164b49634deSclaudio 	case SHOW_DBBYAREA:
1657f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1,
166b49634deSclaudio 		    &res->addr, sizeof(res->addr));
167b49634deSclaudio 		break;
16832286112Snorby 	case SHOW_DBEXT:
1697f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_EXT, 0, 0, -1, NULL, 0);
17032286112Snorby 		break;
17132286112Snorby 	case SHOW_DBNET:
1727f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_NET, 0, 0, -1, NULL, 0);
17332286112Snorby 		break;
17432286112Snorby 	case SHOW_DBRTR:
1757f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_RTR, 0, 0, -1, NULL, 0);
17632286112Snorby 		break;
17732286112Snorby 	case SHOW_DBSELF:
1787f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SELF, 0, 0, -1, NULL, 0);
17932286112Snorby 		break;
18032286112Snorby 	case SHOW_DBSUM:
1817f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SUM, 0, 0, -1, NULL, 0);
18232286112Snorby 		break;
18332286112Snorby 	case SHOW_DBASBR:
1847f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_ASBR, 0, 0, -1, NULL, 0);
18532286112Snorby 		break;
18697494e25Sclaudio 	case SHOW_DBOPAQ:
18797494e25Sclaudio 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_OPAQ, 0, 0, -1, NULL, 0);
18897494e25Sclaudio 		break;
18937355230Snorby 	case SHOW_RIB:
1907aa44f3cSnorby 		printf("%-20s %-17s %-12s %-9s %-7s %-8s\n", "Destination",
1917aa44f3cSnorby 		    "Nexthop", "Path Type", "Type", "Cost", "Uptime");
192c5ba8b41Sderaadt 		/*FALLTHROUGH*/
19337355230Snorby 	case SHOW_RIB_DTAIL:
1947f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, -1, NULL, 0);
19537355230Snorby 		break;
196c47b7f65Sclaudio 	case SHOW_FIB:
197c47b7f65Sclaudio 		if (!res->addr.s_addr)
1987f472484Spyr 			imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0, -1,
199c47b7f65Sclaudio 			    &res->flags, sizeof(res->flags));
200c47b7f65Sclaudio 		else
2017f472484Spyr 			imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1,
202c47b7f65Sclaudio 			    &res->addr, sizeof(res->addr));
203c47b7f65Sclaudio 		show_fib_head();
204c47b7f65Sclaudio 		break;
205c47b7f65Sclaudio 	case SHOW_FIB_IFACE:
2064c561fb6Sclaudio 		if (*res->ifname)
2077f472484Spyr 			imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1,
2084c561fb6Sclaudio 			    res->ifname, sizeof(res->ifname));
2094c561fb6Sclaudio 		else
2107f472484Spyr 			imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1, NULL, 0);
211c47b7f65Sclaudio 		show_interface_head();
212c47b7f65Sclaudio 		break;
21373a141beSclaudio 	case FIB:
21473a141beSclaudio 		errx(1, "fib couple|decouple");
21573a141beSclaudio 		break;
21673a141beSclaudio 	case FIB_COUPLE:
2177f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, -1, NULL, 0);
21873a141beSclaudio 		printf("couple request sent.\n");
21973a141beSclaudio 		done = 1;
22073a141beSclaudio 		break;
22173a141beSclaudio 	case FIB_DECOUPLE:
2227f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, -1, NULL, 0);
22373a141beSclaudio 		printf("decouple request sent.\n");
22473a141beSclaudio 		done = 1;
22573a141beSclaudio 		break;
226119f0f1dSdlg 	case FIB_RELOAD:
227119f0f1dSdlg 		imsg_compose(ibuf, IMSG_CTL_FIB_RELOAD, 0, 0, -1, NULL, 0);
228119f0f1dSdlg 		printf("reload request sent.\n");
229119f0f1dSdlg 		done = 1;
230119f0f1dSdlg 		break;
231c3319070Sclaudio 	case LOG_VERBOSE:
232c3319070Sclaudio 		verbose = 1;
233c3319070Sclaudio 		/* FALLTHROUGH */
234c3319070Sclaudio 	case LOG_BRIEF:
235c3319070Sclaudio 		imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1,
236c3319070Sclaudio 		    &verbose, sizeof(verbose));
237c3319070Sclaudio 		printf("logging request sent.\n");
238c3319070Sclaudio 		done = 1;
239c3319070Sclaudio 		break;
240b49634deSclaudio 	case RELOAD:
2417f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0);
242b49634deSclaudio 		printf("reload request sent.\n");
243b49634deSclaudio 		done = 1;
244b49634deSclaudio 		break;
245b49634deSclaudio 	}
246b49634deSclaudio 
247b49634deSclaudio 	while (ibuf->w.queued)
248b49634deSclaudio 		if (msgbuf_write(&ibuf->w) < 0)
249b49634deSclaudio 			err(1, "write error");
250b49634deSclaudio 
251b49634deSclaudio 	while (!done) {
252b49634deSclaudio 		if ((n = imsg_read(ibuf)) == -1)
253b49634deSclaudio 			errx(1, "imsg_read error");
254b49634deSclaudio 		if (n == 0)
255b49634deSclaudio 			errx(1, "pipe closed");
256b49634deSclaudio 
257b49634deSclaudio 		while (!done) {
258b49634deSclaudio 			if ((n = imsg_get(ibuf, &imsg)) == -1)
259b49634deSclaudio 				errx(1, "imsg_get error");
260b49634deSclaudio 			if (n == 0)
261b49634deSclaudio 				break;
262b49634deSclaudio 			switch (res->action) {
263b49634deSclaudio 			case SHOW:
26459df52c7Snorby 			case SHOW_SUM:
26559df52c7Snorby 				done = show_summary_msg(&imsg);
266b49634deSclaudio 				break;
267b49634deSclaudio 			case SHOW_IFACE:
268b49634deSclaudio 				done = show_interface_msg(&imsg);
269b49634deSclaudio 				break;
27012bb42a0Snorby 			case SHOW_IFACE_DTAIL:
27112bb42a0Snorby 				done = show_interface_detail_msg(&imsg);
27212bb42a0Snorby 				break;
273b49634deSclaudio 			case SHOW_NBR:
274b49634deSclaudio 				done = show_nbr_msg(&imsg);
275b49634deSclaudio 				break;
276b49634deSclaudio 			case SHOW_NBR_DTAIL:
277b49634deSclaudio 				done = show_nbr_detail_msg(&imsg);
278b49634deSclaudio 				break;
279b49634deSclaudio 			case SHOW_DB:
280b49634deSclaudio 			case SHOW_DBBYAREA:
28132286112Snorby 			case SHOW_DBSELF:
282b49634deSclaudio 				done = show_database_msg(&imsg);
283b49634deSclaudio 				break;
28432286112Snorby 			case SHOW_DBEXT:
28532286112Snorby 			case SHOW_DBNET:
28632286112Snorby 			case SHOW_DBRTR:
28732286112Snorby 			case SHOW_DBSUM:
28832286112Snorby 			case SHOW_DBASBR:
28997494e25Sclaudio 			case SHOW_DBOPAQ:
29032286112Snorby 				done = show_db_msg_detail(&imsg);
29132286112Snorby 				break;
29237355230Snorby 			case SHOW_RIB:
29337355230Snorby 				done = show_rib_msg(&imsg);
29437355230Snorby 				break;
29537355230Snorby 			case SHOW_RIB_DTAIL:
29637355230Snorby 				done = show_rib_detail_msg(&imsg);
29737355230Snorby 				break;
298c47b7f65Sclaudio 			case SHOW_FIB:
299c47b7f65Sclaudio 				done = show_fib_msg(&imsg);
300c47b7f65Sclaudio 				break;
301c47b7f65Sclaudio 			case SHOW_FIB_IFACE:
302c47b7f65Sclaudio 				done = show_fib_interface_msg(&imsg);
303c47b7f65Sclaudio 				break;
304b49634deSclaudio 			case NONE:
30573a141beSclaudio 			case FIB:
30673a141beSclaudio 			case FIB_COUPLE:
30773a141beSclaudio 			case FIB_DECOUPLE:
308119f0f1dSdlg 			case FIB_RELOAD:
309c3319070Sclaudio 			case LOG_VERBOSE:
310c3319070Sclaudio 			case LOG_BRIEF:
311b49634deSclaudio 			case RELOAD:
312b49634deSclaudio 				break;
313b49634deSclaudio 			}
314b49634deSclaudio 			imsg_free(&imsg);
315b49634deSclaudio 		}
316b49634deSclaudio 	}
317b49634deSclaudio 	close(ctl_sock);
318b49634deSclaudio 	free(ibuf);
319b49634deSclaudio 
320b49634deSclaudio 	return (0);
321b49634deSclaudio }
322b49634deSclaudio 
323b49634deSclaudio int
32459df52c7Snorby show_summary_msg(struct imsg *imsg)
325b49634deSclaudio {
32659df52c7Snorby 	struct ctl_sum		*sum;
32759df52c7Snorby 	struct ctl_sum_area	*sumarea;
32859df52c7Snorby 
32959df52c7Snorby 	switch (imsg->hdr.type) {
33059df52c7Snorby 	case IMSG_CTL_SHOW_SUM:
33159df52c7Snorby 		sum = imsg->data;
33259df52c7Snorby 		printf("Router ID: %s\n", inet_ntoa(sum->rtr_id));
33311c16ffaSnorby 		printf("Uptime: %s\n", fmt_timeframe_core(sum->uptime));
33459df52c7Snorby 		printf("RFC1583 compatibility flag is ");
33559df52c7Snorby 		if (sum->rfc1583compat)
33659df52c7Snorby 			printf("enabled\n");
33759df52c7Snorby 		else
33859df52c7Snorby 			printf("disabled\n");
33959df52c7Snorby 
34037877ca4Sdlg 		printf("SPF delay is %d msec(s), hold time between two SPFs "
34137877ca4Sdlg 		    "is %d msec(s)\n", sum->spf_delay, sum->spf_hold_time);
3420439e4c8Sclaudio 		printf("Number of external LSA(s) %d (Checksum sum 0x%x)\n",
3430439e4c8Sclaudio 		    sum->num_ext_lsa, sum->ext_lsa_cksum);
34459df52c7Snorby 		printf("Number of areas attached to this router: %d\n",
34559df52c7Snorby 		    sum->num_area);
34659df52c7Snorby 		break;
34759df52c7Snorby 	case IMSG_CTL_SHOW_SUM_AREA:
34859df52c7Snorby 		sumarea = imsg->data;
34959df52c7Snorby 		printf("\nArea ID: %s\n", inet_ntoa(sumarea->area));
35059df52c7Snorby 		printf("  Number of interfaces in this area: %d\n",
35159df52c7Snorby 		    sumarea->num_iface);
35259df52c7Snorby 		printf("  Number of fully adjacent neighbors in this "
35359df52c7Snorby 		    "area: %d\n", sumarea->num_adj_nbr);
35459df52c7Snorby 		printf("  SPF algorithm executed %d time(s)\n",
35559df52c7Snorby 		    sumarea->num_spf_calc);
3560439e4c8Sclaudio 		printf("  Number LSA(s) %d (Checksum sum 0x%x)\n",
3570439e4c8Sclaudio 		    sumarea->num_lsa, sumarea->lsa_cksum);
35859df52c7Snorby 		break;
35959df52c7Snorby 	case IMSG_CTL_END:
36059df52c7Snorby 		printf("\n");
36159df52c7Snorby 		return (1);
36259df52c7Snorby 	default:
36359df52c7Snorby 		break;
36459df52c7Snorby 	}
365b49634deSclaudio 
366b49634deSclaudio 	return (0);
367b49634deSclaudio }
368b49634deSclaudio 
369b49634deSclaudio int
3703caca30dSnorby get_ifms_type(int mediatype)
3713caca30dSnorby {
3723caca30dSnorby 	switch (mediatype) {
3733caca30dSnorby 	case IFT_ETHER:
3743caca30dSnorby 		return (IFM_ETHER);
3753caca30dSnorby 	case IFT_FDDI:
3763caca30dSnorby 		return (IFM_FDDI);
3773caca30dSnorby 	case IFT_CARP:
3783caca30dSnorby 		return (IFM_CARP);
379a5bcf77aSclaudio 	case IFT_PPP:
380a5bcf77aSclaudio 		return (IFM_TDM);
3813caca30dSnorby 	default:
3823caca30dSnorby 		return (0);
3833caca30dSnorby 	}
3843caca30dSnorby }
3853caca30dSnorby 
3863caca30dSnorby int
387b49634deSclaudio show_interface_msg(struct imsg *imsg)
388b49634deSclaudio {
389b49634deSclaudio 	struct ctl_iface	*iface;
39012bb42a0Snorby 	char			*netid;
39112bb42a0Snorby 
39212bb42a0Snorby 	switch (imsg->hdr.type) {
39312bb42a0Snorby 	case IMSG_CTL_SHOW_INTERFACE:
39412bb42a0Snorby 		iface = imsg->data;
39512bb42a0Snorby 
39612bb42a0Snorby 		if (asprintf(&netid, "%s/%d", inet_ntoa(iface->addr),
39712bb42a0Snorby 		    mask2prefixlen(iface->mask.s_addr)) == -1)
39812bb42a0Snorby 			err(1, NULL);
39912bb42a0Snorby 		printf("%-11s %-18s %-6s %-10s %-10s %s %3d %3d\n",
40012bb42a0Snorby 		    iface->name, netid, if_state_name(iface->state),
4017afdfd2dSdlg 		    iface->hello_timer.tv_sec < 0 ? "-" :
4027afdfd2dSdlg 		    fmt_timeframe_core(iface->hello_timer.tv_sec),
4030f617141Sclaudio 		    get_linkstate(iface->mediatype, iface->linkstate),
4040f617141Sclaudio 		    fmt_timeframe_core(iface->uptime),
40511c16ffaSnorby 		    iface->nbr_cnt, iface->adj_cnt);
40612bb42a0Snorby 		free(netid);
40712bb42a0Snorby 		break;
40812bb42a0Snorby 	case IMSG_CTL_END:
40912bb42a0Snorby 		printf("\n");
41012bb42a0Snorby 		return (1);
41112bb42a0Snorby 	default:
41212bb42a0Snorby 		break;
41312bb42a0Snorby 	}
41412bb42a0Snorby 
41512bb42a0Snorby 	return (0);
41612bb42a0Snorby }
41712bb42a0Snorby 
41812bb42a0Snorby int
41912bb42a0Snorby show_interface_detail_msg(struct imsg *imsg)
42012bb42a0Snorby {
42112bb42a0Snorby 	struct ctl_iface	*iface;
422b49634deSclaudio 
423b49634deSclaudio 	switch (imsg->hdr.type) {
424b49634deSclaudio 	case IMSG_CTL_SHOW_INTERFACE:
425b49634deSclaudio 		iface = imsg->data;
426b49634deSclaudio 		printf("\n");
4273caca30dSnorby 		printf("Interface %s, line protocol is %s\n",
4283caca30dSnorby 		    iface->name, print_link(iface->flags));
429b49634deSclaudio 		printf("  Internet address %s/%d, ",
430b49634deSclaudio 		    inet_ntoa(iface->addr),
4313ec0d80eSclaudio 		    mask2prefixlen(iface->mask.s_addr));
432b49634deSclaudio 		printf("Area %s\n", inet_ntoa(iface->area));
4333caca30dSnorby 		printf("  Linkstate %s\n",
4340f617141Sclaudio 		    get_linkstate(iface->mediatype, iface->linkstate));
435b49634deSclaudio 		printf("  Router ID %s, network type %s, cost: %d\n",
436b49634deSclaudio 		    inet_ntoa(iface->rtr_id),
4379ac7929fSclaudio 		    if_type_name(iface->type), iface->metric);
43859df52c7Snorby 		printf("  Transmit delay is %d sec(s), state %s, priority %d\n",
4399ac7929fSclaudio 		    iface->transmit_delay, if_state_name(iface->state),
440b49634deSclaudio 		    iface->priority);
441b49634deSclaudio 		printf("  Designated Router (ID) %s, ",
442b49634deSclaudio 		    inet_ntoa(iface->dr_id));
443b49634deSclaudio 		printf("interface address %s\n", inet_ntoa(iface->dr_addr));
444b49634deSclaudio 		printf("  Backup Designated Router (ID) %s, ",
445b49634deSclaudio 		    inet_ntoa(iface->bdr_id));
446b49634deSclaudio 		printf("interface address %s\n", inet_ntoa(iface->bdr_addr));
4477afdfd2dSdlg 		if (iface->dead_interval == FAST_RTR_DEAD_TIME) {
4487afdfd2dSdlg 			printf("  Timer intervals configured, "
4497afdfd2dSdlg 			    "hello %d msec, dead %d, wait %d, retransmit %d\n",
4507afdfd2dSdlg 			     iface->fast_hello_interval, iface->dead_interval,
4517afdfd2dSdlg 			     iface->dead_interval, iface->rxmt_interval);
4527afdfd2dSdlg 
4537afdfd2dSdlg 		} else {
454b49634deSclaudio 			printf("  Timer intervals configured, "
455b49634deSclaudio 			    "hello %d, dead %d, wait %d, retransmit %d\n",
456b49634deSclaudio 			     iface->hello_interval, iface->dead_interval,
457b49634deSclaudio 			     iface->dead_interval, iface->rxmt_interval);
4587afdfd2dSdlg 		}
459a68e4c86Sstevesk 		if (iface->passive)
460a68e4c86Sstevesk 			printf("    Passive interface (No Hellos)\n");
4617afdfd2dSdlg 		else if (iface->hello_timer.tv_sec < 0)
462b49634deSclaudio 			printf("    Hello timer not running\n");
463b49634deSclaudio 		else
4647afdfd2dSdlg 			printf("    Hello timer due in %s+%ldmsec\n",
4657afdfd2dSdlg 			    fmt_timeframe_core(iface->hello_timer.tv_sec),
4667afdfd2dSdlg 			    iface->hello_timer.tv_usec / 1000);
46711c16ffaSnorby 		printf("    Uptime %s\n", fmt_timeframe_core(iface->uptime));
468b49634deSclaudio 		printf("  Neighbor count is %d, adjacent neighbor count is "
469b49634deSclaudio 		    "%d\n", iface->nbr_cnt, iface->adj_cnt);
470a4aef966Smsf 		if (iface->auth_type > 0) {
471a4aef966Smsf 			switch (iface->auth_type) {
472a4aef966Smsf 			case AUTH_SIMPLE:
473a4aef966Smsf 				printf("  Simple password authentication "
474a4aef966Smsf 				    "enabled\n");
4759b01acb5Sstevesk 				break;
476a4aef966Smsf 			case AUTH_CRYPT:
477a4aef966Smsf 				printf("  Message digest authentication "
478a4aef966Smsf 				    "enabled\n");
479a4aef966Smsf 				printf("    Primary key id is %d\n",
480a4aef966Smsf 				    iface->auth_keyid);
4819b01acb5Sstevesk 				break;
482a4aef966Smsf 			default:
483a4aef966Smsf 				break;
484a4aef966Smsf 			}
485a4aef966Smsf 		}
486b49634deSclaudio 		break;
487b49634deSclaudio 	case IMSG_CTL_END:
488b49634deSclaudio 		printf("\n");
489b49634deSclaudio 		return (1);
490b49634deSclaudio 	default:
491b49634deSclaudio 		break;
492b49634deSclaudio 	}
493b49634deSclaudio 
494b49634deSclaudio 	return (0);
495b49634deSclaudio }
496b49634deSclaudio 
497b49634deSclaudio const char *
498b49634deSclaudio print_link(int state)
499b49634deSclaudio {
500b49634deSclaudio 	if (state & IFF_UP)
501b49634deSclaudio 		return ("UP");
502b49634deSclaudio 	else
503b49634deSclaudio 		return ("DOWN");
504b49634deSclaudio }
505b49634deSclaudio 
506b49634deSclaudio #define TF_BUFS	8
507b49634deSclaudio #define TF_LEN	9
508b49634deSclaudio 
509b49634deSclaudio const char *
510b49634deSclaudio fmt_timeframe(time_t t)
511b49634deSclaudio {
512b49634deSclaudio 	if (t == 0)
513b49634deSclaudio 		return ("Never");
514b49634deSclaudio 	else
515b49634deSclaudio 		return (fmt_timeframe_core(time(NULL) - t));
516b49634deSclaudio }
517b49634deSclaudio 
518b49634deSclaudio const char *
519b49634deSclaudio fmt_timeframe_core(time_t t)
520b49634deSclaudio {
521b49634deSclaudio 	char		*buf;
522b49634deSclaudio 	static char	 tfbuf[TF_BUFS][TF_LEN];	/* ring buffer */
523b49634deSclaudio 	static int	 idx = 0;
524*035b0708Sgilles 	unsigned int	 sec, min, hrs, day;
525*035b0708Sgilles 	unsigned long long	week;
526b49634deSclaudio 
527b49634deSclaudio 	if (t == 0)
52811c16ffaSnorby 		return ("00:00:00");
529b49634deSclaudio 
530b49634deSclaudio 	buf = tfbuf[idx++];
531b49634deSclaudio 	if (idx == TF_BUFS)
532b49634deSclaudio 		idx = 0;
533b49634deSclaudio 
534b49634deSclaudio 	week = t;
535b49634deSclaudio 
536b49634deSclaudio 	sec = week % 60;
537b49634deSclaudio 	week /= 60;
538b49634deSclaudio 	min = week % 60;
539b49634deSclaudio 	week /= 60;
540b49634deSclaudio 	hrs = week % 24;
541b49634deSclaudio 	week /= 24;
542b49634deSclaudio 	day = week % 7;
543b49634deSclaudio 	week /= 7;
544b49634deSclaudio 
545b49634deSclaudio 	if (week > 0)
546*035b0708Sgilles 		snprintf(buf, TF_LEN, "%02lluw%01ud%02uh", week, day, hrs);
547b49634deSclaudio 	else if (day > 0)
548b49634deSclaudio 		snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
549b49634deSclaudio 	else
550b49634deSclaudio 		snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
551b49634deSclaudio 
552b49634deSclaudio 	return (buf);
553b49634deSclaudio }
554b49634deSclaudio 
555b49634deSclaudio const char *
556b49634deSclaudio log_id(u_int32_t id)
557b49634deSclaudio {
558b49634deSclaudio 	static char	buf[48];
559b49634deSclaudio 	struct in_addr	addr;
560b49634deSclaudio 
561b49634deSclaudio 	addr.s_addr = id;
562b49634deSclaudio 
563b49634deSclaudio 	if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL)
564b49634deSclaudio 		return ("?");
565b49634deSclaudio 	else
566b49634deSclaudio 		return (buf);
567b49634deSclaudio }
568b49634deSclaudio 
569b49634deSclaudio const char *
570b49634deSclaudio log_adv_rtr(u_int32_t adv_rtr)
571b49634deSclaudio {
572b49634deSclaudio 	static char	buf[48];
573b49634deSclaudio 	struct in_addr	addr;
574b49634deSclaudio 
575b49634deSclaudio 	addr.s_addr = adv_rtr;
576b49634deSclaudio 
577b49634deSclaudio 	if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL)
578b49634deSclaudio 		return ("?");
579b49634deSclaudio 	else
580b49634deSclaudio 		return (buf);
581b49634deSclaudio }
582b49634deSclaudio 
5833ec0d80eSclaudio /* prototype defined in ospfd.h and shared with the kroute.c version */
584b49634deSclaudio u_int8_t
5853ec0d80eSclaudio mask2prefixlen(in_addr_t ina)
586b49634deSclaudio {
5873ec0d80eSclaudio 	if (ina == 0)
588b49634deSclaudio 		return (0);
589b49634deSclaudio 	else
5903ec0d80eSclaudio 		return (33 - ffs(ntohl(ina)));
591b49634deSclaudio }
592b49634deSclaudio 
593b49634deSclaudio void
59497494e25Sclaudio show_database_head(struct in_addr aid, char *ifname, u_int8_t type)
595b49634deSclaudio {
596b49634deSclaudio 	char	*header, *format;
59797494e25Sclaudio 	int	 cleanup = 0;
598b49634deSclaudio 
599b49634deSclaudio 	switch (type) {
600b49634deSclaudio 	case LSA_TYPE_ROUTER:
601b49634deSclaudio 		format = "Router Link States";
602b49634deSclaudio 		break;
603b49634deSclaudio 	case LSA_TYPE_NETWORK:
604b49634deSclaudio 		format = "Net Link States";
605b49634deSclaudio 		break;
606b49634deSclaudio 	case LSA_TYPE_SUM_NETWORK:
607b49634deSclaudio 		format = "Summary Net Link States";
608b49634deSclaudio 		break;
609b49634deSclaudio 	case LSA_TYPE_SUM_ROUTER:
610b49634deSclaudio 		format = "Summary Router Link States";
611b49634deSclaudio 		break;
612b49634deSclaudio 	case LSA_TYPE_EXTERNAL:
613b49634deSclaudio 		format = NULL;
614b49634deSclaudio 		if ((header = strdup("Type-5 AS External Link States")) == NULL)
615b49634deSclaudio 			err(1, NULL);
616b49634deSclaudio 		break;
61797494e25Sclaudio 	case LSA_TYPE_LINK_OPAQ:
61897494e25Sclaudio 		format = "Type-9 Link Local Opaque Link States";
61997494e25Sclaudio 		break;
62097494e25Sclaudio 	case LSA_TYPE_AREA_OPAQ:
62197494e25Sclaudio 		format = "Type-10 Area Local Opaque Link States";
62297494e25Sclaudio 		break;
62397494e25Sclaudio 	case LSA_TYPE_AS_OPAQ:
62497494e25Sclaudio 		format = NULL;
62597494e25Sclaudio 		if ((header = strdup("Type-11 AS Wide Opaque Link States")) ==
62697494e25Sclaudio 		    NULL)
62797494e25Sclaudio 			err(1, NULL);
62897494e25Sclaudio 		break;
629b49634deSclaudio 	default:
63097494e25Sclaudio 		if (asprintf(&format, "LSA type %x", ntohs(type)) == -1)
63197494e25Sclaudio 			err(1, NULL);
63297494e25Sclaudio 		cleanup = 1;
63397494e25Sclaudio 		break;
634b49634deSclaudio 	}
63597494e25Sclaudio 	if (type == LSA_TYPE_LINK_OPAQ) {
63697494e25Sclaudio 		if (asprintf(&header, "%s (Area %s Interface %s)", format,
63797494e25Sclaudio 		    inet_ntoa(aid), ifname) == -1)
63897494e25Sclaudio 			err(1, NULL);
63997494e25Sclaudio 	} else if (type != LSA_TYPE_EXTERNAL && type != LSA_TYPE_AS_OPAQ)
640b49634deSclaudio 		if (asprintf(&header, "%s (Area %s)", format,
641b49634deSclaudio 		    inet_ntoa(aid)) == -1)
642b49634deSclaudio 			err(1, NULL);
643b49634deSclaudio 
64432286112Snorby 	printf("\n%-15s %s\n\n", "", header);
645b49634deSclaudio 	free(header);
64697494e25Sclaudio 	if (cleanup)
64797494e25Sclaudio 		free(format);
648b49634deSclaudio }
649b49634deSclaudio 
650b49634deSclaudio int
651b49634deSclaudio show_database_msg(struct imsg *imsg)
652b49634deSclaudio {
653b49634deSclaudio 	static struct in_addr	 area_id;
65497494e25Sclaudio 	static char		 ifname[IF_NAMESIZE];
655b49634deSclaudio 	static u_int8_t		 lasttype;
656b49634deSclaudio 	struct area		*area;
65797494e25Sclaudio 	struct iface		*iface;
658b49634deSclaudio 	struct lsa_hdr		*lsa;
659b49634deSclaudio 
660b49634deSclaudio 	switch (imsg->hdr.type) {
661b49634deSclaudio 	case IMSG_CTL_SHOW_DATABASE:
66232286112Snorby 	case IMSG_CTL_SHOW_DB_SELF:
663b49634deSclaudio 		lsa = imsg->data;
66432286112Snorby 		if (lsa->type != lasttype) {
66597494e25Sclaudio 			show_database_head(area_id, ifname, lsa->type);
66632286112Snorby 			printf("%-15s %-15s %-4s %-10s %-8s\n", "Link ID",
66732286112Snorby 			    "Adv Router", "Age", "Seq#", "Checksum");
66832286112Snorby 		}
669b49634deSclaudio 		printf("%-15s %-15s %-4d 0x%08x 0x%04x\n",
670b49634deSclaudio 		    log_id(lsa->ls_id), log_adv_rtr(lsa->adv_rtr),
671b49634deSclaudio 		    ntohs(lsa->age), ntohl(lsa->seq_num),
672b49634deSclaudio 		    ntohs(lsa->ls_chksum));
673b49634deSclaudio 		lasttype = lsa->type;
674b49634deSclaudio 		break;
675b49634deSclaudio 	case IMSG_CTL_AREA:
676b49634deSclaudio 		area = imsg->data;
677b49634deSclaudio 		area_id = area->id;
67843dbf367Snorby 		lasttype = 0;
679b49634deSclaudio 		break;
68097494e25Sclaudio 	case IMSG_CTL_IFACE:
68197494e25Sclaudio 		iface = imsg->data;
68297494e25Sclaudio 		strlcpy(ifname, iface->name, sizeof(ifname));
68397494e25Sclaudio 		lasttype = 0;
68497494e25Sclaudio 		break;
685b49634deSclaudio 	case IMSG_CTL_END:
68632286112Snorby 		printf("\n");
68732286112Snorby 		return (1);
68832286112Snorby 	default:
68932286112Snorby 		break;
69032286112Snorby 	}
69132286112Snorby 
69232286112Snorby 	return (0);
69332286112Snorby }
69432286112Snorby 
69532286112Snorby char *
69632286112Snorby print_ls_type(u_int8_t type)
69732286112Snorby {
69832286112Snorby 	switch (type) {
69932286112Snorby 	case LSA_TYPE_ROUTER:
70032286112Snorby 		return ("Router");
70132286112Snorby 	case LSA_TYPE_NETWORK:
70232286112Snorby 		return ("Network");
70332286112Snorby 	case LSA_TYPE_SUM_NETWORK:
70432286112Snorby 		return ("Summary (Network)");
70532286112Snorby 	case LSA_TYPE_SUM_ROUTER:
70632286112Snorby 		return ("Summary (Router)");
70732286112Snorby 	case LSA_TYPE_EXTERNAL:
70832286112Snorby 		return ("AS External");
70997494e25Sclaudio 	case LSA_TYPE_LINK_OPAQ:
71097494e25Sclaudio 		return ("Type-9 Opaque");
71197494e25Sclaudio 	case LSA_TYPE_AREA_OPAQ:
71297494e25Sclaudio 		return ("Type-10 Opaque");
71397494e25Sclaudio 	case LSA_TYPE_AS_OPAQ:
71497494e25Sclaudio 		return ("Type-11 Opaque");
71532286112Snorby 	default:
71632286112Snorby 		return ("Unknown");
71732286112Snorby 	}
71832286112Snorby }
71932286112Snorby 
72032286112Snorby void
72132286112Snorby show_db_hdr_msg_detail(struct lsa_hdr *lsa)
72232286112Snorby {
72332286112Snorby 	printf("LS age: %d\n", ntohs(lsa->age));
72432286112Snorby 	printf("Options: %s\n", print_ospf_options(lsa->opts));
72532286112Snorby 	printf("LS Type: %s\n", print_ls_type(lsa->type));
72632286112Snorby 
72732286112Snorby 	switch (lsa->type) {
72832286112Snorby 	case LSA_TYPE_ROUTER:
72932286112Snorby 		printf("Link State ID: %s\n", log_id(lsa->ls_id));
73032286112Snorby 		break;
73132286112Snorby 	case LSA_TYPE_NETWORK:
73232286112Snorby 		printf("Link State ID: %s (address of Designated Router)\n",
73332286112Snorby 		    log_id(lsa->ls_id));
73432286112Snorby 		break;
73532286112Snorby 	case LSA_TYPE_SUM_NETWORK:
73632286112Snorby 		printf("Link State ID: %s (Network ID)\n", log_id(lsa->ls_id));
73732286112Snorby 		break;
73832286112Snorby 	case LSA_TYPE_SUM_ROUTER:
73932286112Snorby 		printf("Link State ID: %s (ASBR Router ID)\n",
74032286112Snorby 		    log_id(lsa->ls_id));
74132286112Snorby 		break;
74232286112Snorby 	case LSA_TYPE_EXTERNAL:
74332286112Snorby 		printf("Link State ID: %s (External Network Number)\n",
74432286112Snorby 		     log_id(lsa->ls_id));
74532286112Snorby 		break;
74697494e25Sclaudio 	case LSA_TYPE_LINK_OPAQ:
74797494e25Sclaudio 	case LSA_TYPE_AREA_OPAQ:
74897494e25Sclaudio 	case LSA_TYPE_AS_OPAQ:
74997494e25Sclaudio 		printf("Link State ID: %s Type %d ID %d\n", log_id(lsa->ls_id),
75097494e25Sclaudio 		    LSA_24_GETHI(ntohl(lsa->ls_id)),
75197494e25Sclaudio 		    LSA_24_GETLO(ntohl(lsa->ls_id)));
75297494e25Sclaudio 		break;
75332286112Snorby 	}
75432286112Snorby 
75532286112Snorby 	printf("Advertising Router: %s\n", log_adv_rtr(lsa->adv_rtr));
75632286112Snorby 	printf("LS Seq Number: 0x%08x\n", ntohl(lsa->seq_num));
75732286112Snorby 	printf("Checksum: 0x%04x\n", ntohs(lsa->ls_chksum));
75832286112Snorby 	printf("Length: %d\n", ntohs(lsa->len));
75932286112Snorby }
76032286112Snorby 
76132286112Snorby char *
76232286112Snorby print_rtr_link_type(u_int8_t type)
76332286112Snorby {
76432286112Snorby 	switch (type) {
76532286112Snorby 	case LINK_TYPE_POINTTOPOINT:
76632286112Snorby 		return ("Point-to-Point");
76732286112Snorby 	case LINK_TYPE_TRANSIT_NET:
76832286112Snorby 		return ("Transit Network");
76932286112Snorby 	case LINK_TYPE_STUB_NET:
77032286112Snorby 		return ("Stub Network");
77132286112Snorby 	case LINK_TYPE_VIRTUAL:
77232286112Snorby 		return ("Virtual Link");
77332286112Snorby 	default:
77432286112Snorby 		return ("Unknown");
77532286112Snorby 	}
77632286112Snorby }
77732286112Snorby 
77832286112Snorby const char *
77932286112Snorby print_ospf_flags(u_int8_t opts)
78032286112Snorby {
78132286112Snorby 	static char	optbuf[32];
78232286112Snorby 
78332286112Snorby 	snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s",
78432286112Snorby 	    opts & OSPF_RTR_V ? "V" : "-",
78532286112Snorby 	    opts & OSPF_RTR_E ? "E" : "-",
78632286112Snorby 	    opts & OSPF_RTR_B ? "B" : "-");
78732286112Snorby 	return (optbuf);
78832286112Snorby }
78932286112Snorby 
79032286112Snorby int
79132286112Snorby show_db_msg_detail(struct imsg *imsg)
79232286112Snorby {
79332286112Snorby 	static struct in_addr	 area_id;
79497494e25Sclaudio 	static char		 ifname[IF_NAMESIZE];
79532286112Snorby 	static u_int8_t		 lasttype;
79632286112Snorby 	struct in_addr		 addr, data;
79732286112Snorby 	struct area		*area;
79897494e25Sclaudio 	struct iface		*iface;
79932286112Snorby 	struct lsa		*lsa;
80032286112Snorby 	struct lsa_rtr_link	*rtr_link;
80132286112Snorby 	struct lsa_asext	*asext;
80232286112Snorby 	u_int16_t		 i, nlinks, off;
80332286112Snorby 
80432286112Snorby 	/* XXX sanity checks! */
80532286112Snorby 
80632286112Snorby 	switch (imsg->hdr.type) {
80732286112Snorby 	case IMSG_CTL_SHOW_DB_EXT:
80832286112Snorby 		lsa = imsg->data;
80932286112Snorby 		if (lsa->hdr.type != lasttype)
81097494e25Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
81132286112Snorby 		show_db_hdr_msg_detail(&lsa->hdr);
81232286112Snorby 		addr.s_addr = lsa->data.asext.mask;
81332286112Snorby 		printf("Network Mask: %s\n", inet_ntoa(addr));
81432286112Snorby 
81532286112Snorby 		asext = (struct lsa_asext *)((char *)lsa + sizeof(lsa->hdr));
81632286112Snorby 
81732286112Snorby 		printf("    Metric type: ");
81832286112Snorby 		if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_E_FLAG)
81932286112Snorby 			printf("2\n");
82032286112Snorby 		else
82132286112Snorby 			printf("1\n");
82232286112Snorby 		printf("    Metric: %d\n", ntohl(asext->metric)
82332286112Snorby 		    & LSA_METRIC_MASK);
82432286112Snorby 		addr.s_addr = asext->fw_addr;
82532286112Snorby 		printf("    Forwarding Address: %s\n", inet_ntoa(addr));
82632286112Snorby 		printf("    External Route Tag: %d\n\n", ntohl(asext->ext_tag));
82732286112Snorby 
82832286112Snorby 		lasttype = lsa->hdr.type;
82932286112Snorby 		break;
83032286112Snorby 	case IMSG_CTL_SHOW_DB_NET:
83132286112Snorby 		lsa = imsg->data;
83232286112Snorby 		if (lsa->hdr.type != lasttype)
83397494e25Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
83432286112Snorby 		show_db_hdr_msg_detail(&lsa->hdr);
83532286112Snorby 		addr.s_addr = lsa->data.net.mask;
83632286112Snorby 		printf("Network Mask: %s\n", inet_ntoa(addr));
83732286112Snorby 
83832286112Snorby 		nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr)
83932286112Snorby 		    - sizeof(u_int32_t)) / sizeof(struct lsa_net_link);
84032286112Snorby 		off = sizeof(lsa->hdr) + sizeof(u_int32_t);
841ce1e71ccSbluhm 		printf("Number of Routers: %d\n", nlinks);
84232286112Snorby 
84332286112Snorby 		for (i = 0; i < nlinks; i++) {
84432286112Snorby 			addr.s_addr = lsa->data.net.att_rtr[i];
84532286112Snorby 			printf("    Attached Router: %s\n", inet_ntoa(addr));
84632286112Snorby 		}
84732286112Snorby 
84832286112Snorby 		printf("\n");
84932286112Snorby 		lasttype = lsa->hdr.type;
85032286112Snorby 		break;
85132286112Snorby 	case IMSG_CTL_SHOW_DB_RTR:
85232286112Snorby 		lsa = imsg->data;
85332286112Snorby 		if (lsa->hdr.type != lasttype)
85497494e25Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
85532286112Snorby 		show_db_hdr_msg_detail(&lsa->hdr);
85632286112Snorby 		printf("Flags: %s\n", print_ospf_flags(lsa->data.rtr.flags));
85732286112Snorby 		nlinks = ntohs(lsa->data.rtr.nlinks);
85832286112Snorby 		printf("Number of Links: %d\n\n", nlinks);
85932286112Snorby 
86032286112Snorby 		off = sizeof(lsa->hdr) + sizeof(struct lsa_rtr);
86132286112Snorby 
86232286112Snorby 		for (i = 0; i < nlinks; i++) {
86332286112Snorby 			rtr_link = (struct lsa_rtr_link *)((char *)lsa + off);
86432286112Snorby 
86532286112Snorby 			printf("    Link connected to: %s\n",
86632286112Snorby 			    print_rtr_link_type(rtr_link->type));
86732286112Snorby 
86832286112Snorby 			addr.s_addr = rtr_link->id;
86932286112Snorby 			data.s_addr = rtr_link->data;
87032286112Snorby 
87132286112Snorby 			switch (rtr_link->type) {
87232286112Snorby 			case LINK_TYPE_POINTTOPOINT:
87332286112Snorby 			case LINK_TYPE_VIRTUAL:
87432286112Snorby 				printf("    Link ID (Neighbors Router ID):"
87532286112Snorby 				    " %s\n", inet_ntoa(addr));
87632286112Snorby 				printf("    Link Data (Router Interface "
87732286112Snorby 				    "address): %s\n", inet_ntoa(data));
87832286112Snorby 				break;
87932286112Snorby 			case LINK_TYPE_TRANSIT_NET:
88032286112Snorby 				printf("    Link ID (Designated Router "
88132286112Snorby 				    "address): %s\n", inet_ntoa(addr));
88232286112Snorby 				printf("    Link Data (Router Interface "
88332286112Snorby 				    "address): %s\n", inet_ntoa(data));
88432286112Snorby 				break;
88532286112Snorby 			case LINK_TYPE_STUB_NET:
88632286112Snorby 				printf("    Link ID (Network ID): %s\n",
88732286112Snorby 				    inet_ntoa(addr));
88832286112Snorby 				printf("    Link Data (Network Mask): %s\n",
88932286112Snorby 				    inet_ntoa(data));
89032286112Snorby 				break;
89132286112Snorby 			default:
89232286112Snorby 				printf("    Link ID (Unknown): %s\n",
89332286112Snorby 				    inet_ntoa(addr));
89432286112Snorby 				printf("    Link Data (Unknown): %s\n",
89532286112Snorby 				    inet_ntoa(data));
89632286112Snorby 				break;
89732286112Snorby 			}
89832286112Snorby 
89932286112Snorby 			printf("    Metric: %d\n\n", ntohs(rtr_link->metric));
90032286112Snorby 
90132286112Snorby 			off += sizeof(struct lsa_rtr_link) +
90232286112Snorby 			    rtr_link->num_tos * sizeof(u_int32_t);
90332286112Snorby 		}
90432286112Snorby 
90532286112Snorby 		lasttype = lsa->hdr.type;
90632286112Snorby 		break;
90732286112Snorby 	case IMSG_CTL_SHOW_DB_SUM:
90832286112Snorby 	case IMSG_CTL_SHOW_DB_ASBR:
90932286112Snorby 		lsa = imsg->data;
91032286112Snorby 		if (lsa->hdr.type != lasttype)
91197494e25Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
91232286112Snorby 		show_db_hdr_msg_detail(&lsa->hdr);
91332286112Snorby 		addr.s_addr = lsa->data.sum.mask;
91432286112Snorby 		printf("Network Mask: %s\n", inet_ntoa(addr));
91532286112Snorby 		printf("Metric: %d\n\n", ntohl(lsa->data.sum.metric) &
91632286112Snorby 		    LSA_METRIC_MASK);
91732286112Snorby 		lasttype = lsa->hdr.type;
91832286112Snorby 		break;
91997494e25Sclaudio 	case IMSG_CTL_SHOW_DB_OPAQ:
92097494e25Sclaudio 		lsa = imsg->data;
92197494e25Sclaudio 		if (lsa->hdr.type != lasttype)
92297494e25Sclaudio 			show_database_head(area_id, ifname, lsa->hdr.type);
92397494e25Sclaudio 		show_db_hdr_msg_detail(&lsa->hdr);
92497494e25Sclaudio 		/* XXX should we hexdump the data? */
92597494e25Sclaudio 		lasttype = lsa->hdr.type;
92697494e25Sclaudio 		break;
92732286112Snorby 	case IMSG_CTL_AREA:
92832286112Snorby 		area = imsg->data;
92932286112Snorby 		area_id = area->id;
93015904804Snorby 		lasttype = 0;
93132286112Snorby 		break;
93297494e25Sclaudio 	case IMSG_CTL_IFACE:
93397494e25Sclaudio 		iface = imsg->data;
93497494e25Sclaudio 		strlcpy(ifname, iface->name, sizeof(ifname));
93597494e25Sclaudio 		lasttype = 0;
93697494e25Sclaudio 		break;
93732286112Snorby 	case IMSG_CTL_END:
938b49634deSclaudio 		return (1);
939b49634deSclaudio 	default:
940b49634deSclaudio 		break;
941b49634deSclaudio 	}
942b49634deSclaudio 
943b49634deSclaudio 	return (0);
944b49634deSclaudio }
945b49634deSclaudio 
946b49634deSclaudio int
947b49634deSclaudio show_nbr_msg(struct imsg *imsg)
948b49634deSclaudio {
949b49634deSclaudio 	struct ctl_nbr	*nbr;
950b49634deSclaudio 	char		*state;
951b49634deSclaudio 
952b49634deSclaudio 	switch (imsg->hdr.type) {
953b49634deSclaudio 	case IMSG_CTL_SHOW_NBR:
954b49634deSclaudio 		nbr = imsg->data;
9559ac7929fSclaudio 		if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state),
9569ac7929fSclaudio 		    if_state_name(nbr->iface_state)) == -1)
957b49634deSclaudio 			err(1, NULL);
958129e6b5fSnorby 		printf("%-15s %-3d %-12s %-9s", inet_ntoa(nbr->id),
959b49634deSclaudio 		    nbr->priority, state, fmt_timeframe_core(nbr->dead_timer));
960129e6b5fSnorby 		printf("%-15s %-9s %s\n", inet_ntoa(nbr->addr), nbr->name,
961129e6b5fSnorby 		    nbr->uptime == 0 ? "-" : fmt_timeframe_core(nbr->uptime));
962b49634deSclaudio 		free(state);
963b49634deSclaudio 		break;
964b49634deSclaudio 	case IMSG_CTL_END:
965b49634deSclaudio 		printf("\n");
966b49634deSclaudio 		return (1);
967b49634deSclaudio 	default:
968b49634deSclaudio 		break;
969b49634deSclaudio 	}
970b49634deSclaudio 
971b49634deSclaudio 	return (0);
972b49634deSclaudio }
973b49634deSclaudio 
974b49634deSclaudio const char *
975b49634deSclaudio print_ospf_options(u_int8_t opts)
976b49634deSclaudio {
977b49634deSclaudio 	static char	optbuf[32];
978b49634deSclaudio 
97997494e25Sclaudio 	snprintf(optbuf, sizeof(optbuf), "%s|%s|%s|%s|%s|%s|%s|%s",
98097494e25Sclaudio 	    opts & OSPF_OPTION_DN ? "DN" : "-",
98197494e25Sclaudio 	    opts & OSPF_OPTION_O ? "O" : "-",
982b49634deSclaudio 	    opts & OSPF_OPTION_DC ? "DC" : "-",
983b49634deSclaudio 	    opts & OSPF_OPTION_EA ? "EA" : "-",
984b49634deSclaudio 	    opts & OSPF_OPTION_NP ? "N/P" : "-",
985b49634deSclaudio 	    opts & OSPF_OPTION_MC ? "MC" : "-",
98697494e25Sclaudio 	    opts & OSPF_OPTION_E ? "E" : "-",
98797494e25Sclaudio 	    opts & OSPF_OPTION_MT ? "MT" : "-");
988b49634deSclaudio 	return (optbuf);
989b49634deSclaudio }
990b49634deSclaudio 
991b49634deSclaudio int
992b49634deSclaudio show_nbr_detail_msg(struct imsg *imsg)
993b49634deSclaudio {
994b49634deSclaudio 	struct ctl_nbr	*nbr;
995b49634deSclaudio 
996b49634deSclaudio 	switch (imsg->hdr.type) {
997b49634deSclaudio 	case IMSG_CTL_SHOW_NBR:
998b49634deSclaudio 		nbr = imsg->data;
999b49634deSclaudio 		printf("\nNeighbor %s, ", inet_ntoa(nbr->id));
1000b49634deSclaudio 		printf("interface address %s\n", inet_ntoa(nbr->addr));
100152580a1cSnorby 		printf("  Area %s, interface %s\n", inet_ntoa(nbr->area),
100252580a1cSnorby 		    nbr->name);
1003b49634deSclaudio 		printf("  Neighbor priority is %d, "
1004b49634deSclaudio 		    "State is %s, %d state changes\n",
10059ac7929fSclaudio 		    nbr->priority, nbr_state_name(nbr->nbr_state),
1006b49634deSclaudio 		    nbr->state_chng_cnt);
1007b49634deSclaudio 		printf("  DR is %s, ", inet_ntoa(nbr->dr));
1008b49634deSclaudio 		printf("BDR is %s\n", inet_ntoa(nbr->bdr));
100952580a1cSnorby 		printf("  Options %s\n", print_ospf_options(nbr->options));
1010b49634deSclaudio 		printf("  Dead timer due in %s\n",
1011b49634deSclaudio 		    fmt_timeframe_core(nbr->dead_timer));
1012a9686be3Snorby 		printf("  Uptime %s\n", fmt_timeframe_core(nbr->uptime));
1013b49634deSclaudio 		printf("  Database Summary List %d\n", nbr->db_sum_lst_cnt);
1014b49634deSclaudio 		printf("  Link State Request List %d\n", nbr->ls_req_lst_cnt);
1015b49634deSclaudio 		printf("  Link State Retransmission List %d\n",
1016b49634deSclaudio 		    nbr->ls_retrans_lst_cnt);
1017b49634deSclaudio 		break;
1018b49634deSclaudio 	case IMSG_CTL_END:
1019b49634deSclaudio 		printf("\n");
1020b49634deSclaudio 		return (1);
1021b49634deSclaudio 	default:
1022b49634deSclaudio 		break;
1023b49634deSclaudio 	}
1024b49634deSclaudio 
1025b49634deSclaudio 	return (0);
1026b49634deSclaudio }
102737355230Snorby 
102837355230Snorby int
102937355230Snorby show_rib_msg(struct imsg *imsg)
103037355230Snorby {
103137355230Snorby 	struct ctl_rt	*rt;
103237355230Snorby 	char		*dstnet;
103337355230Snorby 
103437355230Snorby 	switch (imsg->hdr.type) {
103537355230Snorby 	case IMSG_CTL_SHOW_RIB:
103637355230Snorby 		rt = imsg->data;
103737355230Snorby 		switch (rt->d_type) {
103837355230Snorby 		case DT_NET:
103937355230Snorby 			if (asprintf(&dstnet, "%s/%d", inet_ntoa(rt->prefix),
104037355230Snorby 			    rt->prefixlen) == -1)
104137355230Snorby 				err(1, NULL);
104237355230Snorby 			break;
104337355230Snorby 		case DT_RTR:
104437355230Snorby 			if (asprintf(&dstnet, "%s",
104537355230Snorby 			    inet_ntoa(rt->prefix)) == -1)
104637355230Snorby 				err(1, NULL);
104737355230Snorby 			break;
104837355230Snorby 		default:
104937355230Snorby 			errx(1, "Invalid route type");
105037355230Snorby 		}
105137355230Snorby 
10527aa44f3cSnorby 		printf("%-20s %-17s %-12s %-9s %-7d %s\n", dstnet,
10539ac7929fSclaudio 		    inet_ntoa(rt->nexthop), path_type_name(rt->p_type),
10549ac7929fSclaudio 		    dst_type_name(rt->d_type), rt->cost,
10557aa44f3cSnorby 		    rt->uptime == 0 ? "-" : fmt_timeframe_core(rt->uptime));
105637355230Snorby 		free(dstnet);
105737355230Snorby 		break;
105837355230Snorby 	case IMSG_CTL_END:
105937355230Snorby 		printf("\n");
106037355230Snorby 		return (1);
106137355230Snorby 	default:
106237355230Snorby 		break;
106337355230Snorby 	}
106437355230Snorby 
106537355230Snorby 	return (0);
106637355230Snorby }
106737355230Snorby 
106837355230Snorby void
106937355230Snorby show_rib_head(struct in_addr aid, u_int8_t d_type, u_int8_t p_type)
107037355230Snorby {
107191e3b0aeSnorby 	char	*header, *format, *format2;
107237355230Snorby 
107337355230Snorby 	switch (p_type) {
107437355230Snorby 	case PT_INTRA_AREA:
107537355230Snorby 	case PT_INTER_AREA:
107637355230Snorby 		switch (d_type) {
107737355230Snorby 		case DT_NET:
107837355230Snorby 			format = "Network Routing Table";
107991e3b0aeSnorby 			format2 = "";
108037355230Snorby 			break;
108137355230Snorby 		case DT_RTR:
108237355230Snorby 			format = "Router Routing Table";
108391e3b0aeSnorby 			format2 = "Type";
108437355230Snorby 			break;
108537355230Snorby 		default:
108637355230Snorby 			errx(1, "unknown route type");
108737355230Snorby 		}
108837355230Snorby 		break;
108937355230Snorby 	case PT_TYPE1_EXT:
109037355230Snorby 	case PT_TYPE2_EXT:
109137355230Snorby 		format = NULL;
109291e3b0aeSnorby 		format2 = "Cost 2";
109337355230Snorby 		if ((header = strdup("External Routing Table")) == NULL)
109437355230Snorby 			err(1, NULL);
109537355230Snorby 		break;
109637355230Snorby 	default:
109737355230Snorby 		errx(1, "unknown route type");
109837355230Snorby 	}
109937355230Snorby 
110037355230Snorby 	if (p_type != PT_TYPE1_EXT && p_type != PT_TYPE2_EXT)
110137355230Snorby 		if (asprintf(&header, "%s (Area %s)", format,
110237355230Snorby 		    inet_ntoa(aid)) == -1)
110337355230Snorby 			err(1, NULL);
110437355230Snorby 
110591e3b0aeSnorby 	printf("\n%-18s %s\n", "", header);
110637355230Snorby 	free(header);
110737355230Snorby 
110891e3b0aeSnorby 	printf("\n%-18s %-15s %-15s %-12s %-7s %-7s\n", "Destination",
110991e3b0aeSnorby 	    "Nexthop", "Adv Router", "Path type", "Cost", format2);
111091e3b0aeSnorby }
111137355230Snorby 
111291e3b0aeSnorby const char *
111391e3b0aeSnorby print_ospf_rtr_flags(u_int8_t opts)
111491e3b0aeSnorby {
111591e3b0aeSnorby 	static char	optbuf[32];
111691e3b0aeSnorby 
111791e3b0aeSnorby 	snprintf(optbuf, sizeof(optbuf), "%s%s%s",
111891e3b0aeSnorby 	    opts & OSPF_RTR_E ? "AS" : "",
111991e3b0aeSnorby 	    opts & OSPF_RTR_E && opts & OSPF_RTR_B ? "+" : "",
112091e3b0aeSnorby 	    opts & OSPF_RTR_B ? "ABR" : "");
112191e3b0aeSnorby 	return (optbuf);
112237355230Snorby }
112337355230Snorby 
112437355230Snorby int
112537355230Snorby show_rib_detail_msg(struct imsg *imsg)
112637355230Snorby {
112737355230Snorby 	static struct in_addr	 area_id;
112837355230Snorby 	struct ctl_rt		*rt;
112937355230Snorby 	struct area		*area;
113037355230Snorby 	char			*dstnet;
113137355230Snorby 	static u_int8_t		 lasttype;
113237355230Snorby 
113337355230Snorby 	switch (imsg->hdr.type) {
113437355230Snorby 	case IMSG_CTL_SHOW_RIB:
113537355230Snorby 		rt = imsg->data;
113637355230Snorby 
113737355230Snorby 		switch (rt->p_type) {
113837355230Snorby 		case PT_INTRA_AREA:
113937355230Snorby 		case PT_INTER_AREA:
114037355230Snorby 			switch (rt->d_type) {
114137355230Snorby 			case DT_NET:
114237355230Snorby 				if (lasttype != RIB_NET)
114337355230Snorby 					show_rib_head(rt->area, rt->d_type,
114437355230Snorby 					     rt->p_type);
114537355230Snorby 				if (asprintf(&dstnet, "%s/%d",
114637355230Snorby 				    inet_ntoa(rt->prefix), rt->prefixlen) == -1)
114737355230Snorby 					err(1, NULL);
114837355230Snorby 				lasttype = RIB_NET;
114937355230Snorby 				break;
115037355230Snorby 			case DT_RTR:
115137355230Snorby 				if (lasttype != RIB_RTR)
115237355230Snorby 					show_rib_head(rt->area, rt->d_type,
115337355230Snorby 					     rt->p_type);
115437355230Snorby 				if (asprintf(&dstnet, "%s",
115537355230Snorby 				    inet_ntoa(rt->prefix)) == -1)
115637355230Snorby 					err(1, NULL);
115737355230Snorby 				lasttype = RIB_RTR;
115837355230Snorby 				break;
115937355230Snorby 			default:
116037355230Snorby 				errx(1, "unknown route type");
116137355230Snorby 			}
116291e3b0aeSnorby 			printf("%-18s %-15s ", dstnet, inet_ntoa(rt->nexthop));
116391e3b0aeSnorby 			printf("%-15s %-12s %-7d", inet_ntoa(rt->adv_rtr),
11649ac7929fSclaudio 			    path_type_name(rt->p_type), rt->cost);
116537355230Snorby 			free(dstnet);
116691e3b0aeSnorby 
116791e3b0aeSnorby 			if (rt->d_type == DT_RTR)
116891e3b0aeSnorby 				printf(" %-7s",
116991e3b0aeSnorby 				    print_ospf_rtr_flags(rt->flags));
117091e3b0aeSnorby 
117191e3b0aeSnorby 			printf("\n");
117237355230Snorby 			break;
117337355230Snorby 		case PT_TYPE1_EXT:
117437355230Snorby 		case PT_TYPE2_EXT:
117591e3b0aeSnorby 			if (lasttype != RIB_EXT)
117691e3b0aeSnorby 				show_rib_head(rt->area, rt->d_type, rt->p_type);
117791e3b0aeSnorby 
117891e3b0aeSnorby 			if (asprintf(&dstnet, "%s/%d",
117991e3b0aeSnorby 			    inet_ntoa(rt->prefix), rt->prefixlen) == -1)
118091e3b0aeSnorby 				err(1, NULL);
118191e3b0aeSnorby 
118291e3b0aeSnorby 			printf("%-18s %-15s ", dstnet, inet_ntoa(rt->nexthop));
118391e3b0aeSnorby 			printf("%-15s %-12s %-7d %-7d\n",
11849ac7929fSclaudio 			    inet_ntoa(rt->adv_rtr), path_type_name(rt->p_type),
118591e3b0aeSnorby 			    rt->cost, rt->cost2);
11861c1dafb4Snorby 			free(dstnet);
118791e3b0aeSnorby 
118891e3b0aeSnorby 			lasttype = RIB_EXT;
118937355230Snorby 			break;
119037355230Snorby 		default:
119137355230Snorby 			errx(1, "unknown route type");
119237355230Snorby 		}
119337355230Snorby 		break;
119437355230Snorby 	case IMSG_CTL_AREA:
119537355230Snorby 		area = imsg->data;
119637355230Snorby 		area_id = area->id;
119737355230Snorby 		break;
119837355230Snorby 	case IMSG_CTL_END:
119937355230Snorby 		printf("\n");
120037355230Snorby 		return (1);
120137355230Snorby 	default:
120237355230Snorby 		break;
120337355230Snorby 	}
120437355230Snorby 
120537355230Snorby 	return (0);
120637355230Snorby }
1207c47b7f65Sclaudio 
1208c47b7f65Sclaudio void
1209c47b7f65Sclaudio show_fib_head(void)
1210c47b7f65Sclaudio {
1211c47b7f65Sclaudio 	printf("flags: * = valid, O = OSPF, C = Connected, S = Static\n");
1212253df265Sclaudio 	printf("%-6s %-4s %-20s %-17s\n", "Flags", "Prio", "Destination", "Nexthop");
1213c47b7f65Sclaudio }
1214c47b7f65Sclaudio 
1215c47b7f65Sclaudio int
1216c47b7f65Sclaudio show_fib_msg(struct imsg *imsg)
1217c47b7f65Sclaudio {
1218c47b7f65Sclaudio 	struct kroute		*k;
1219c47b7f65Sclaudio 	char			*p;
1220c47b7f65Sclaudio 
1221c47b7f65Sclaudio 	switch (imsg->hdr.type) {
1222c47b7f65Sclaudio 	case IMSG_CTL_KROUTE:
1223c47b7f65Sclaudio 		if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute))
1224c47b7f65Sclaudio 			errx(1, "wrong imsg len");
1225c47b7f65Sclaudio 		k = imsg->data;
1226c47b7f65Sclaudio 
1227c47b7f65Sclaudio 		if (k->flags & F_DOWN)
1228c47b7f65Sclaudio 			printf(" ");
1229c47b7f65Sclaudio 		else
1230c47b7f65Sclaudio 			printf("*");
1231c47b7f65Sclaudio 
1232347b5019Sclaudio 		if (!(k->flags & F_KERNEL))
1233c47b7f65Sclaudio 			printf("O");
1234c47b7f65Sclaudio 		else if (k->flags & F_CONNECTED)
1235c47b7f65Sclaudio 			printf("C");
1236fc1549e1Sclaudio 		else if (k->flags & F_STATIC)
1237c47b7f65Sclaudio 			printf("S");
1238c47b7f65Sclaudio 		else
1239c47b7f65Sclaudio 			printf(" ");
1240c47b7f65Sclaudio 
1241c47b7f65Sclaudio 		printf("     ");
1242253df265Sclaudio 		printf("%4d ", k->priority);
1243c47b7f65Sclaudio 		if (asprintf(&p, "%s/%u", inet_ntoa(k->prefix), k->prefixlen) ==
1244c47b7f65Sclaudio 		    -1)
1245c47b7f65Sclaudio 			err(1, NULL);
1246c47b7f65Sclaudio 		printf("%-20s ", p);
1247c47b7f65Sclaudio 		free(p);
1248c47b7f65Sclaudio 
1249c47b7f65Sclaudio 		if (k->nexthop.s_addr)
1250c47b7f65Sclaudio 			printf("%s", inet_ntoa(k->nexthop));
1251c47b7f65Sclaudio 		else if (k->flags & F_CONNECTED)
1252c47b7f65Sclaudio 			printf("link#%u", k->ifindex);
1253c47b7f65Sclaudio 		printf("\n");
1254c47b7f65Sclaudio 
1255c47b7f65Sclaudio 		break;
1256c47b7f65Sclaudio 	case IMSG_CTL_END:
1257c47b7f65Sclaudio 		printf("\n");
1258c47b7f65Sclaudio 		return (1);
1259c47b7f65Sclaudio 	default:
1260c47b7f65Sclaudio 		break;
1261c47b7f65Sclaudio 	}
1262c47b7f65Sclaudio 
1263c47b7f65Sclaudio 	return (0);
1264c47b7f65Sclaudio }
1265c47b7f65Sclaudio 
1266c47b7f65Sclaudio void
1267c47b7f65Sclaudio show_interface_head(void)
1268c47b7f65Sclaudio {
12694c561fb6Sclaudio 	printf("%-15s%-15s%s\n", "Interface", "Flags",
1270c47b7f65Sclaudio 	    "Link state");
1271c47b7f65Sclaudio }
1272c47b7f65Sclaudio 
12730f617141Sclaudio const struct if_status_description
12740f617141Sclaudio 		if_status_descriptions[] = LINK_STATE_DESCRIPTIONS;
1275c47b7f65Sclaudio const struct ifmedia_description
1276c47b7f65Sclaudio 		ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS;
1277c47b7f65Sclaudio 
1278c47b7f65Sclaudio const char *
1279c47b7f65Sclaudio get_media_descr(int media_type)
1280c47b7f65Sclaudio {
1281c47b7f65Sclaudio 	const struct ifmedia_description	*p;
1282c47b7f65Sclaudio 
1283c47b7f65Sclaudio 	for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++)
1284c47b7f65Sclaudio 		if (media_type == p->ifmt_word)
1285c47b7f65Sclaudio 			return (p->ifmt_string);
1286c47b7f65Sclaudio 
1287a5bcf77aSclaudio 	return ("unknown");
1288c47b7f65Sclaudio }
1289c47b7f65Sclaudio 
1290c47b7f65Sclaudio const char *
1291c47b7f65Sclaudio get_linkstate(int media_type, int link_state)
1292c47b7f65Sclaudio {
12930f617141Sclaudio 	const struct if_status_description *p;
12940f617141Sclaudio 	static char buf[8];
1295c47b7f65Sclaudio 
12960f617141Sclaudio 	for (p = if_status_descriptions; p->ifs_string != NULL; p++) {
12970f617141Sclaudio 		if (LINK_STATE_DESC_MATCH(p, media_type, link_state))
12980f617141Sclaudio 			return (p->ifs_string);
1299c47b7f65Sclaudio 	}
13000f617141Sclaudio 	snprintf(buf, sizeof(buf), "[#%d]", link_state);
13010f617141Sclaudio 	return (buf);
1302c47b7f65Sclaudio }
1303c47b7f65Sclaudio 
1304c47b7f65Sclaudio void
130556babc06Sclaudio print_baudrate(u_int64_t baudrate)
1306c47b7f65Sclaudio {
1307c47b7f65Sclaudio 	if (baudrate > IF_Gbps(1))
130856babc06Sclaudio 		printf("%llu GBit/s", baudrate / IF_Gbps(1));
1309c47b7f65Sclaudio 	else if (baudrate > IF_Mbps(1))
131056babc06Sclaudio 		printf("%llu MBit/s", baudrate / IF_Mbps(1));
1311c47b7f65Sclaudio 	else if (baudrate > IF_Kbps(1))
131256babc06Sclaudio 		printf("%llu KBit/s", baudrate / IF_Kbps(1));
1313c47b7f65Sclaudio 	else
131456babc06Sclaudio 		printf("%llu Bit/s", baudrate);
1315c47b7f65Sclaudio }
1316c47b7f65Sclaudio 
1317c47b7f65Sclaudio int
1318c47b7f65Sclaudio show_fib_interface_msg(struct imsg *imsg)
1319c47b7f65Sclaudio {
1320c47b7f65Sclaudio 	struct kif	*k;
1321c47b7f65Sclaudio 	int		 ifms_type;
1322c47b7f65Sclaudio 
1323c47b7f65Sclaudio 	switch (imsg->hdr.type) {
13244c561fb6Sclaudio 	case IMSG_CTL_IFINFO:
1325c47b7f65Sclaudio 		k = imsg->data;
1326c47b7f65Sclaudio 		printf("%-15s", k->ifname);
1327c47b7f65Sclaudio 		printf("%-15s", k->flags & IFF_UP ? "UP" : "");
13280f617141Sclaudio 		ifms_type = get_ifms_type(k->media_type);
1329c47b7f65Sclaudio 		if (ifms_type)
13300f617141Sclaudio 			printf("%s, ", get_media_descr(ifms_type));
13310f617141Sclaudio 
13320f617141Sclaudio 		printf("%s", get_linkstate(k->media_type, k->link_state));
1333c47b7f65Sclaudio 
1334c47b7f65Sclaudio 		if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) {
1335c47b7f65Sclaudio 			printf(", ");
1336c47b7f65Sclaudio 			print_baudrate(k->baudrate);
1337c47b7f65Sclaudio 		}
1338c47b7f65Sclaudio 		printf("\n");
1339c47b7f65Sclaudio 		break;
1340c47b7f65Sclaudio 	case IMSG_CTL_END:
1341c47b7f65Sclaudio 		printf("\n");
1342c47b7f65Sclaudio 		return (1);
1343c47b7f65Sclaudio 	default:
1344c47b7f65Sclaudio 		break;
1345c47b7f65Sclaudio 	}
1346c47b7f65Sclaudio 
1347c47b7f65Sclaudio 	return (0);
1348c47b7f65Sclaudio }
1349