xref: /openbsd-src/usr.sbin/ldpctl/ldpctl.c (revision f1b790a5738b7375271fee81f99119b1f82f2cfd)
1*f1b790a5Sclaudio /*	$OpenBSD: ldpctl.c,v 1.37 2024/11/21 13:38:14 claudio Exp $
2ab0c2486Smichele  *
3ab0c2486Smichele  * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
4ab0c2486Smichele  * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
5ab0c2486Smichele  * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
6ab0c2486Smichele  * Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
7ab0c2486Smichele  *
8ab0c2486Smichele  * Permission to use, copy, modify, and distribute this software for any
9ab0c2486Smichele  * purpose with or without fee is hereby granted, provided that the above
10ab0c2486Smichele  * copyright notice and this permission notice appear in all copies.
11ab0c2486Smichele  *
12ab0c2486Smichele  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13ab0c2486Smichele  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14ab0c2486Smichele  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15ab0c2486Smichele  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16ab0c2486Smichele  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17ab0c2486Smichele  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18ab0c2486Smichele  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19ab0c2486Smichele  */
20ab0c2486Smichele 
21ab0c2486Smichele #include <sys/types.h>
22ab0c2486Smichele #include <sys/socket.h>
23ab0c2486Smichele #include <sys/un.h>
24ab0c2486Smichele #include <netinet/in.h>
25ab0c2486Smichele #include <arpa/inet.h>
26ab0c2486Smichele #include <net/if_media.h>
27ab0c2486Smichele #include <net/if_types.h>
28ab0c2486Smichele #include <netmpls/mpls.h>
29ab0c2486Smichele 
30ab0c2486Smichele #include <err.h>
31397afdbcSderaadt #include <errno.h>
32ab0c2486Smichele #include <stdio.h>
33ab0c2486Smichele #include <stdlib.h>
34ab0c2486Smichele #include <string.h>
35ab0c2486Smichele #include <unistd.h>
36bdfaf4b1Sderaadt #include <limits.h>
37ab0c2486Smichele 
38ab0c2486Smichele #include "ldp.h"
39ab0c2486Smichele #include "ldpd.h"
40ab0c2486Smichele #include "ldpe.h"
416fb6d103Srenato #include "log.h"
42ab0c2486Smichele #include "parser.h"
43ab0c2486Smichele 
44ab0c2486Smichele __dead void	 usage(void);
45ab0c2486Smichele const char	*fmt_timeframe_core(time_t);
460f882be7Sstsp const char	*get_linkstate(uint8_t, int);
476fb6d103Srenato int		 show_interface_msg(struct imsg *, struct parse_result *);
486fb6d103Srenato int		 show_discovery_msg(struct imsg *, struct parse_result *);
490f882be7Sstsp uint64_t	 get_ifms_type(uint8_t);
506fb6d103Srenato int		 show_lib_msg(struct imsg *, struct parse_result *);
516fb6d103Srenato int		 show_nbr_msg(struct imsg *, struct parse_result *);
5292dd8dc8Sclaudio void		 show_fib_head(void);
536fb6d103Srenato int		 show_fib_msg(struct imsg *, struct parse_result *);
54ab0c2486Smichele void		 show_interface_head(void);
5592dd8dc8Sclaudio int		 show_fib_interface_msg(struct imsg *);
56a94c7fd0Srenato int		 show_l2vpn_pw_msg(struct imsg *);
57a94c7fd0Srenato int		 show_l2vpn_binding_msg(struct imsg *);
58e5605ae3Sderaadt const char	*get_media_descr(uint64_t);
596c1e7e28Srenato void		 print_baudrate(uint64_t);
60ab0c2486Smichele 
61ab0c2486Smichele struct imsgbuf	*ibuf;
62ab0c2486Smichele 
63ab0c2486Smichele __dead void
64ab0c2486Smichele usage(void)
65ab0c2486Smichele {
66ab0c2486Smichele 	extern char *__progname;
67ab0c2486Smichele 
68ab0c2486Smichele 	fprintf(stderr, "usage: %s command [argument ...]\n", __progname);
69ab0c2486Smichele 	exit(1);
70ab0c2486Smichele }
71ab0c2486Smichele 
72ab0c2486Smichele int
73ab0c2486Smichele main(int argc, char *argv[])
74ab0c2486Smichele {
75ab0c2486Smichele 	struct sockaddr_un	 sun;
76ab0c2486Smichele 	struct parse_result	*res;
77ab0c2486Smichele 	struct imsg		 imsg;
78ab0c2486Smichele 	unsigned int		 ifidx = 0;
796fb6d103Srenato 	struct kroute		 kr;
80ab0c2486Smichele 	int			 ctl_sock;
81c3319070Sclaudio 	int			 done = 0, verbose = 0;
82ab0c2486Smichele 	int			 n;
833f117ed9Srenato 	struct ctl_nbr		 nbr;
84ab0c2486Smichele 
85ab0c2486Smichele 	/* parse options */
86ab0c2486Smichele 	if ((res = parse(argc - 1, argv + 1)) == NULL)
87ab0c2486Smichele 		exit(1);
88ab0c2486Smichele 
89ab0c2486Smichele 	/* connect to ldpd control socket */
90ab0c2486Smichele 	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
91ab0c2486Smichele 		err(1, "socket");
92ab0c2486Smichele 
9324d93a00Srenato 	memset(&sun, 0, sizeof(sun));
94ab0c2486Smichele 	sun.sun_family = AF_UNIX;
95ab0c2486Smichele 	strlcpy(sun.sun_path, LDPD_SOCKET, sizeof(sun.sun_path));
96ab0c2486Smichele 	if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1)
97ab0c2486Smichele 		err(1, "connect: %s", LDPD_SOCKET);
98ab0c2486Smichele 
997ce073efSrenato 	if (pledge("stdio", NULL) == -1)
1007ce073efSrenato 		err(1, "pledge");
1017ce073efSrenato 
102ab0c2486Smichele 	if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
103ab0c2486Smichele 		err(1, NULL);
104*f1b790a5Sclaudio 	if (imsgbuf_init(ibuf, ctl_sock) == -1)
105*f1b790a5Sclaudio 		err(1, NULL);
106ab0c2486Smichele 	done = 0;
107ab0c2486Smichele 
108ab0c2486Smichele 	/* process user request */
109ab0c2486Smichele 	switch (res->action) {
110ab0c2486Smichele 	case NONE:
111ab0c2486Smichele 		usage();
112ab0c2486Smichele 		/* not reached */
113ab0c2486Smichele 	case SHOW:
114ab0c2486Smichele 	case SHOW_IFACE:
1156fb6d103Srenato 		printf("%-4s %-11s %-6s %-10s %-8s %-12s %3s\n",
1166fb6d103Srenato 		    "AF", "Interface", "State", "Linkstate", "Uptime",
117905cf379Sclaudio 		    "Hello Timers", "ac");
118ab0c2486Smichele 		if (*res->ifname) {
119ab0c2486Smichele 			ifidx = if_nametoindex(res->ifname);
120ab0c2486Smichele 			if (ifidx == 0)
121ab0c2486Smichele 				errx(1, "no such interface %s", res->ifname);
122ab0c2486Smichele 		}
12302ff519fSmichele 		imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1,
124ab0c2486Smichele 		    &ifidx, sizeof(ifidx));
125ab0c2486Smichele 		break;
126d50436bbSclaudio 	case SHOW_DISC:
1276fb6d103Srenato 		printf("%-4s %-15s %-8s %-15s %9s\n",
1286fb6d103Srenato 		    "AF", "ID", "Type", "Source", "Holdtime");
129d50436bbSclaudio 		imsg_compose(ibuf, IMSG_CTL_SHOW_DISCOVERY, 0, 0, -1,
130d50436bbSclaudio 		    NULL, 0);
131d50436bbSclaudio 		break;
132ab0c2486Smichele 	case SHOW_NBR:
1336fb6d103Srenato 		printf("%-4s %-15s %-11s %-15s %8s\n",
1346fb6d103Srenato 		    "AF", "ID", "State", "Remote Address", "Uptime");
13502ff519fSmichele 		imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0);
136ab0c2486Smichele 		break;
137ab0c2486Smichele 	case SHOW_LIB:
1386fb6d103Srenato 		printf("%-4s %-20s %-15s %-11s %-13s %6s\n", "AF",
1396fb6d103Srenato 		    "Destination", "Nexthop", "Local Label", "Remote Label",
1406fb6d103Srenato 		    "In Use");
14102ff519fSmichele 		imsg_compose(ibuf, IMSG_CTL_SHOW_LIB, 0, 0, -1, NULL, 0);
142ab0c2486Smichele 		break;
14392dd8dc8Sclaudio 	case SHOW_FIB:
1446fb6d103Srenato 		if (!ldp_addrisset(res->family, &res->addr))
14502ff519fSmichele 			imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0, -1,
146ab0c2486Smichele 			    &res->flags, sizeof(res->flags));
1476fb6d103Srenato 		else {
1486fb6d103Srenato 			memset(&kr, 0, sizeof(kr));
1496fb6d103Srenato 			kr.af = res->family;
1506fb6d103Srenato 			kr.prefix = res->addr;
15102ff519fSmichele 			imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1,
1526fb6d103Srenato 			    &kr, sizeof(kr));
1536fb6d103Srenato 		}
15492dd8dc8Sclaudio 		show_fib_head();
155ab0c2486Smichele 		break;
15692dd8dc8Sclaudio 	case SHOW_FIB_IFACE:
157ab0c2486Smichele 		if (*res->ifname)
15802ff519fSmichele 			imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1,
159ab0c2486Smichele 			    res->ifname, sizeof(res->ifname));
160ab0c2486Smichele 		else
16102ff519fSmichele 			imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1, NULL, 0);
162ab0c2486Smichele 		show_interface_head();
163ab0c2486Smichele 		break;
164a94c7fd0Srenato 	case SHOW_L2VPN_PW:
165a94c7fd0Srenato 		printf("%-11s %-15s %-14s %-10s\n",
166a94c7fd0Srenato 		    "Interface", "Neighbor", "PWID", "Status");
167a94c7fd0Srenato 		imsg_compose(ibuf, IMSG_CTL_SHOW_L2VPN_PW, 0, 0, -1, NULL, 0);
168a94c7fd0Srenato 		break;
169a94c7fd0Srenato 	case SHOW_L2VPN_BINDING:
170a94c7fd0Srenato 		imsg_compose(ibuf, IMSG_CTL_SHOW_L2VPN_BINDING, 0, 0, -1,
171a94c7fd0Srenato 		    NULL, 0);
172a94c7fd0Srenato 		break;
1733f117ed9Srenato 	case CLEAR_NBR:
1743f117ed9Srenato 		memset(&nbr, 0, sizeof(nbr));
1753f117ed9Srenato 		nbr.af = res->family;
1763f117ed9Srenato 		memcpy(&nbr.raddr, &res->addr, sizeof(nbr.raddr));
1773f117ed9Srenato 		imsg_compose(ibuf, IMSG_CTL_CLEAR_NBR, 0, 0, -1, &nbr,
1783f117ed9Srenato 		    sizeof(nbr));
1793f117ed9Srenato 		done = 1;
1803f117ed9Srenato 		break;
18192dd8dc8Sclaudio 	case FIB:
18292dd8dc8Sclaudio 		errx(1, "fib couple|decouple");
183ab0c2486Smichele 		break;
18492dd8dc8Sclaudio 	case FIB_COUPLE:
18592dd8dc8Sclaudio 		imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, -1, NULL, 0);
186ab0c2486Smichele 		printf("couple request sent.\n");
187ab0c2486Smichele 		done = 1;
188ab0c2486Smichele 		break;
18992dd8dc8Sclaudio 	case FIB_DECOUPLE:
19092dd8dc8Sclaudio 		imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, -1, NULL, 0);
191ab0c2486Smichele 		printf("decouple request sent.\n");
192ab0c2486Smichele 		done = 1;
193ab0c2486Smichele 		break;
194c3319070Sclaudio 	case LOG_VERBOSE:
195c3319070Sclaudio 		verbose = 1;
196c3319070Sclaudio 		/* FALLTHROUGH */
197c3319070Sclaudio 	case LOG_BRIEF:
198c3319070Sclaudio 		imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1,
199c3319070Sclaudio 		    &verbose, sizeof(verbose));
200c3319070Sclaudio 		printf("logging request sent.\n");
201c3319070Sclaudio 		done = 1;
202c3319070Sclaudio 		break;
203ab0c2486Smichele 	case RELOAD:
20402ff519fSmichele 		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0);
205ab0c2486Smichele 		printf("reload request sent.\n");
206ab0c2486Smichele 		done = 1;
207ab0c2486Smichele 		break;
208ab0c2486Smichele 	}
209ab0c2486Smichele 
210dd7efffeSclaudio 	if (imsgbuf_flush(ibuf) == -1)
211ab0c2486Smichele 		err(1, "write error");
212ab0c2486Smichele 
213ab0c2486Smichele 	while (!done) {
214668e5ba9Sclaudio 		if ((n = imsgbuf_read(ibuf)) == -1)
215ef2e27a1Sclaudio 			err(1, "read error");
216ab0c2486Smichele 		if (n == 0)
217ab0c2486Smichele 			errx(1, "pipe closed");
218ab0c2486Smichele 
219ab0c2486Smichele 		while (!done) {
220ab0c2486Smichele 			if ((n = imsg_get(ibuf, &imsg)) == -1)
221ab0c2486Smichele 				errx(1, "imsg_get error");
222ab0c2486Smichele 			if (n == 0)
223ab0c2486Smichele 				break;
224ab0c2486Smichele 			switch (res->action) {
225ab0c2486Smichele 			case SHOW:
226ab0c2486Smichele 			case SHOW_IFACE:
2276fb6d103Srenato 				done = show_interface_msg(&imsg, res);
228ab0c2486Smichele 				break;
229d50436bbSclaudio 			case SHOW_DISC:
2306fb6d103Srenato 				done = show_discovery_msg(&imsg, res);
231d50436bbSclaudio 				break;
232ab0c2486Smichele 			case SHOW_NBR:
2336fb6d103Srenato 				done = show_nbr_msg(&imsg, res);
234ab0c2486Smichele 				break;
235ab0c2486Smichele 			case SHOW_LIB:
2366fb6d103Srenato 				done = show_lib_msg(&imsg, res);
237ab0c2486Smichele 				break;
23892dd8dc8Sclaudio 			case SHOW_FIB:
2396fb6d103Srenato 				done = show_fib_msg(&imsg, res);
240ab0c2486Smichele 				break;
24192dd8dc8Sclaudio 			case SHOW_FIB_IFACE:
24292dd8dc8Sclaudio 				done = show_fib_interface_msg(&imsg);
243ab0c2486Smichele 				break;
244a94c7fd0Srenato 			case SHOW_L2VPN_PW:
245a94c7fd0Srenato 				done = show_l2vpn_pw_msg(&imsg);
246a94c7fd0Srenato 				break;
247a94c7fd0Srenato 			case SHOW_L2VPN_BINDING:
248a94c7fd0Srenato 				done = show_l2vpn_binding_msg(&imsg);
249a94c7fd0Srenato 				break;
250ab0c2486Smichele 			case NONE:
2513f117ed9Srenato 			case CLEAR_NBR:
25292dd8dc8Sclaudio 			case FIB:
25392dd8dc8Sclaudio 			case FIB_COUPLE:
25492dd8dc8Sclaudio 			case FIB_DECOUPLE:
255c3319070Sclaudio 			case LOG_VERBOSE:
256c3319070Sclaudio 			case LOG_BRIEF:
257ab0c2486Smichele 			case RELOAD:
258ab0c2486Smichele 				break;
259ab0c2486Smichele 			}
260ab0c2486Smichele 			imsg_free(&imsg);
261ab0c2486Smichele 		}
262ab0c2486Smichele 	}
263ab0c2486Smichele 	close(ctl_sock);
264ab0c2486Smichele 	free(ibuf);
265ab0c2486Smichele 
266ab0c2486Smichele 	return (0);
267ab0c2486Smichele }
268ab0c2486Smichele 
2690f882be7Sstsp uint64_t
2700f882be7Sstsp get_ifms_type(uint8_t if_type)
271ab0c2486Smichele {
2720f882be7Sstsp 	switch (if_type) {
273ab0c2486Smichele 	case IFT_ETHER:
274ab0c2486Smichele 		return (IFM_ETHER);
275ab0c2486Smichele 		break;
276ab0c2486Smichele 	case IFT_FDDI:
277ab0c2486Smichele 		return (IFM_FDDI);
278ab0c2486Smichele 		break;
279ab0c2486Smichele 	case IFT_CARP:
280ab0c2486Smichele 		return (IFM_CARP);
281ab0c2486Smichele 		break;
282ab0c2486Smichele 	default:
283ab0c2486Smichele 		return (0);
284ab0c2486Smichele 		break;
285ab0c2486Smichele 	}
286ab0c2486Smichele }
287ab0c2486Smichele 
288ab0c2486Smichele #define	TF_BUFS	8
289ab0c2486Smichele #define	TF_LEN	9
290ab0c2486Smichele 
291ab0c2486Smichele const char *
292ab0c2486Smichele fmt_timeframe_core(time_t t)
293ab0c2486Smichele {
294ab0c2486Smichele 	char		*buf;
295ab0c2486Smichele 	static char	 tfbuf[TF_BUFS][TF_LEN];	/* ring buffer */
296ab0c2486Smichele 	static int	 idx = 0;
297ab0c2486Smichele 	unsigned int	 sec, min, hrs, day, week;
298ab0c2486Smichele 
299ab0c2486Smichele 	if (t == 0)
300ab0c2486Smichele 		return ("Stopped");
301ab0c2486Smichele 
302ab0c2486Smichele 	buf = tfbuf[idx++];
303ab0c2486Smichele 	if (idx == TF_BUFS)
304ab0c2486Smichele 		idx = 0;
305ab0c2486Smichele 
306ab0c2486Smichele 	week = t;
307ab0c2486Smichele 
308ab0c2486Smichele 	sec = week % 60;
309ab0c2486Smichele 	week /= 60;
310ab0c2486Smichele 	min = week % 60;
311ab0c2486Smichele 	week /= 60;
312ab0c2486Smichele 	hrs = week % 24;
313ab0c2486Smichele 	week /= 24;
314ab0c2486Smichele 	day = week % 7;
315ab0c2486Smichele 	week /= 7;
316ab0c2486Smichele 
317ab0c2486Smichele 	if (week > 0)
318ab0c2486Smichele 		snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs);
319ab0c2486Smichele 	else if (day > 0)
320ab0c2486Smichele 		snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
321ab0c2486Smichele 	else
322ab0c2486Smichele 		snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
323ab0c2486Smichele 
324ab0c2486Smichele 	return (buf);
325ab0c2486Smichele }
326ab0c2486Smichele 
327ab0c2486Smichele int
3286fb6d103Srenato show_interface_msg(struct imsg *imsg, struct parse_result *res)
329ab0c2486Smichele {
330ab0c2486Smichele 	struct ctl_iface	*iface;
331905cf379Sclaudio 	char			*timers;
332ab0c2486Smichele 
333ab0c2486Smichele 	switch (imsg->hdr.type) {
334ab0c2486Smichele 	case IMSG_CTL_SHOW_INTERFACE:
335ab0c2486Smichele 		iface = imsg->data;
336ab0c2486Smichele 
3376fb6d103Srenato 		if (res->family != AF_UNSPEC && res->family != iface->af)
3386fb6d103Srenato 			break;
3396fb6d103Srenato 
340905cf379Sclaudio 		if (asprintf(&timers, "%u/%u", iface->hello_interval,
341905cf379Sclaudio 		    iface->hello_holdtime) == -1)
342ab0c2486Smichele 			err(1, NULL);
343905cf379Sclaudio 
3446fb6d103Srenato 		printf("%-4s %-11s %-6s %-10s %-8s %-12s %3u\n",
3456fb6d103Srenato 		    af_name(iface->af), iface->name,
3466fb6d103Srenato 		    if_state_name(iface->state), get_linkstate(iface->if_type,
3476fb6d103Srenato 		    iface->linkstate), iface->uptime == 0 ? "00:00:00" :
3486fb6d103Srenato 		    fmt_timeframe_core(iface->uptime), timers, iface->adj_cnt);
349905cf379Sclaudio 		free(timers);
350ab0c2486Smichele 		break;
351ab0c2486Smichele 	case IMSG_CTL_END:
352ab0c2486Smichele 		printf("\n");
353ab0c2486Smichele 		return (1);
354ab0c2486Smichele 	default:
355ab0c2486Smichele 		break;
356ab0c2486Smichele 	}
357ab0c2486Smichele 
358ab0c2486Smichele 	return (0);
359ab0c2486Smichele }
360ab0c2486Smichele 
361ab0c2486Smichele int
3626fb6d103Srenato show_discovery_msg(struct imsg *imsg, struct parse_result *res)
363d50436bbSclaudio {
364d50436bbSclaudio 	struct ctl_adj	*adj;
3656fb6d103Srenato 	const char	*addr;
366d50436bbSclaudio 
367d50436bbSclaudio 	switch (imsg->hdr.type) {
368d50436bbSclaudio 	case IMSG_CTL_SHOW_DISCOVERY:
369d50436bbSclaudio 		adj = imsg->data;
370d50436bbSclaudio 
3716fb6d103Srenato 		if (res->family != AF_UNSPEC && res->family != adj->af)
3726fb6d103Srenato 			break;
3736fb6d103Srenato 
3746fb6d103Srenato 		printf("%-4s %-15s ", af_name(adj->af), inet_ntoa(adj->id));
375d50436bbSclaudio 		switch(adj->type) {
376d50436bbSclaudio 		case HELLO_LINK:
3776fb6d103Srenato 			printf("%-8s %-15s ", "Link", adj->ifname);
378d50436bbSclaudio 			break;
379d50436bbSclaudio 		case HELLO_TARGETED:
3806fb6d103Srenato 			addr = log_addr(adj->af, &adj->src_addr);
3816fb6d103Srenato 
3826fb6d103Srenato 			printf("%-8s %-15s ", "Targeted", addr);
3836fb6d103Srenato 			if (strlen(addr) > 15)
3846fb6d103Srenato 				printf("\n%46s", " ");
385d50436bbSclaudio 			break;
386d50436bbSclaudio 		}
3876fb6d103Srenato 		printf("%9u\n", adj->holdtime);
388d50436bbSclaudio 		break;
389d50436bbSclaudio 	case IMSG_CTL_END:
390d50436bbSclaudio 		printf("\n");
391d50436bbSclaudio 		return (1);
392d50436bbSclaudio 	default:
393d50436bbSclaudio 		break;
394d50436bbSclaudio 	}
395d50436bbSclaudio 
396d50436bbSclaudio 	return (0);
397d50436bbSclaudio }
398d50436bbSclaudio 
399d50436bbSclaudio int
4006fb6d103Srenato show_lib_msg(struct imsg *imsg, struct parse_result *res)
401ab0c2486Smichele {
402ab0c2486Smichele 	struct ctl_rt	*rt;
4034dcd314eSrenato 	char		*dstnet;
404ab0c2486Smichele 
405ab0c2486Smichele 	switch (imsg->hdr.type) {
406ab0c2486Smichele 	case IMSG_CTL_SHOW_LIB:
407ab0c2486Smichele 		rt = imsg->data;
4086fb6d103Srenato 
4096fb6d103Srenato 		if (res->family != AF_UNSPEC && res->family != rt->af)
4106fb6d103Srenato 			break;
4116fb6d103Srenato 
4126fb6d103Srenato 		if (asprintf(&dstnet, "%s/%d", log_addr(rt->af, &rt->prefix),
413ab0c2486Smichele 		    rt->prefixlen) == -1)
414ab0c2486Smichele 			err(1, NULL);
415fe033e8fSmichele 
4166fb6d103Srenato 		printf("%-4s %-20s", af_name(rt->af), dstnet);
4176fb6d103Srenato 		if (strlen(dstnet) > 20)
4186fb6d103Srenato 			printf("\n%25s", " ");
4196fb6d103Srenato 		printf(" %-15s %-11s %-13s %6s\n", inet_ntoa(rt->nexthop),
4204dcd314eSrenato 		    log_label(rt->local_label), log_label(rt->remote_label),
421cbddacefSclaudio 		    rt->in_use ? "yes" : "no");
4226fb6d103Srenato 
423ab0c2486Smichele 		free(dstnet);
424ab0c2486Smichele 		break;
425ab0c2486Smichele 	case IMSG_CTL_END:
426ab0c2486Smichele 		printf("\n");
427ab0c2486Smichele 		return (1);
428ab0c2486Smichele 	default:
429ab0c2486Smichele 		break;
430ab0c2486Smichele 	}
431ab0c2486Smichele 
432ab0c2486Smichele 	return (0);
433ab0c2486Smichele }
434ab0c2486Smichele 
435ab0c2486Smichele int
4366fb6d103Srenato show_nbr_msg(struct imsg *imsg, struct parse_result *res)
437ab0c2486Smichele {
438ab0c2486Smichele 	struct ctl_nbr	*nbr;
4396fb6d103Srenato 	const char	*addr;
440ab0c2486Smichele 
441ab0c2486Smichele 	switch (imsg->hdr.type) {
442ab0c2486Smichele 	case IMSG_CTL_SHOW_NBR:
443ab0c2486Smichele 		nbr = imsg->data;
4446fb6d103Srenato 
4456fb6d103Srenato 		if (res->family != AF_UNSPEC && res->family != nbr->af)
4466fb6d103Srenato 			break;
4476fb6d103Srenato 
4486fb6d103Srenato 		addr = log_addr(nbr->af, &nbr->raddr);
4496fb6d103Srenato 
4506fb6d103Srenato 		printf("%-4s %-15s %-11s %-15s",
4516fb6d103Srenato 		    af_name(nbr->af), inet_ntoa(nbr->id),
4526fb6d103Srenato 		    nbr_state_name(nbr->nbr_state), addr);
4536fb6d103Srenato 		if (strlen(addr) > 15)
4546fb6d103Srenato 			printf("\n%48s", " ");
4556fb6d103Srenato 		printf(" %8s\n", nbr->uptime == 0 ? "-" :
4566fb6d103Srenato 		    fmt_timeframe_core(nbr->uptime));
457ab0c2486Smichele 		break;
458ab0c2486Smichele 	case IMSG_CTL_END:
459ab0c2486Smichele 		printf("\n");
460ab0c2486Smichele 		return (1);
461ab0c2486Smichele 	default:
462ab0c2486Smichele 		break;
463ab0c2486Smichele 	}
464ab0c2486Smichele 
465ab0c2486Smichele 	return (0);
466ab0c2486Smichele }
467ab0c2486Smichele 
468ab0c2486Smichele void
46992dd8dc8Sclaudio show_fib_head(void)
470ab0c2486Smichele {
47186bd313bSclaudio 	printf("Flags: C = Connected, S = Static\n");
47286bd313bSclaudio 	printf(" %-4s %-20s %-17s %-17s %s\n", "Prio", "Destination",
47386bd313bSclaudio 	    "Nexthop", "Local Label", "Remote Label");
474ab0c2486Smichele }
475ab0c2486Smichele 
476ab0c2486Smichele int
4776fb6d103Srenato show_fib_msg(struct imsg *imsg, struct parse_result *res)
478ab0c2486Smichele {
479ab0c2486Smichele 	struct kroute	*k;
480ab0c2486Smichele 	char		*p;
4816fb6d103Srenato 	const char	*nexthop;
482ab0c2486Smichele 
483ab0c2486Smichele 	switch (imsg->hdr.type) {
484ab0c2486Smichele 	case IMSG_CTL_KROUTE:
485ab0c2486Smichele 		if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute))
486ab0c2486Smichele 			errx(1, "wrong imsg len");
487ab0c2486Smichele 		k = imsg->data;
488ab0c2486Smichele 
4896fb6d103Srenato 		if (res->family != AF_UNSPEC && res->family != k->af)
4906fb6d103Srenato 			break;
4916fb6d103Srenato 
49286bd313bSclaudio 		if (k->flags & F_CONNECTED)
493ab0c2486Smichele 			printf("C");
494ab0c2486Smichele 		else if (k->flags & F_STATIC)
495ab0c2486Smichele 			printf("S");
496ab0c2486Smichele 		else
497ab0c2486Smichele 			printf(" ");
498ab0c2486Smichele 
49986bd313bSclaudio 		printf(" %3d ", k->priority);
5006fb6d103Srenato 		if (asprintf(&p, "%s/%u", log_addr(k->af, &k->prefix),
501ab0c2486Smichele 		    k->prefixlen) == -1)
502ab0c2486Smichele 			err(1, NULL);
503ab0c2486Smichele 		printf("%-20s ", p);
5046fb6d103Srenato 		if (strlen(p) > 20)
5056fb6d103Srenato 			printf("\n%27s", " ");
506ab0c2486Smichele 		free(p);
507ab0c2486Smichele 
5086fb6d103Srenato 		if (ldp_addrisset(k->af, &k->nexthop)) {
5096fb6d103Srenato 			switch (k->af) {
5106fb6d103Srenato 			case AF_INET:
5116fb6d103Srenato 				printf("%-18s", inet_ntoa(k->nexthop.v4));
5126fb6d103Srenato 				break;
5136fb6d103Srenato 			case AF_INET6:
5146fb6d103Srenato 				nexthop = log_in6addr_scope(&k->nexthop.v6,
5156fb6d103Srenato 				    k->ifindex);
5166fb6d103Srenato 				printf("%-18s", nexthop);
5176fb6d103Srenato 				if (strlen(nexthop) > 18)
5186fb6d103Srenato 					printf("\n%45s", " ");
5196fb6d103Srenato 				break;
5206fb6d103Srenato 			default:
5216fb6d103Srenato 				printf("%-18s", " ");
5226fb6d103Srenato 				break;
5236fb6d103Srenato 			}
5246fb6d103Srenato 		} else if (k->flags & F_CONNECTED)
525ab0c2486Smichele 			printf("link#%-13u", k->ifindex);
526ab0c2486Smichele 
5274dcd314eSrenato 		printf("%-18s", log_label(k->local_label));
5284dcd314eSrenato 		printf("%s", log_label(k->remote_label));
529ab0c2486Smichele 		printf("\n");
530ab0c2486Smichele 		break;
531ab0c2486Smichele 	case IMSG_CTL_END:
532ab0c2486Smichele 		printf("\n");
533ab0c2486Smichele 		return (1);
534ab0c2486Smichele 	default:
535ab0c2486Smichele 		break;
536ab0c2486Smichele 	}
537ab0c2486Smichele 
538ab0c2486Smichele 	return (0);
539ab0c2486Smichele }
540ab0c2486Smichele 
541ab0c2486Smichele void
542ab0c2486Smichele show_interface_head(void)
543ab0c2486Smichele {
544ab0c2486Smichele 	printf("%-15s%-15s%s\n", "Interface", "Flags",
545ab0c2486Smichele 	    "Link state");
546ab0c2486Smichele }
547ab0c2486Smichele 
548ab0c2486Smichele int
54992dd8dc8Sclaudio show_fib_interface_msg(struct imsg *imsg)
550ab0c2486Smichele {
551ab0c2486Smichele 	struct kif	*k;
5520f882be7Sstsp 	uint64_t	 ifms_type;
553ab0c2486Smichele 
554ab0c2486Smichele 	switch (imsg->hdr.type) {
555ab0c2486Smichele 	case IMSG_CTL_IFINFO:
556ab0c2486Smichele 		k = imsg->data;
557ab0c2486Smichele 		printf("%-15s", k->ifname);
558ab0c2486Smichele 		printf("%-15s", k->flags & IFF_UP ? "UP" : "");
5590f882be7Sstsp 		ifms_type = get_ifms_type(k->if_type);
560ab0c2486Smichele 		if (ifms_type)
5610f617141Sclaudio 			printf("%s, ", get_media_descr(ifms_type));
5620f617141Sclaudio 
5630f882be7Sstsp 		printf("%s", get_linkstate(k->if_type, k->link_state));
564ab0c2486Smichele 
565ab0c2486Smichele 		if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) {
566ab0c2486Smichele 			printf(", ");
567ab0c2486Smichele 			print_baudrate(k->baudrate);
568ab0c2486Smichele 		}
569ab0c2486Smichele 		printf("\n");
570ab0c2486Smichele 		break;
571ab0c2486Smichele 	case IMSG_CTL_END:
572ab0c2486Smichele 		printf("\n");
573ab0c2486Smichele 		return (1);
574ab0c2486Smichele 	default:
575ab0c2486Smichele 		break;
576ab0c2486Smichele 	}
577ab0c2486Smichele 
578ab0c2486Smichele 	return (0);
579ab0c2486Smichele }
580ab0c2486Smichele 
581a94c7fd0Srenato int
582a94c7fd0Srenato show_l2vpn_pw_msg(struct imsg *imsg)
583a94c7fd0Srenato {
584a94c7fd0Srenato 	struct ctl_pw	*pw;
585a94c7fd0Srenato 
586a94c7fd0Srenato 	switch (imsg->hdr.type) {
587a94c7fd0Srenato 	case IMSG_CTL_SHOW_L2VPN_PW:
588a94c7fd0Srenato 		pw = imsg->data;
589a94c7fd0Srenato 
590a94c7fd0Srenato 		printf("%-11s %-15s %-14u %-10s\n", pw->ifname,
59157e0fe15Srenato 		    inet_ntoa(pw->lsr_id), pw->pwid,
592a94c7fd0Srenato 		    (pw->status ? "UP" : "DOWN"));
593a94c7fd0Srenato 		break;
594a94c7fd0Srenato 	case IMSG_CTL_END:
595a94c7fd0Srenato 		printf("\n");
596a94c7fd0Srenato 		return (1);
597a94c7fd0Srenato 	default:
598a94c7fd0Srenato 		break;
599a94c7fd0Srenato 	}
600a94c7fd0Srenato 
601a94c7fd0Srenato 	return (0);
602a94c7fd0Srenato }
603a94c7fd0Srenato 
604a94c7fd0Srenato int
605a94c7fd0Srenato show_l2vpn_binding_msg(struct imsg *imsg)
606a94c7fd0Srenato {
607a94c7fd0Srenato 	struct ctl_pw	*pw;
608a94c7fd0Srenato 
609a94c7fd0Srenato 	switch (imsg->hdr.type) {
610a94c7fd0Srenato 	case IMSG_CTL_SHOW_L2VPN_BINDING:
611a94c7fd0Srenato 		pw = imsg->data;
612a94c7fd0Srenato 
613a94c7fd0Srenato 		printf("Neighbor: %s - PWID: %u (%s)\n",
61457e0fe15Srenato 		    inet_ntoa(pw->lsr_id), pw->pwid,
6154dcd314eSrenato 		    pw_type_name(pw->type));
616a94c7fd0Srenato 		printf("%-12s%-15s%-15s%-10s\n", "", "Label", "Group-ID",
617a94c7fd0Srenato 		    "MTU");
618a94c7fd0Srenato 		if (pw->local_label != NO_LABEL)
619a94c7fd0Srenato 			printf("  %-10s%-15u%-15u%u\n", "Local",
620a94c7fd0Srenato 			    pw->local_label, pw->local_gid, pw->local_ifmtu);
621a94c7fd0Srenato 		else
622a94c7fd0Srenato 			printf("  %-10s%-15s%-15s%s\n", "Local", "-",
623a94c7fd0Srenato 			    "-", "-");
624a94c7fd0Srenato 		if (pw->remote_label != NO_LABEL)
625a94c7fd0Srenato 			printf("  %-10s%-15u%-15u%u\n", "Remote",
626a94c7fd0Srenato 			    pw->remote_label, pw->remote_gid,
627a94c7fd0Srenato 			    pw->remote_ifmtu);
628a94c7fd0Srenato 		else
629a94c7fd0Srenato 			printf("  %-10s%-15s%-15s%s\n", "Remote", "-",
630a94c7fd0Srenato 			    "-", "-");
631a94c7fd0Srenato 		break;
632a94c7fd0Srenato 	case IMSG_CTL_END:
633a94c7fd0Srenato 		printf("\n");
634a94c7fd0Srenato 		return (1);
635a94c7fd0Srenato 	default:
636a94c7fd0Srenato 		break;
637a94c7fd0Srenato 	}
638a94c7fd0Srenato 
639a94c7fd0Srenato 	return (0);
640a94c7fd0Srenato }
641a94c7fd0Srenato 
6420f617141Sclaudio const struct if_status_description
6430f617141Sclaudio 		if_status_descriptions[] = LINK_STATE_DESCRIPTIONS;
644ab0c2486Smichele const struct ifmedia_description
645ab0c2486Smichele 		ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS;
646ab0c2486Smichele 
647ab0c2486Smichele const char *
648e5605ae3Sderaadt get_media_descr(uint64_t media_type)
649ab0c2486Smichele {
650ab0c2486Smichele 	const struct ifmedia_description	*p;
651ab0c2486Smichele 
652ab0c2486Smichele 	for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++)
653ab0c2486Smichele 		if (media_type == p->ifmt_word)
654ab0c2486Smichele 			return (p->ifmt_string);
655ab0c2486Smichele 
656ab0c2486Smichele 	return ("unknown");
657ab0c2486Smichele }
658ab0c2486Smichele 
659ab0c2486Smichele const char *
6600f882be7Sstsp get_linkstate(uint8_t if_type, int link_state)
661ab0c2486Smichele {
6620f617141Sclaudio 	const struct if_status_description *p;
6630f617141Sclaudio 	static char buf[8];
664ab0c2486Smichele 
6650f617141Sclaudio 	for (p = if_status_descriptions; p->ifs_string != NULL; p++) {
6660f882be7Sstsp 		if (LINK_STATE_DESC_MATCH(p, if_type, link_state))
6670f617141Sclaudio 			return (p->ifs_string);
668ab0c2486Smichele 	}
6690f617141Sclaudio 	snprintf(buf, sizeof(buf), "[#%d]", link_state);
6700f617141Sclaudio 	return (buf);
671ab0c2486Smichele }
672ab0c2486Smichele 
673ab0c2486Smichele void
6746c1e7e28Srenato print_baudrate(uint64_t baudrate)
675ab0c2486Smichele {
676ab0c2486Smichele 	if (baudrate > IF_Gbps(1))
677ab0c2486Smichele 		printf("%llu GBit/s", baudrate / IF_Gbps(1));
678ab0c2486Smichele 	else if (baudrate > IF_Mbps(1))
679ab0c2486Smichele 		printf("%llu MBit/s", baudrate / IF_Mbps(1));
680ab0c2486Smichele 	else if (baudrate > IF_Kbps(1))
681ab0c2486Smichele 		printf("%llu KBit/s", baudrate / IF_Kbps(1));
682ab0c2486Smichele 	else
683ab0c2486Smichele 		printf("%llu Bit/s", baudrate);
684ab0c2486Smichele }
685