xref: /openbsd/usr.sbin/ospfctl/ospfctl.c (revision c502c694)
1*c502c694Sdenis /*	$OpenBSD: ospfctl.c,v 1.68 2020/05/20 11:11:24 denis 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>
30c0dbf5cfSsthen #include <errno.h>
31b49634deSclaudio #include <stdio.h>
32b49634deSclaudio #include <stdlib.h>
33b49634deSclaudio #include <string.h>
34b49634deSclaudio #include <unistd.h>
35b49634deSclaudio 
36b49634deSclaudio #include "ospf.h"
37b49634deSclaudio #include "ospfd.h"
3887862bd3Sdenis #include "ospfctl.h"
39b49634deSclaudio #include "ospfe.h"
40b49634deSclaudio #include "parser.h"
41b49634deSclaudio 
42cbb557dbShenning __dead void	 usage(void);
4387862bd3Sdenis 
4487862bd3Sdenis int show(struct imsg *, struct parse_result *);
45b49634deSclaudio 
46b49634deSclaudio struct imsgbuf		*ibuf;
4787862bd3Sdenis const struct output	*output = &show_output;
48b49634deSclaudio 
49cbb557dbShenning __dead void
usage(void)50b49634deSclaudio usage(void)
51b49634deSclaudio {
52b49634deSclaudio 	extern char *__progname;
53b49634deSclaudio 
54d1b94773Sreyk 	fprintf(stderr, "usage: %s [-s socket] command [argument ...]\n",
55d1b94773Sreyk 	    __progname);
56b49634deSclaudio 	exit(1);
57b49634deSclaudio }
58b49634deSclaudio 
59b49634deSclaudio int
main(int argc,char * argv[])60b49634deSclaudio main(int argc, char *argv[])
61b49634deSclaudio {
62b49634deSclaudio 	struct sockaddr_un	 sun;
63b49634deSclaudio 	struct parse_result	*res;
64b49634deSclaudio 	struct imsg		 imsg;
65b49634deSclaudio 	unsigned int		 ifidx = 0;
66ec107b41Sremi 	int			 ctl_sock, r;
67b49634deSclaudio 	int			 done = 0;
68c3319070Sclaudio 	int			 n, verbose = 0;
69d1b94773Sreyk 	int			 ch;
70d1b94773Sreyk 	char			*sockname;
71d1b94773Sreyk 
72ec107b41Sremi 	r = getrtable();
73ec107b41Sremi 	if (asprintf(&sockname, "%s.%d", OSPFD_SOCKET, r) == -1)
74ec107b41Sremi 		err(1, "asprintf");
75ec107b41Sremi 
76d1b94773Sreyk 	while ((ch = getopt(argc, argv, "s:")) != -1) {
77d1b94773Sreyk 		switch (ch) {
78d1b94773Sreyk 		case 's':
79d1b94773Sreyk 			sockname = optarg;
80d1b94773Sreyk 			break;
81d1b94773Sreyk 		default:
82d1b94773Sreyk 			usage();
83d1b94773Sreyk 			/* NOTREACHED */
84d1b94773Sreyk 		}
85d1b94773Sreyk 	}
86d1b94773Sreyk 	argc -= optind;
87d1b94773Sreyk 	argv += optind;
88b49634deSclaudio 
89b49634deSclaudio 	/* parse options */
90d1b94773Sreyk 	if ((res = parse(argc, argv)) == NULL)
91b49634deSclaudio 		exit(1);
92b49634deSclaudio 
93b49634deSclaudio 	/* connect to ospfd control socket */
94b49634deSclaudio 	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
95b49634deSclaudio 		err(1, "socket");
96b49634deSclaudio 
97b49634deSclaudio 	bzero(&sun, sizeof(sun));
98b49634deSclaudio 	sun.sun_family = AF_UNIX;
99d1b94773Sreyk 	strlcpy(sun.sun_path, sockname, sizeof(sun.sun_path));
100cee51daaSflorian 
101b49634deSclaudio 	if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1)
102d1b94773Sreyk 		err(1, "connect: %s", sockname);
103b49634deSclaudio 
10468598ea0Sderaadt 	if (pledge("stdio", NULL) == -1)
10568598ea0Sderaadt 		err(1, "pledge");
10668598ea0Sderaadt 
107b49634deSclaudio 	if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
108d2141824Sstevesk 		err(1, NULL);
1097b4c0c10Seric 	imsg_init(ibuf, ctl_sock);
110b49634deSclaudio 	done = 0;
111b49634deSclaudio 
112b49634deSclaudio 	/* process user request */
113b49634deSclaudio 	switch (res->action) {
114b49634deSclaudio 	case NONE:
115b49634deSclaudio 		usage();
116b49634deSclaudio 		/* not reached */
117b49634deSclaudio 	case SHOW:
11859df52c7Snorby 	case SHOW_SUM:
1197f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_SUM, 0, 0, -1, NULL, 0);
120b49634deSclaudio 		break;
121b49634deSclaudio 	case SHOW_IFACE:
12212bb42a0Snorby 	case SHOW_IFACE_DTAIL:
123b49634deSclaudio 		if (*res->ifname) {
124b49634deSclaudio 			ifidx = if_nametoindex(res->ifname);
125b49634deSclaudio 			if (ifidx == 0)
126b49634deSclaudio 				errx(1, "no such interface %s", res->ifname);
127b49634deSclaudio 		}
1287f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1,
129b49634deSclaudio 		    &ifidx, sizeof(ifidx));
130b49634deSclaudio 		break;
131b49634deSclaudio 	case SHOW_NBR:
132b49634deSclaudio 	case SHOW_NBR_DTAIL:
1337f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0);
134b49634deSclaudio 		break;
135b49634deSclaudio 	case SHOW_DB:
1367f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1, NULL, 0);
137b49634deSclaudio 		break;
138b49634deSclaudio 	case SHOW_DBBYAREA:
1397f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1,
140b49634deSclaudio 		    &res->addr, sizeof(res->addr));
141b49634deSclaudio 		break;
14232286112Snorby 	case SHOW_DBEXT:
1437f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_EXT, 0, 0, -1, NULL, 0);
14432286112Snorby 		break;
14532286112Snorby 	case SHOW_DBNET:
1467f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_NET, 0, 0, -1, NULL, 0);
14732286112Snorby 		break;
14832286112Snorby 	case SHOW_DBRTR:
1497f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_RTR, 0, 0, -1, NULL, 0);
15032286112Snorby 		break;
15132286112Snorby 	case SHOW_DBSELF:
1527f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SELF, 0, 0, -1, NULL, 0);
15332286112Snorby 		break;
15432286112Snorby 	case SHOW_DBSUM:
1557f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SUM, 0, 0, -1, NULL, 0);
15632286112Snorby 		break;
15732286112Snorby 	case SHOW_DBASBR:
1587f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_ASBR, 0, 0, -1, NULL, 0);
15932286112Snorby 		break;
16097494e25Sclaudio 	case SHOW_DBOPAQ:
16197494e25Sclaudio 		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_OPAQ, 0, 0, -1, NULL, 0);
16297494e25Sclaudio 		break;
16337355230Snorby 	case SHOW_RIB:
16437355230Snorby 	case SHOW_RIB_DTAIL:
1657f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, -1, NULL, 0);
16637355230Snorby 		break;
167c47b7f65Sclaudio 	case SHOW_FIB:
168c47b7f65Sclaudio 		if (!res->addr.s_addr)
1697f472484Spyr 			imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0, -1,
170c47b7f65Sclaudio 			    &res->flags, sizeof(res->flags));
171c47b7f65Sclaudio 		else
1727f472484Spyr 			imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1,
173c47b7f65Sclaudio 			    &res->addr, sizeof(res->addr));
174c47b7f65Sclaudio 		break;
175c47b7f65Sclaudio 	case SHOW_FIB_IFACE:
1764c561fb6Sclaudio 		if (*res->ifname)
1777f472484Spyr 			imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1,
1784c561fb6Sclaudio 			    res->ifname, sizeof(res->ifname));
1794c561fb6Sclaudio 		else
1807f472484Spyr 			imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1, NULL, 0);
181c47b7f65Sclaudio 		break;
18273a141beSclaudio 	case FIB:
18373a141beSclaudio 		errx(1, "fib couple|decouple");
18473a141beSclaudio 		break;
18573a141beSclaudio 	case FIB_COUPLE:
1867f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, -1, NULL, 0);
18773a141beSclaudio 		printf("couple request sent.\n");
18873a141beSclaudio 		done = 1;
18973a141beSclaudio 		break;
19073a141beSclaudio 	case FIB_DECOUPLE:
1917f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, -1, NULL, 0);
19273a141beSclaudio 		printf("decouple request sent.\n");
19373a141beSclaudio 		done = 1;
19473a141beSclaudio 		break;
195119f0f1dSdlg 	case FIB_RELOAD:
196119f0f1dSdlg 		imsg_compose(ibuf, IMSG_CTL_FIB_RELOAD, 0, 0, -1, NULL, 0);
197119f0f1dSdlg 		printf("reload request sent.\n");
198119f0f1dSdlg 		done = 1;
199119f0f1dSdlg 		break;
200c3319070Sclaudio 	case LOG_VERBOSE:
201c3319070Sclaudio 		verbose = 1;
202c3319070Sclaudio 		/* FALLTHROUGH */
203c3319070Sclaudio 	case LOG_BRIEF:
204c3319070Sclaudio 		imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1,
205c3319070Sclaudio 		    &verbose, sizeof(verbose));
206c3319070Sclaudio 		printf("logging request sent.\n");
207c3319070Sclaudio 		done = 1;
208c3319070Sclaudio 		break;
209b49634deSclaudio 	case RELOAD:
2107f472484Spyr 		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0);
211b49634deSclaudio 		printf("reload request sent.\n");
212b49634deSclaudio 		done = 1;
213b49634deSclaudio 		break;
214b49634deSclaudio 	}
215b49634deSclaudio 
216b49634deSclaudio 	while (ibuf->w.queued)
217c0dbf5cfSsthen 		if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
218b49634deSclaudio 			err(1, "write error");
219b49634deSclaudio 
22087862bd3Sdenis 	/* no output for certain commands such as log verbose */
22187862bd3Sdenis 	if (!done) {
22287862bd3Sdenis 		output->head(res);
22387862bd3Sdenis 
224b49634deSclaudio 		while (!done) {
225cc37529cSclaudio 			if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
226b49634deSclaudio 				errx(1, "imsg_read error");
227b49634deSclaudio 			if (n == 0)
228b49634deSclaudio 				errx(1, "pipe closed");
229b49634deSclaudio 
230b49634deSclaudio 			while (!done) {
231b49634deSclaudio 				if ((n = imsg_get(ibuf, &imsg)) == -1)
232b49634deSclaudio 					errx(1, "imsg_get error");
233b49634deSclaudio 				if (n == 0)
234b49634deSclaudio 					break;
23587862bd3Sdenis 
23687862bd3Sdenis 				done = show(&imsg, res);
237b49634deSclaudio 				imsg_free(&imsg);
238b49634deSclaudio 			}
239b49634deSclaudio 		}
24087862bd3Sdenis 
24187862bd3Sdenis 		output->tail();
24287862bd3Sdenis 	}
24387862bd3Sdenis 
244b49634deSclaudio 	close(ctl_sock);
245b49634deSclaudio 	free(ibuf);
246b49634deSclaudio 
247b49634deSclaudio 	return (0);
248b49634deSclaudio }
249b49634deSclaudio 
250b49634deSclaudio int
show(struct imsg * imsg,struct parse_result * res)25187862bd3Sdenis show(struct imsg *imsg, struct parse_result *res)
252b49634deSclaudio {
25359df52c7Snorby 	struct ctl_sum		*sum;
25459df52c7Snorby 	struct ctl_sum_area	*sumarea;
25587862bd3Sdenis 	struct ctl_iface	*ctliface;
25687862bd3Sdenis 	struct ctl_nbr		*nbr;
25787862bd3Sdenis 	struct ctl_rt		*rt;
25887862bd3Sdenis 	struct kroute		*k;
25987862bd3Sdenis 	struct kif		*kif;
26087862bd3Sdenis 	static struct in_addr	 area_id;
26187862bd3Sdenis 	struct area		*area;
26287862bd3Sdenis 	static u_int8_t		 lasttype;
26387862bd3Sdenis 	static char		 ifname[IF_NAMESIZE];
26487862bd3Sdenis 	struct iface		*iface;
26587862bd3Sdenis 	struct lsa		*lsa;
26687862bd3Sdenis 	struct lsa_hdr		*lsa_hdr;
26759df52c7Snorby 
26859df52c7Snorby 	switch (imsg->hdr.type) {
26959df52c7Snorby 	case IMSG_CTL_SHOW_SUM:
27059df52c7Snorby 		sum = imsg->data;
27187862bd3Sdenis 		output->summary(sum);
27259df52c7Snorby 		break;
27359df52c7Snorby 	case IMSG_CTL_SHOW_SUM_AREA:
27459df52c7Snorby 		sumarea = imsg->data;
27587862bd3Sdenis 		output->summary_area(sumarea);
27687862bd3Sdenis 		break;
27787862bd3Sdenis 	case IMSG_CTL_SHOW_INTERFACE:
27887862bd3Sdenis 		ctliface = imsg->data;
27987862bd3Sdenis 		if(res->action == SHOW_IFACE_DTAIL)
28087862bd3Sdenis 			output->interface(ctliface, 1);
28187862bd3Sdenis 		else
28287862bd3Sdenis 			output->interface(ctliface, 0);
28387862bd3Sdenis 		break;
28487862bd3Sdenis 	case IMSG_CTL_SHOW_NBR:
28587862bd3Sdenis 		nbr = imsg->data;
28687862bd3Sdenis 		if(res->action == SHOW_NBR_DTAIL)
28787862bd3Sdenis 			output->neighbor(nbr, 1);
28887862bd3Sdenis 		else
28987862bd3Sdenis 			output->neighbor(nbr, 0);
29087862bd3Sdenis 		break;
29187862bd3Sdenis 	case IMSG_CTL_SHOW_RIB:
29287862bd3Sdenis 		rt = imsg->data;
29387862bd3Sdenis 		if(res->action == SHOW_RIB_DTAIL)
29487862bd3Sdenis 			output->rib(rt, 1);
29587862bd3Sdenis 		else
29687862bd3Sdenis 			output->rib(rt, 0);
29787862bd3Sdenis 		break;
29887862bd3Sdenis 	case IMSG_CTL_KROUTE:
29987862bd3Sdenis 		if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute))
30087862bd3Sdenis 			errx(1, "wrong imsg len");
30187862bd3Sdenis 		k = imsg->data;
30287862bd3Sdenis 		output->fib(k);
30387862bd3Sdenis 		break;
30487862bd3Sdenis 	case IMSG_CTL_IFINFO:
30587862bd3Sdenis 		kif = imsg->data;
30687862bd3Sdenis 		output->fib_interface(kif);
30787862bd3Sdenis 		break;
30887862bd3Sdenis 	case IMSG_CTL_SHOW_DB_EXT:
30987862bd3Sdenis 	case IMSG_CTL_SHOW_DB_NET:
31087862bd3Sdenis 	case IMSG_CTL_SHOW_DB_RTR:
31187862bd3Sdenis 	case IMSG_CTL_SHOW_DB_SUM:
31287862bd3Sdenis 	case IMSG_CTL_SHOW_DB_ASBR:
31387862bd3Sdenis 	case IMSG_CTL_SHOW_DB_OPAQ:
31487862bd3Sdenis 		lsa = imsg->data;
31587862bd3Sdenis 		output->db(lsa, area_id, lasttype, ifname);
31687862bd3Sdenis 		lasttype = lsa->hdr.type;
31787862bd3Sdenis 		break;
31887862bd3Sdenis 	case IMSG_CTL_SHOW_DATABASE:
31987862bd3Sdenis 	case IMSG_CTL_SHOW_DB_SELF:
32087862bd3Sdenis 		lsa_hdr = imsg->data;
32187862bd3Sdenis 		output->db_simple(lsa_hdr, area_id, lasttype, ifname);
32287862bd3Sdenis 		lasttype = lsa_hdr->type;
32387862bd3Sdenis 		break;
32487862bd3Sdenis 	case IMSG_CTL_AREA:
32587862bd3Sdenis 		area = imsg->data;
32687862bd3Sdenis 		area_id = area->id;
32787862bd3Sdenis 		lasttype = 0;
32887862bd3Sdenis 		break;
32987862bd3Sdenis 	case IMSG_CTL_IFACE:
33087862bd3Sdenis 		iface = imsg->data;
33187862bd3Sdenis 		strlcpy(ifname, iface->name, sizeof(ifname));
33287862bd3Sdenis 		lasttype = 0;
33359df52c7Snorby 		break;
33459df52c7Snorby 	case IMSG_CTL_END:
33559df52c7Snorby 		return (1);
33659df52c7Snorby 	default:
33787862bd3Sdenis 		warnx("unknown imsg %d received", imsg->hdr.type);
33859df52c7Snorby 		break;
33959df52c7Snorby 	}
340b49634deSclaudio 
341b49634deSclaudio 	return (0);
342b49634deSclaudio }
343b49634deSclaudio 
34418ffdd94Sstsp uint64_t
get_ifms_type(uint8_t if_type)34518ffdd94Sstsp get_ifms_type(uint8_t if_type)
3463caca30dSnorby {
34718ffdd94Sstsp 	switch (if_type) {
3483caca30dSnorby 	case IFT_ETHER:
3493caca30dSnorby 		return (IFM_ETHER);
3503caca30dSnorby 	case IFT_FDDI:
3513caca30dSnorby 		return (IFM_FDDI);
3523caca30dSnorby 	case IFT_CARP:
3533caca30dSnorby 		return (IFM_CARP);
354a5bcf77aSclaudio 	case IFT_PPP:
355a5bcf77aSclaudio 		return (IFM_TDM);
3563caca30dSnorby 	default:
3573caca30dSnorby 		return (0);
3583caca30dSnorby 	}
3593caca30dSnorby }
3603caca30dSnorby 
361b49634deSclaudio const char *
print_link(int state)362b49634deSclaudio print_link(int state)
363b49634deSclaudio {
364b49634deSclaudio 	if (state & IFF_UP)
365b49634deSclaudio 		return ("UP");
366b49634deSclaudio 	else
367b49634deSclaudio 		return ("DOWN");
368b49634deSclaudio }
369b49634deSclaudio 
370b49634deSclaudio #define TF_BUFS	8
371b49634deSclaudio #define TF_LEN	9
372b49634deSclaudio 
373b49634deSclaudio const char *
fmt_timeframe_core(time_t t)374b49634deSclaudio fmt_timeframe_core(time_t t)
375b49634deSclaudio {
376b49634deSclaudio 	char			*buf;
377b49634deSclaudio 	static char		 tfbuf[TF_BUFS][TF_LEN];/* ring buffer */
378b49634deSclaudio 	static int		 idx = 0;
379035b0708Sgilles 	unsigned int		 sec, min, hrs, day;
380035b0708Sgilles 	unsigned long long	 week;
381b49634deSclaudio 
382b49634deSclaudio 	if (t == 0)
38311c16ffaSnorby 		return ("00:00:00");
384b49634deSclaudio 
385b49634deSclaudio 	buf = tfbuf[idx++];
386b49634deSclaudio 	if (idx == TF_BUFS)
387b49634deSclaudio 		idx = 0;
388b49634deSclaudio 
389b49634deSclaudio 	week = t;
390b49634deSclaudio 
391b49634deSclaudio 	sec = week % 60;
392b49634deSclaudio 	week /= 60;
393b49634deSclaudio 	min = week % 60;
394b49634deSclaudio 	week /= 60;
395b49634deSclaudio 	hrs = week % 24;
396b49634deSclaudio 	week /= 24;
397b49634deSclaudio 	day = week % 7;
398b49634deSclaudio 	week /= 7;
399b49634deSclaudio 
400b49634deSclaudio 	if (week > 0)
401035b0708Sgilles 		snprintf(buf, TF_LEN, "%02lluw%01ud%02uh", week, day, hrs);
402b49634deSclaudio 	else if (day > 0)
403b49634deSclaudio 		snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
404b49634deSclaudio 	else
405b49634deSclaudio 		snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
406b49634deSclaudio 
407b49634deSclaudio 	return (buf);
408b49634deSclaudio }
409b49634deSclaudio 
410b49634deSclaudio const char *
log_id(u_int32_t id)411b49634deSclaudio log_id(u_int32_t id)
412b49634deSclaudio {
413b49634deSclaudio 	static char	buf[48];
414b49634deSclaudio 	struct in_addr	addr;
415b49634deSclaudio 
416b49634deSclaudio 	addr.s_addr = id;
417b49634deSclaudio 
418b49634deSclaudio 	if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL)
419b49634deSclaudio 		return ("?");
420b49634deSclaudio 	else
421b49634deSclaudio 		return (buf);
422b49634deSclaudio }
423b49634deSclaudio 
424b49634deSclaudio const char *
log_adv_rtr(u_int32_t adv_rtr)425b49634deSclaudio log_adv_rtr(u_int32_t adv_rtr)
426b49634deSclaudio {
427b49634deSclaudio 	static char	buf[48];
428b49634deSclaudio 	struct in_addr	addr;
429b49634deSclaudio 
430b49634deSclaudio 	addr.s_addr = adv_rtr;
431b49634deSclaudio 
432b49634deSclaudio 	if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL)
433b49634deSclaudio 		return ("?");
434b49634deSclaudio 	else
435b49634deSclaudio 		return (buf);
436b49634deSclaudio }
437b49634deSclaudio 
4383ec0d80eSclaudio /* prototype defined in ospfd.h and shared with the kroute.c version */
439b49634deSclaudio u_int8_t
mask2prefixlen(in_addr_t ina)4403ec0d80eSclaudio mask2prefixlen(in_addr_t ina)
441b49634deSclaudio {
4423ec0d80eSclaudio 	if (ina == 0)
443b49634deSclaudio 		return (0);
444b49634deSclaudio 	else
4453ec0d80eSclaudio 		return (33 - ffs(ntohl(ina)));
446b49634deSclaudio }
447b49634deSclaudio 
44832286112Snorby char *
print_ls_type(u_int8_t type)44932286112Snorby print_ls_type(u_int8_t type)
45032286112Snorby {
45132286112Snorby 	switch (type) {
45232286112Snorby 	case LSA_TYPE_ROUTER:
45332286112Snorby 		return ("Router");
45432286112Snorby 	case LSA_TYPE_NETWORK:
45532286112Snorby 		return ("Network");
45632286112Snorby 	case LSA_TYPE_SUM_NETWORK:
45732286112Snorby 		return ("Summary (Network)");
45832286112Snorby 	case LSA_TYPE_SUM_ROUTER:
45932286112Snorby 		return ("Summary (Router)");
46032286112Snorby 	case LSA_TYPE_EXTERNAL:
46132286112Snorby 		return ("AS External");
46297494e25Sclaudio 	case LSA_TYPE_LINK_OPAQ:
46397494e25Sclaudio 		return ("Type-9 Opaque");
46497494e25Sclaudio 	case LSA_TYPE_AREA_OPAQ:
46597494e25Sclaudio 		return ("Type-10 Opaque");
46697494e25Sclaudio 	case LSA_TYPE_AS_OPAQ:
46797494e25Sclaudio 		return ("Type-11 Opaque");
46832286112Snorby 	default:
46932286112Snorby 		return ("Unknown");
47032286112Snorby 	}
47132286112Snorby }
47232286112Snorby 
47332286112Snorby char *
print_rtr_link_type(u_int8_t type)47432286112Snorby print_rtr_link_type(u_int8_t type)
47532286112Snorby {
47632286112Snorby 	switch (type) {
47732286112Snorby 	case LINK_TYPE_POINTTOPOINT:
47832286112Snorby 		return ("Point-to-Point");
47932286112Snorby 	case LINK_TYPE_TRANSIT_NET:
48032286112Snorby 		return ("Transit Network");
48132286112Snorby 	case LINK_TYPE_STUB_NET:
48232286112Snorby 		return ("Stub Network");
48332286112Snorby 	case LINK_TYPE_VIRTUAL:
48432286112Snorby 		return ("Virtual Link");
48532286112Snorby 	default:
48632286112Snorby 		return ("Unknown");
48732286112Snorby 	}
48832286112Snorby }
48932286112Snorby 
49032286112Snorby const char *
print_ospf_flags(u_int8_t opts)49132286112Snorby print_ospf_flags(u_int8_t opts)
49232286112Snorby {
49332286112Snorby 	static char	optbuf[32];
49432286112Snorby 
49532286112Snorby 	snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s",
49632286112Snorby 	    opts & OSPF_RTR_V ? "V" : "-",
49732286112Snorby 	    opts & OSPF_RTR_E ? "E" : "-",
49832286112Snorby 	    opts & OSPF_RTR_B ? "B" : "-");
49932286112Snorby 	return (optbuf);
50032286112Snorby }
50132286112Snorby 
502b49634deSclaudio const char *
print_ospf_options(u_int8_t opts)503b49634deSclaudio print_ospf_options(u_int8_t opts)
504b49634deSclaudio {
505b49634deSclaudio 	static char	optbuf[32];
506b49634deSclaudio 
50797494e25Sclaudio 	snprintf(optbuf, sizeof(optbuf), "%s|%s|%s|%s|%s|%s|%s|%s",
50897494e25Sclaudio 	    opts & OSPF_OPTION_DN ? "DN" : "-",
50997494e25Sclaudio 	    opts & OSPF_OPTION_O ? "O" : "-",
510b49634deSclaudio 	    opts & OSPF_OPTION_DC ? "DC" : "-",
511b49634deSclaudio 	    opts & OSPF_OPTION_EA ? "EA" : "-",
512b49634deSclaudio 	    opts & OSPF_OPTION_NP ? "N/P" : "-",
513b49634deSclaudio 	    opts & OSPF_OPTION_MC ? "MC" : "-",
51497494e25Sclaudio 	    opts & OSPF_OPTION_E ? "E" : "-",
51597494e25Sclaudio 	    opts & OSPF_OPTION_MT ? "MT" : "-");
516b49634deSclaudio 	return (optbuf);
517b49634deSclaudio }
518b49634deSclaudio 
51991e3b0aeSnorby const char *
print_ospf_rtr_flags(u_int8_t opts)52091e3b0aeSnorby print_ospf_rtr_flags(u_int8_t opts)
52191e3b0aeSnorby {
52291e3b0aeSnorby 	static char	optbuf[32];
52391e3b0aeSnorby 
52491e3b0aeSnorby 	snprintf(optbuf, sizeof(optbuf), "%s%s%s",
52591e3b0aeSnorby 	    opts & OSPF_RTR_E ? "AS" : "",
52691e3b0aeSnorby 	    opts & OSPF_RTR_E && opts & OSPF_RTR_B ? "+" : "",
52791e3b0aeSnorby 	    opts & OSPF_RTR_B ? "ABR" : "");
52891e3b0aeSnorby 	return (optbuf);
52937355230Snorby }
53037355230Snorby 
5310f617141Sclaudio const struct if_status_description
5320f617141Sclaudio 		if_status_descriptions[] = LINK_STATE_DESCRIPTIONS;
533c47b7f65Sclaudio const struct ifmedia_description
534c47b7f65Sclaudio 		ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS;
535c47b7f65Sclaudio 
536c47b7f65Sclaudio const char *
get_media_descr(uint64_t media_type)537e5605ae3Sderaadt get_media_descr(uint64_t media_type)
538c47b7f65Sclaudio {
539c47b7f65Sclaudio 	const struct ifmedia_description	*p;
540c47b7f65Sclaudio 
541c47b7f65Sclaudio 	for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++)
542c47b7f65Sclaudio 		if (media_type == p->ifmt_word)
543c47b7f65Sclaudio 			return (p->ifmt_string);
544c47b7f65Sclaudio 
545a5bcf77aSclaudio 	return ("unknown");
546c47b7f65Sclaudio }
547c47b7f65Sclaudio 
548c47b7f65Sclaudio const char *
get_linkstate(uint8_t if_type,int link_state)54918ffdd94Sstsp get_linkstate(uint8_t if_type, int link_state)
550c47b7f65Sclaudio {
5510f617141Sclaudio 	const struct if_status_description *p;
5520f617141Sclaudio 	static char buf[8];
553c47b7f65Sclaudio 
5540f617141Sclaudio 	for (p = if_status_descriptions; p->ifs_string != NULL; p++) {
55518ffdd94Sstsp 		if (LINK_STATE_DESC_MATCH(p, if_type, link_state))
5560f617141Sclaudio 			return (p->ifs_string);
557c47b7f65Sclaudio 	}
5580f617141Sclaudio 	snprintf(buf, sizeof(buf), "[#%d]", link_state);
5590f617141Sclaudio 	return (buf);
560c47b7f65Sclaudio }
561c47b7f65Sclaudio 
56287862bd3Sdenis const char *
print_baudrate(u_int64_t baudrate)56356babc06Sclaudio print_baudrate(u_int64_t baudrate)
564c47b7f65Sclaudio {
56587862bd3Sdenis 	static char	buf[32];
566*c502c694Sdenis 
567c47b7f65Sclaudio 	if (baudrate > IF_Gbps(1))
56887862bd3Sdenis 		snprintf(buf, sizeof(buf), "%llu GBit/s", baudrate / IF_Gbps(1));
569c47b7f65Sclaudio 	else if (baudrate > IF_Mbps(1))
57087862bd3Sdenis 		snprintf(buf, sizeof(buf), "%llu MBit/s", baudrate / IF_Mbps(1));
571c47b7f65Sclaudio 	else if (baudrate > IF_Kbps(1))
57287862bd3Sdenis 		snprintf(buf, sizeof(buf), "%llu KBit/s", baudrate / IF_Kbps(1));
573c47b7f65Sclaudio 	else
57487862bd3Sdenis 		snprintf(buf, sizeof(buf), "%llu Bit/s", baudrate);
57587862bd3Sdenis 	return (buf);
576c47b7f65Sclaudio }
577