xref: /openbsd/usr.sbin/dvmrpctl/dvmrpctl.c (revision d28a6801)
1*d28a6801Snaddy /*	$OpenBSD: dvmrpctl.c,v 1.16 2022/01/20 14:10:07 naddy Exp $ */
289189827Snorby 
389189827Snorby /*
489189827Snorby  * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
589189827Snorby  * Copyright (c) 2004, 2005, 2006 Esben Norby <norby@openbsd.org>
689189827Snorby  * Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
789189827Snorby  *
889189827Snorby  * Permission to use, copy, modify, and distribute this software for any
989189827Snorby  * purpose with or without fee is hereby granted, provided that the above
1089189827Snorby  * copyright notice and this permission notice appear in all copies.
1189189827Snorby  *
1289189827Snorby  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1389189827Snorby  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1489189827Snorby  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1589189827Snorby  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1689189827Snorby  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1789189827Snorby  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1889189827Snorby  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1989189827Snorby  */
2089189827Snorby 
2189189827Snorby #include <sys/types.h>
2289189827Snorby #include <sys/socket.h>
2389189827Snorby #include <sys/un.h>
2489189827Snorby #include <netinet/in.h>
2589189827Snorby #include <netinet/ip_mroute.h>
2689189827Snorby #include <arpa/inet.h>
2789189827Snorby #include <net/if_types.h>
2889189827Snorby 
2989189827Snorby #include <err.h>
30397afdbcSderaadt #include <errno.h>
3189189827Snorby #include <stdio.h>
3289189827Snorby #include <stdlib.h>
3389189827Snorby #include <string.h>
3489189827Snorby #include <unistd.h>
3589189827Snorby 
3689189827Snorby #include "igmp.h"
3789189827Snorby #include "dvmrp.h"
3889189827Snorby #include "dvmrpd.h"
3989189827Snorby #include "dvmrpe.h"
4089189827Snorby #include "parser.h"
4189189827Snorby #include "log.h"
4289189827Snorby 
4389189827Snorby __dead void	 usage(void);
4489189827Snorby int		 show_summary_msg(struct imsg *);
4589189827Snorby int		 show_interface_msg(struct imsg *);
4689189827Snorby int		 show_interface_detail_msg(struct imsg *);
4789189827Snorby int		 show_igmp_msg(struct imsg *);
4889189827Snorby const char	*print_if_type(enum iface_type type);
4989189827Snorby const char	*print_nbr_state(int);
5089189827Snorby const char	*print_link(int);
5189189827Snorby const char	*fmt_timeframe(time_t t);
5289189827Snorby const char	*fmt_timeframe_core(time_t t);
5389189827Snorby int		 show_nbr_msg(struct imsg *);
5489189827Snorby const char	*print_dvmrp_options(u_int8_t);
5589189827Snorby int		 show_nbr_detail_msg(struct imsg *);
5689189827Snorby int		 show_rib_msg(struct imsg *);
5789189827Snorby int		 show_rib_detail_msg(struct imsg *);
5889189827Snorby int		 show_mfc_msg(struct imsg *);
5989189827Snorby int		 show_mfc_detail_msg(struct imsg *);
609f69273fSstsp const char *	 get_linkstate(uint8_t, int);
6189189827Snorby 
6289189827Snorby struct imsgbuf	*ibuf;
6389189827Snorby 
6489189827Snorby __dead void
usage(void)6589189827Snorby usage(void)
6689189827Snorby {
6789189827Snorby 	extern char *__progname;
6889189827Snorby 
69b63b9e86Ssobrado 	fprintf(stderr, "usage: %s command [argument ...]\n", __progname);
7089189827Snorby 	exit(1);
7189189827Snorby }
7289189827Snorby 
7389189827Snorby int
main(int argc,char * argv[])7489189827Snorby main(int argc, char *argv[])
7589189827Snorby {
7689189827Snorby 	struct sockaddr_un	 sun;
7789189827Snorby 	struct parse_result	*res;
7889189827Snorby 	struct imsg		 imsg;
7989189827Snorby 	unsigned int		 ifidx = 0;
8089189827Snorby 	int			 ctl_sock;
81c3319070Sclaudio 	int			 done = 0, verbose = 0;
8289189827Snorby 	int			 n;
8389189827Snorby 
8489189827Snorby 	/* parse options */
8589189827Snorby 	if ((res = parse(argc - 1, argv + 1)) == NULL)
8689189827Snorby 		exit(1);
8789189827Snorby 
8889189827Snorby 	/* connect to dvmrpd control socket */
8989189827Snorby 	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
9089189827Snorby 		err(1, "socket");
9189189827Snorby 
9289189827Snorby 	bzero(&sun, sizeof(sun));
9389189827Snorby 	sun.sun_family = AF_UNIX;
9489189827Snorby 	strlcpy(sun.sun_path, DVMRPD_SOCKET, sizeof(sun.sun_path));
9589189827Snorby 	if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1)
9689189827Snorby 		err(1, "connect: %s", DVMRPD_SOCKET);
9789189827Snorby 
98daa441c5Sderaadt 	if (pledge("stdio", NULL) == -1)
99bc3fb1a1Sderaadt 		err(1, "pledge");
100bc3fb1a1Sderaadt 
10189189827Snorby 	if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
10289189827Snorby 		fatal(NULL);
10314d72cd0Spyr 	imsg_init(ibuf, ctl_sock);
10489189827Snorby 	done = 0;
10589189827Snorby 
10689189827Snorby 	/* process user request */
10789189827Snorby 	switch (res->action) {
10889189827Snorby 	case NONE:
10989189827Snorby 		usage();
11089189827Snorby 		/* NOTREACHED */
11189189827Snorby 	case SHOW:
11289189827Snorby 	case SHOW_SUM:
11314d72cd0Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_SUM, 0, 0, -1, NULL, 0);
11489189827Snorby 		break;
11589189827Snorby 	case SHOW_IFACE:
11689189827Snorby 		printf("%-11s %-18s %-10s %-10s %-10s %-8s %s\n",
11789189827Snorby 		    "Interface", "Address", "State", "ProbeTimer", "Linkstate",
11889189827Snorby 		    "Uptime", "Groups");
11989189827Snorby 		/* FALLTHROUGH */
12089189827Snorby 	case SHOW_IFACE_DTAIL:
12189189827Snorby 		if (*res->ifname) {
12289189827Snorby 			ifidx = if_nametoindex(res->ifname);
12389189827Snorby 			if (ifidx == 0)
12489189827Snorby 				errx(1, "no such interface %s", res->ifname);
12589189827Snorby 		}
12614d72cd0Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_IFACE, 0, 0, -1, &ifidx,
12789189827Snorby 		    sizeof(ifidx));
12889189827Snorby 		break;
12989189827Snorby 	case SHOW_IGMP:
13089189827Snorby 		if (*res->ifname) {
13189189827Snorby 			ifidx = if_nametoindex(res->ifname);
13289189827Snorby 			if (ifidx == 0)
13389189827Snorby 				errx(1, "no such interface %s", res->ifname);
13489189827Snorby 		}
13514d72cd0Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_IGMP, 0, 0, -1, &ifidx,
13689189827Snorby 		    sizeof(ifidx));
13789189827Snorby 		break;
13889189827Snorby 	case SHOW_NBR:
13989189827Snorby 		printf("%-15s %-10s %-9s %-15s %-11s %-8s\n", "ID", "State",
14089189827Snorby 		    "DeadTime", "Address", "Interface", "Uptime");
14189189827Snorby 		/* FALLTHROUGH */
14289189827Snorby 	case SHOW_NBR_DTAIL:
14314d72cd0Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0);
14489189827Snorby 		break;
14589189827Snorby 	case SHOW_RIB:
14689189827Snorby 		printf("%-20s %-17s %-7s %-10s %-s\n", "Destination", "Nexthop",
14789189827Snorby 		    "Cost", "Uptime", "Expire");
14889189827Snorby 		/* FALLTHROUGH */
14989189827Snorby 	case SHOW_RIB_DTAIL:
15014d72cd0Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, -1, NULL, 0);
15189189827Snorby 		break;
15289189827Snorby 	case SHOW_MFC:
15389189827Snorby 		printf("%-16s %-16s %-9s %-9s %-4s %-10s %-10s\n", "Group",
15489189827Snorby 		    "Origin", "Incoming", "Outgoing", "TTL", "Uptime",
15589189827Snorby 		    "Expire");
15689189827Snorby 		/* FALLTHROUGH */
15789189827Snorby 	case SHOW_MFC_DTAIL:
15814d72cd0Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_MFC, 0, 0, -1, NULL, 0);
15989189827Snorby 		break;
160c3319070Sclaudio 	case LOG_VERBOSE:
161c3319070Sclaudio 		verbose = 1;
162c3319070Sclaudio 		/* FALLTHROUGH */
163c3319070Sclaudio 	case LOG_BRIEF:
164c3319070Sclaudio 		imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1,
165c3319070Sclaudio 		    &verbose, sizeof(verbose));
166c3319070Sclaudio 		printf("logging request sent.\n");
167c3319070Sclaudio 		done = 1;
168c3319070Sclaudio 		break;
16989189827Snorby 	case RELOAD:
17014d72cd0Spyr 		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0);
17189189827Snorby 		printf("reload request sent.\n");
17289189827Snorby 		done = 1;
17389189827Snorby 		break;
17489189827Snorby 	}
17589189827Snorby 
17689189827Snorby 	while (ibuf->w.queued)
177397afdbcSderaadt 		if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
17889189827Snorby 			err(1, "write error");
17989189827Snorby 
18089189827Snorby 	while (!done) {
181b74bd0c0Sclaudio 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
18289189827Snorby 			errx(1, "imsg_read error");
18389189827Snorby 		if (n == 0)
18489189827Snorby 			errx(1, "pipe closed");
18589189827Snorby 
18689189827Snorby 		while (!done) {
18789189827Snorby 			if ((n = imsg_get(ibuf, &imsg)) == -1)
18889189827Snorby 				errx(1, "imsg_get error");
18989189827Snorby 			if (n == 0)
19089189827Snorby 				break;
19189189827Snorby 			switch (res->action) {
19289189827Snorby 			case SHOW:
19389189827Snorby 			case SHOW_SUM:
19489189827Snorby 				done = show_summary_msg(&imsg);
19589189827Snorby 				break;
19689189827Snorby 			case SHOW_IFACE:
19789189827Snorby 				done = show_interface_msg(&imsg);
19889189827Snorby 				break;
19989189827Snorby 			case SHOW_IFACE_DTAIL:
20089189827Snorby 				done = show_interface_detail_msg(&imsg);
20189189827Snorby 				break;
20289189827Snorby 			case SHOW_IGMP:
20389189827Snorby 				done = show_igmp_msg(&imsg);
20489189827Snorby 				break;
20589189827Snorby 			case SHOW_NBR:
20689189827Snorby 				done = show_nbr_msg(&imsg);
20789189827Snorby 				break;
20889189827Snorby 			case SHOW_NBR_DTAIL:
20989189827Snorby 				done = show_nbr_detail_msg(&imsg);
21089189827Snorby 				break;
21189189827Snorby 			case SHOW_RIB:
21289189827Snorby 				done = show_rib_msg(&imsg);
21389189827Snorby 				break;
21489189827Snorby 			case SHOW_RIB_DTAIL:
21589189827Snorby 				done = show_rib_detail_msg(&imsg);
21689189827Snorby 				break;
21789189827Snorby 			case SHOW_MFC:
21889189827Snorby 				done = show_mfc_msg(&imsg);
21989189827Snorby 				break;
22089189827Snorby 			case SHOW_MFC_DTAIL:
22189189827Snorby 				done = show_mfc_detail_msg(&imsg);
22289189827Snorby 				break;
22389189827Snorby 			case NONE:
224c3319070Sclaudio 			case LOG_VERBOSE:
225c3319070Sclaudio 			case LOG_BRIEF:
22689189827Snorby 			case RELOAD:
22789189827Snorby 				break;
22889189827Snorby 			}
22989189827Snorby 			imsg_free(&imsg);
23089189827Snorby 		}
23189189827Snorby 	}
23289189827Snorby 	close(ctl_sock);
23389189827Snorby 	free(ibuf);
23489189827Snorby 
23589189827Snorby 	return (0);
23689189827Snorby }
23789189827Snorby 
23889189827Snorby int
show_summary_msg(struct imsg * imsg)23989189827Snorby show_summary_msg(struct imsg *imsg)
24089189827Snorby {
24189189827Snorby 	struct ctl_sum		*sum;
24289189827Snorby 
24389189827Snorby 	switch (imsg->hdr.type) {
24489189827Snorby 	case IMSG_CTL_SHOW_SUM:
24589189827Snorby 		sum = imsg->data;
24689189827Snorby 		printf("Router ID: %s\n", inet_ntoa(sum->rtr_id));
24789189827Snorby 		printf("Hold time is %d sec(s)\n", sum->hold_time);
24889189827Snorby 		break;
24989189827Snorby 	case IMSG_CTL_END:
25089189827Snorby 		printf("\n");
25189189827Snorby 		return (1);
25289189827Snorby 	default:
25389189827Snorby 		break;
25489189827Snorby 	}
25589189827Snorby 
25689189827Snorby 	return (0);
25789189827Snorby }
25889189827Snorby 
25989189827Snorby int
show_interface_msg(struct imsg * imsg)26089189827Snorby show_interface_msg(struct imsg *imsg)
26189189827Snorby {
26289189827Snorby 	struct ctl_iface	*iface;
26389189827Snorby 	char			*netid;
26489189827Snorby 
26589189827Snorby 	switch (imsg->hdr.type) {
26689189827Snorby 	case IMSG_CTL_SHOW_IFACE:
26789189827Snorby 		iface = imsg->data;
26889189827Snorby 
26989189827Snorby 		if (asprintf(&netid, "%s/%d", inet_ntoa(iface->addr),
27089189827Snorby 		    mask2prefixlen(iface->mask.s_addr)) == -1)
27189189827Snorby 			err(1, NULL);
27289189827Snorby 		printf("%-11s %-18s %-10s %-10s %-10s %-8s %5d\n",
27389189827Snorby 		    iface->name, netid, if_state_name(iface->state),
27489189827Snorby 		    iface->probe_timer == 0 ? "00:00:00" :
27589189827Snorby 		    fmt_timeframe_core(iface->probe_timer),
2769f69273fSstsp 		    get_linkstate(iface->if_type, iface->linkstate),
2770f617141Sclaudio 		    iface->uptime == 0 ? "00:00:00" :
27889189827Snorby 		    fmt_timeframe_core(iface->uptime), iface->group_cnt);
27989189827Snorby 		free(netid);
28089189827Snorby 		break;
28189189827Snorby 	case IMSG_CTL_END:
28289189827Snorby 		printf("\n");
28389189827Snorby 		return (1);
28489189827Snorby 	default:
28589189827Snorby 		break;
28689189827Snorby 	}
28789189827Snorby 
28889189827Snorby 	return (0);
28989189827Snorby }
29089189827Snorby 
29189189827Snorby int
show_interface_detail_msg(struct imsg * imsg)29289189827Snorby show_interface_detail_msg(struct imsg *imsg)
29389189827Snorby {
29489189827Snorby 	struct ctl_iface	*iface;
29589189827Snorby 
29689189827Snorby 	switch (imsg->hdr.type) {
29789189827Snorby 	case IMSG_CTL_SHOW_IFACE:
29889189827Snorby 		iface = imsg->data;
29989189827Snorby 
30089189827Snorby 		printf("\n");
30189189827Snorby 		printf("Interface %s, line protocol is %s\n",
30289189827Snorby 		    iface->name, print_link(iface->flags));
30389189827Snorby 		printf("  Internet address %s/%d\n",
30489189827Snorby 		    inet_ntoa(iface->addr),
30589189827Snorby 		    mask2prefixlen(iface->mask.s_addr));
30689189827Snorby 		printf("  Linkstate %s\n",
3079f69273fSstsp 		    get_linkstate(iface->if_type, iface->linkstate));
30889189827Snorby 		printf("  Network type %s, cost: %d\n",
30989189827Snorby 		    if_type_name(iface->type), iface->metric);
31089189827Snorby 		printf("  State %s, querier ", if_state_name(iface->state));
31189189827Snorby 		if (iface->state == IF_STA_QUERIER)
31289189827Snorby 			printf("%s\n", inet_ntoa(iface->addr));
31389189827Snorby 		else
31489189827Snorby 			printf("%s\n", inet_ntoa(iface->querier));
31589189827Snorby 		printf("  Generation ID %d\n", iface->gen_id);
31689189827Snorby 		printf("  Timer intervals configured, "
31789189827Snorby 		    "probe %d, dead %d\n", iface->probe_interval,
31889189827Snorby 		    iface->dead_interval);
31989189827Snorby 		if (iface->passive)
32089189827Snorby 			printf("    Passive interface (No Hellos)\n");
32189189827Snorby 		else if (iface->probe_timer < 0)
32289189827Snorby 			printf("    Hello timer not running\n");
32389189827Snorby 		else
32489189827Snorby 			printf("    Hello timer due in %s\n",
32589189827Snorby 			    fmt_timeframe_core(iface->probe_timer));
32689189827Snorby 		printf("    Uptime %s\n", iface->uptime == 0 ?
32789189827Snorby 		    "00:00:00" : fmt_timeframe_core(iface->uptime));
328b39d1d57Smichele 		printf("  Adjacent neighbor count is "
329b39d1d57Smichele 		    "%d\n", iface->adj_cnt);
33089189827Snorby 		break;
33189189827Snorby 	case IMSG_CTL_END:
33289189827Snorby 		printf("\n");
33389189827Snorby 		return (1);
33489189827Snorby 	default:
33589189827Snorby 		break;
33689189827Snorby 	}
33789189827Snorby 
33889189827Snorby 	return (0);
33989189827Snorby }
34089189827Snorby 
34189189827Snorby int
show_igmp_msg(struct imsg * imsg)34289189827Snorby show_igmp_msg(struct imsg *imsg)
34389189827Snorby {
34489189827Snorby 	struct ctl_iface	*iface;
34589189827Snorby 	struct ctl_group	*group;
34689189827Snorby 	char			*netid;
34789189827Snorby 
34889189827Snorby 	switch (imsg->hdr.type) {
34989189827Snorby 	case IMSG_CTL_SHOW_IFACE:
35089189827Snorby 		iface = imsg->data;
35189189827Snorby 		if (asprintf(&netid, "%s/%d", inet_ntoa(iface->addr),
35289189827Snorby 		    mask2prefixlen(iface->mask.s_addr)) == -1)
35389189827Snorby 			err(1, NULL);
35489189827Snorby 		printf("\nInterface %s, address %s, state %s, groups %d\n",
35589189827Snorby 		    iface->name, netid, if_state_name(iface->state),
35689189827Snorby 		    iface->group_cnt);
35789189827Snorby 		free(netid);
35889189827Snorby 		printf("  %-16s %-10s %-10s %-10s\n", "Group", "State",
35989189827Snorby 		    "DeadTimer", "Uptime");
36089189827Snorby 		break;
36189189827Snorby 	case IMSG_CTL_SHOW_IGMP:
36289189827Snorby 		group = imsg->data;
36389189827Snorby 		printf("  %-16s %-10s %-10s %-10s\n", inet_ntoa(group->addr),
36489189827Snorby 		    group_state_name(group->state),
36589189827Snorby 		    group->dead_timer == 0 ? "00:00:00" :
36689189827Snorby 		    fmt_timeframe_core(group->dead_timer),
36789189827Snorby 		    group->uptime == 0 ? "00:00:00" :
36889189827Snorby 		    fmt_timeframe_core(group->uptime));
36989189827Snorby 		break;
37089189827Snorby 	case IMSG_CTL_END:
37189189827Snorby 		printf("\n");
37289189827Snorby 		return (1);
37389189827Snorby 	default:
37489189827Snorby 		break;
37589189827Snorby 	}
37689189827Snorby 
37789189827Snorby 	return (0);
37889189827Snorby }
37989189827Snorby 
38089189827Snorby const char *
print_if_type(enum iface_type type)38189189827Snorby print_if_type(enum iface_type type)
38289189827Snorby {
38389189827Snorby 	switch (type) {
38489189827Snorby 	case IF_TYPE_POINTOPOINT:
38589189827Snorby 		return ("POINTOPOINT");
38689189827Snorby 	case IF_TYPE_BROADCAST:
38789189827Snorby 		return ("BROADCAST");
38889189827Snorby 	default:
38989189827Snorby 		return ("UNKNOWN");
39089189827Snorby 	}
39189189827Snorby }
39289189827Snorby 
39389189827Snorby const char *
print_nbr_state(int state)39489189827Snorby print_nbr_state(int state)
39589189827Snorby {
39689189827Snorby 	switch (state) {
39789189827Snorby 	case NBR_STA_DOWN:
39889189827Snorby 		return ("DOWN");
39989189827Snorby 	case NBR_STA_1_WAY:
40089189827Snorby 		return ("1-WAY");
40189189827Snorby 	case NBR_STA_2_WAY:
40289189827Snorby 		return ("2-WAY");
40389189827Snorby 	default:
40489189827Snorby 		return ("UNKNOWN");
40589189827Snorby 	}
40689189827Snorby }
40789189827Snorby 
40889189827Snorby const char *
print_link(int state)40989189827Snorby print_link(int state)
41089189827Snorby {
41189189827Snorby 	if (state & IFF_UP)
41289189827Snorby 		return ("UP");
41389189827Snorby 	else
41489189827Snorby 		return ("DOWN");
41589189827Snorby }
41689189827Snorby 
41789189827Snorby #define TF_BUFS	8
41889189827Snorby #define TF_LEN	9
41989189827Snorby 
42089189827Snorby const char *
fmt_timeframe(time_t t)42189189827Snorby fmt_timeframe(time_t t)
42289189827Snorby {
42389189827Snorby 	if (t == 0)
42489189827Snorby 		return ("Never");
42589189827Snorby 	else
42689189827Snorby 		return (fmt_timeframe_core(time(NULL) - t));
42789189827Snorby }
42889189827Snorby 
42989189827Snorby const char *
fmt_timeframe_core(time_t t)43089189827Snorby fmt_timeframe_core(time_t t)
43189189827Snorby {
43289189827Snorby 	char		*buf;
43389189827Snorby 	static char	 tfbuf[TF_BUFS][TF_LEN];	/* ring buffer */
43489189827Snorby 	static int	 idx = 0;
435035b0708Sgilles 	unsigned int	 sec, min, hrs, day;
436035b0708Sgilles 	unsigned long long	week;
43789189827Snorby 
43889189827Snorby 	if (t == 0)
43989189827Snorby 		return ("Stopped");
44089189827Snorby 
44189189827Snorby 	buf = tfbuf[idx++];
44289189827Snorby 	if (idx == TF_BUFS)
44389189827Snorby 		idx = 0;
44489189827Snorby 
44589189827Snorby 	week = t;
44689189827Snorby 
44789189827Snorby 	sec = week % 60;
44889189827Snorby 	week /= 60;
44989189827Snorby 	min = week % 60;
45089189827Snorby 	week /= 60;
45189189827Snorby 	hrs = week % 24;
45289189827Snorby 	week /= 24;
45389189827Snorby 	day = week % 7;
45489189827Snorby 	week /= 7;
45589189827Snorby 
45689189827Snorby 	if (week > 0)
457035b0708Sgilles 		snprintf(buf, TF_LEN, "%02lluw%01ud%02uh", week, day, hrs);
45889189827Snorby 	else if (day > 0)
45989189827Snorby 		snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
46089189827Snorby 	else
46189189827Snorby 		snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
46289189827Snorby 
46389189827Snorby 	return (buf);
46489189827Snorby }
46589189827Snorby 
46689189827Snorby /* prototype defined in dvmrpd.h and shared with the kroute.c version */
46789189827Snorby u_int8_t
mask2prefixlen(in_addr_t ina)46889189827Snorby mask2prefixlen(in_addr_t ina)
46989189827Snorby {
47089189827Snorby 	if (ina == 0)
47189189827Snorby 		return (0);
47289189827Snorby 	else
47389189827Snorby 		return (33 - ffs(ntohl(ina)));
47489189827Snorby }
47589189827Snorby 
47689189827Snorby int
show_nbr_msg(struct imsg * imsg)47789189827Snorby show_nbr_msg(struct imsg *imsg)
47889189827Snorby {
47989189827Snorby 	struct ctl_nbr	*nbr;
48089189827Snorby 
48189189827Snorby 	switch (imsg->hdr.type) {
48289189827Snorby 	case IMSG_CTL_SHOW_NBR:
48389189827Snorby 		nbr = imsg->data;
48489189827Snorby 		printf("%-15s %-10s %-10s", inet_ntoa(nbr->id),
48589189827Snorby 		    print_nbr_state(nbr->state),
48689189827Snorby 		    fmt_timeframe_core(nbr->dead_timer));
48789189827Snorby 		printf("%-15s %-11s %s\n", inet_ntoa(nbr->addr),
48889189827Snorby 		    nbr->name, fmt_timeframe_core(nbr->uptime));
48989189827Snorby 		break;
49089189827Snorby 	case IMSG_CTL_END:
49189189827Snorby 		printf("\n");
49289189827Snorby 		return (1);
49389189827Snorby 	default:
49489189827Snorby 		break;
49589189827Snorby 	}
49689189827Snorby 
49789189827Snorby 	return (0);
49889189827Snorby }
49989189827Snorby 
50089189827Snorby const char *
print_dvmrp_options(u_int8_t opts)50189189827Snorby print_dvmrp_options(u_int8_t opts)
50289189827Snorby {
50389189827Snorby 	static char	optbuf[32];
50489189827Snorby 
50589189827Snorby 	snprintf(optbuf, sizeof(optbuf), "*|*|%s|%s|%s|%s|%s|%s",
50689189827Snorby 	    opts & DVMRP_CAP_NETMASK ? "N" : "-",
50789189827Snorby 	    opts & DVMRP_CAP_SNMP ? "S" : "-",
50889189827Snorby 	    opts & DVMRP_CAP_MTRACE ? "M" : "-",
50989189827Snorby 	    opts & DVMRP_CAP_GENID ? "G" : "-",
51089189827Snorby 	    opts & DVMRP_CAP_PRUNE ? "P" : "-",
51189189827Snorby 	    opts & DVMRP_CAP_LEAF ? "L" : "-");
51289189827Snorby 	return (optbuf);
51389189827Snorby }
51489189827Snorby 
51589189827Snorby int
show_nbr_detail_msg(struct imsg * imsg)51689189827Snorby show_nbr_detail_msg(struct imsg *imsg)
51789189827Snorby {
51889189827Snorby 	switch (imsg->hdr.type) {
51989189827Snorby 	case IMSG_CTL_SHOW_NBR:
52089189827Snorby 		break;
52189189827Snorby 	case IMSG_CTL_END:
52289189827Snorby 		printf("\n");
52389189827Snorby 		return (1);
52489189827Snorby 	default:
52589189827Snorby 		break;
52689189827Snorby 	}
52789189827Snorby 
52889189827Snorby 	return (0);
52989189827Snorby }
53089189827Snorby 
53189189827Snorby int
show_rib_msg(struct imsg * imsg)53289189827Snorby show_rib_msg(struct imsg *imsg)
53389189827Snorby {
53489189827Snorby 	struct ctl_rt	*rt;
53589189827Snorby 	char		*dstnet;
53689189827Snorby 
53789189827Snorby 	switch (imsg->hdr.type) {
53889189827Snorby 	case IMSG_CTL_SHOW_RIB:
53989189827Snorby 		rt = imsg->data;
54089189827Snorby 		if (asprintf(&dstnet, "%s/%d", inet_ntoa(rt->prefix),
54189189827Snorby 		    rt->prefixlen) == -1)
54289189827Snorby 			err(1, NULL);
54389189827Snorby 
54489189827Snorby 		printf("%-20s %-17s %-7d %-9s %9s\n", dstnet,
54589189827Snorby 		    inet_ntoa(rt->nexthop),
54689189827Snorby 		    rt->cost, rt->uptime == 0 ? "-" :
54789189827Snorby 		    fmt_timeframe_core(rt->uptime),
54889189827Snorby 		    rt->expire == 0 ? "00:00:00" :
54989189827Snorby 		    fmt_timeframe_core(rt->expire));
55089189827Snorby 		free(dstnet);
55189189827Snorby 
55289189827Snorby 		break;
55389189827Snorby 	case IMSG_CTL_END:
55489189827Snorby 		printf("\n");
55589189827Snorby 		return (1);
55689189827Snorby 	default:
55789189827Snorby 		break;
55889189827Snorby 	}
55989189827Snorby 
56089189827Snorby 	return (0);
56189189827Snorby }
56289189827Snorby 
56389189827Snorby int
show_rib_detail_msg(struct imsg * imsg)56489189827Snorby show_rib_detail_msg(struct imsg *imsg)
56589189827Snorby {
56689189827Snorby 
56789189827Snorby 	switch (imsg->hdr.type) {
56889189827Snorby 	case IMSG_CTL_SHOW_RIB:
56989189827Snorby 		break;
57089189827Snorby 	case IMSG_CTL_END:
57189189827Snorby 		printf("\n");
57289189827Snorby 		return (1);
57389189827Snorby 	default:
57489189827Snorby 		break;
57589189827Snorby 	}
57689189827Snorby 
57789189827Snorby 	return (0);
57889189827Snorby }
57989189827Snorby 
58089189827Snorby int
show_mfc_msg(struct imsg * imsg)58189189827Snorby show_mfc_msg(struct imsg *imsg)
58289189827Snorby {
58389189827Snorby 	char		 iname[IF_NAMESIZE];
58489189827Snorby 	char		 oname[IF_NAMESIZE] = "-";
58589189827Snorby 	struct ctl_mfc	*mfc;
58689189827Snorby 	int		 i;
58789189827Snorby 
58889189827Snorby 
58989189827Snorby 	switch (imsg->hdr.type) {
59089189827Snorby 	case IMSG_CTL_SHOW_MFC:
59189189827Snorby 		mfc = imsg->data;
59289189827Snorby 		if_indextoname(mfc->ifindex, iname);
59389189827Snorby 
59489189827Snorby 		/* search for first entry with ttl > 0 */
59589189827Snorby 		for (i = 0; i < MAXVIFS; i++) {
59689189827Snorby 			if (mfc->ttls[i] > 0) {
59789189827Snorby 				if_indextoname(i, oname);
59889189827Snorby 				i++;
59989189827Snorby 				break;
60089189827Snorby 			}
60189189827Snorby 		}
60289189827Snorby 
60389189827Snorby 		/* display first entry with uptime */
60489189827Snorby 		printf("%-16s ", inet_ntoa(mfc->group));
60589189827Snorby 		printf("%-16s %-9s %-9s %-4d %-10s %-10s\n",
60689189827Snorby 		    inet_ntoa(mfc->origin), iname, oname, mfc->ttls[i - 1],
60789189827Snorby 		    mfc->uptime == 0 ? "-" : fmt_timeframe_core(mfc->uptime),
60889189827Snorby 		    mfc->expire == 0 ? "-" : fmt_timeframe_core(mfc->expire));
60989189827Snorby 
61089189827Snorby 		/* display remaining entries with ttl > 0 */
61189189827Snorby 		for (; i < MAXVIFS; i++) {
61289189827Snorby 			if (mfc->ttls[i] > 0) {
61389189827Snorby 				if_indextoname(i, oname);
61489189827Snorby 				printf("%43s %-9s %-4d\n", " ", oname,
61589189827Snorby 				    mfc->ttls[i]);
61689189827Snorby 			}
61789189827Snorby 		}
61889189827Snorby 		break;
61989189827Snorby 	case IMSG_CTL_END:
62089189827Snorby 		printf("\n");
62189189827Snorby 		return (1);
62289189827Snorby 	default:
62389189827Snorby 		break;
62489189827Snorby 	}
62589189827Snorby 
62689189827Snorby 	return (0);
62789189827Snorby }
62889189827Snorby 
62989189827Snorby int
show_mfc_detail_msg(struct imsg * imsg)63089189827Snorby show_mfc_detail_msg(struct imsg *imsg)
63189189827Snorby {
63289189827Snorby 
63389189827Snorby 	switch (imsg->hdr.type) {
63489189827Snorby 	case IMSG_CTL_SHOW_MFC:
63589189827Snorby 		break;
63689189827Snorby 	case IMSG_CTL_END:
63789189827Snorby 		printf("\n");
63889189827Snorby 		return (1);
63989189827Snorby 	default:
64089189827Snorby 		break;
64189189827Snorby 	}
64289189827Snorby 
64389189827Snorby 	return (0);
64489189827Snorby }
64589189827Snorby 
6460f617141Sclaudio const struct if_status_description
6470f617141Sclaudio 		if_status_descriptions[] = LINK_STATE_DESCRIPTIONS;
64889189827Snorby 
64989189827Snorby const char *
get_linkstate(uint8_t if_type,int link_state)6509f69273fSstsp get_linkstate(uint8_t if_type, int link_state)
65189189827Snorby {
6520f617141Sclaudio 	const struct if_status_description *p;
6530f617141Sclaudio 	static char buf[8];
65489189827Snorby 
6550f617141Sclaudio 	for (p = if_status_descriptions; p->ifs_string != NULL; p++) {
6569f69273fSstsp 		if (LINK_STATE_DESC_MATCH(p, if_type, link_state))
6570f617141Sclaudio 			return (p->ifs_string);
65889189827Snorby 	}
6590f617141Sclaudio 	snprintf(buf, sizeof(buf), "[#%d]", link_state);
6600f617141Sclaudio 	return (buf);
66189189827Snorby }
662