GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/eigrpctl/eigrpctl.c Lines: 0 427 0.0 %
Date: 2017-11-07 Branches: 0 291 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: eigrpctl.c,v 1.9 2017/02/22 14:18:25 renato Exp $ */
2
3
/*
4
 * Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
5
 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
6
 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
7
 * Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
8
 *
9
 * Permission to use, copy, modify, and distribute this software for any
10
 * purpose with or without fee is hereby granted, provided that the above
11
 * copyright notice and this permission notice appear in all copies.
12
 *
13
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
 */
21
22
#include <sys/types.h>
23
#include <sys/socket.h>
24
#include <sys/un.h>
25
#include <netinet/in.h>
26
#include <arpa/inet.h>
27
#include <net/if_media.h>
28
#include <net/if_types.h>
29
30
#include <err.h>
31
#include <errno.h>
32
#include <stdio.h>
33
#include <stdlib.h>
34
#include <string.h>
35
#include <unistd.h>
36
37
#include "eigrp.h"
38
#include "eigrpd.h"
39
#include "eigrpe.h"
40
#include "rde.h"
41
#include "log.h"
42
#include "parser.h"
43
44
__dead void	 usage(void);
45
uint64_t	 get_ifms_type(uint8_t);
46
int		 show_interface_msg(struct imsg *, struct parse_result *);
47
int		 show_interface_detail_msg(struct imsg *,
48
    struct parse_result *);
49
const char	*print_link(int);
50
const char	*fmt_timeframe_core(time_t);
51
int		 show_nbr_msg(struct imsg *, struct parse_result *);
52
int		 show_topology_msg(struct imsg *, struct parse_result *);
53
int		 show_topology_detail_msg(struct imsg *,
54
    struct parse_result *);
55
void		 show_fib_head(void);
56
int		 show_fib_msg(struct imsg *, struct parse_result *);
57
void		 show_interface_head(void);
58
const char *	 get_media_descr(uint64_t);
59
const char *	 get_linkstate(uint8_t, int);
60
void		 print_baudrate(uint64_t);
61
int		 show_fib_interface_msg(struct imsg *);
62
int		 show_stats_msg(struct imsg *, struct parse_result *);
63
64
struct imsgbuf	*ibuf;
65
66
__dead void
67
usage(void)
68
{
69
	extern char *__progname;
70
71
	fprintf(stderr, "usage: %s [-s socket] command [argument ...]\n",
72
	    __progname);
73
	exit(1);
74
}
75
76
int
77
main(int argc, char *argv[])
78
{
79
	struct sockaddr_un		 sun;
80
	struct parse_result		*res;
81
	struct imsg			 imsg;
82
	unsigned int			 ifidx = 0;
83
	int				 ctl_sock;
84
	int				 done = 0;
85
	int				 n, verbose = 0;
86
	int				 ch;
87
	char				*sockname;
88
	struct ctl_show_topology_req	 treq;
89
	struct ctl_nbr			 nbr;
90
91
	sockname = EIGRPD_SOCKET;
92
	while ((ch = getopt(argc, argv, "s:")) != -1) {
93
		switch (ch) {
94
		case 's':
95
			sockname = optarg;
96
			break;
97
		default:
98
			usage();
99
			/* NOTREACHED */
100
		}
101
	}
102
	argc -= optind;
103
	argv += optind;
104
105
	/* parse options */
106
	if ((res = parse(argc, argv)) == NULL)
107
		exit(1);
108
109
	/* connect to eigrpd control socket */
110
	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
111
		err(1, "socket");
112
113
	memset(&sun, 0, sizeof(sun));
114
	sun.sun_family = AF_UNIX;
115
	strlcpy(sun.sun_path, sockname, sizeof(sun.sun_path));
116
	if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1)
117
		err(1, "connect: %s", sockname);
118
119
	if (pledge("stdio flock rpath cpath wpath", NULL) == -1)
120
		err(1, "pledge");
121
122
	if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
123
		err(1, NULL);
124
	imsg_init(ibuf, ctl_sock);
125
	done = 0;
126
127
	/* process user request */
128
	switch (res->action) {
129
	case NONE:
130
		usage();
131
		/* not reached */
132
	case SHOW:
133
	case SHOW_IFACE:
134
		printf("%-4s %-5s %-11s %-18s %-10s %-8s %3s\n",
135
		    "AF", "AS", "Interface", "Address", "Linkstate",
136
		    "Uptime", "nc");
137
		/*FALLTHROUGH*/
138
	case SHOW_IFACE_DTAIL:
139
		if (*res->ifname) {
140
			ifidx = if_nametoindex(res->ifname);
141
			if (ifidx == 0)
142
				errx(1, "no such interface %s", res->ifname);
143
		}
144
		imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1,
145
		    &ifidx, sizeof(ifidx));
146
		break;
147
	case SHOW_NBR:
148
		printf("%-4s %-5s %-18s %-11s %-10s %8s\n", "AF", "AS",
149
		    "Address", "Iface", "Holdtime", "Uptime");
150
		imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0);
151
		break;
152
	case SHOW_TOPOLOGY:
153
		memset(&treq, 0, sizeof(treq));
154
		treq.af = res->family;
155
		memcpy(&treq.prefix, &res->addr, sizeof(res->addr));
156
		treq.prefixlen = res->prefixlen;
157
		treq.flags = res->flags;
158
159
		if (!eigrp_addrisset(res->family, &res->addr))
160
			printf("  %-4s %-5s %-18s %-15s %-12s %s\n",
161
			    "AF", "AS", "Destination", "Nexthop", "Interface",
162
			    "Distance");
163
		imsg_compose(ibuf, IMSG_CTL_SHOW_TOPOLOGY, 0, 0, -1,
164
		    &treq, sizeof(treq));
165
		break;
166
	case SHOW_FIB:
167
		show_fib_head();
168
		imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0, -1,
169
		    &res->flags, sizeof(res->flags));
170
		break;
171
	case SHOW_FIB_IFACE:
172
		if (*res->ifname)
173
			imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1,
174
			    res->ifname, sizeof(res->ifname));
175
		else
176
			imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1, NULL, 0);
177
		show_interface_head();
178
		break;
179
	case SHOW_STATS:
180
		imsg_compose(ibuf, IMSG_CTL_SHOW_STATS, 0, 0, -1, NULL, 0);
181
		break;
182
	case CLEAR_NBR:
183
		memset(&nbr, 0, sizeof(nbr));
184
		nbr.af = res->family;
185
		nbr.as = res->as;
186
		memcpy(&nbr.addr, &res->addr, sizeof(res->addr));
187
		imsg_compose(ibuf, IMSG_CTL_CLEAR_NBR, 0, 0, -1, &nbr,
188
		    sizeof(nbr));
189
		done = 1;
190
		break;
191
	case FIB:
192
		errx(1, "fib couple|decouple");
193
		break;
194
	case FIB_COUPLE:
195
		imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, -1, NULL, 0);
196
		printf("couple request sent.\n");
197
		done = 1;
198
		break;
199
	case FIB_DECOUPLE:
200
		imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, -1, NULL, 0);
201
		printf("decouple request sent.\n");
202
		done = 1;
203
		break;
204
	case LOG_VERBOSE:
205
		verbose = 1;
206
		/* FALLTHROUGH */
207
	case LOG_BRIEF:
208
		imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1,
209
		    &verbose, sizeof(verbose));
210
		printf("logging request sent.\n");
211
		done = 1;
212
		break;
213
	case RELOAD:
214
		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0);
215
		printf("reload request sent.\n");
216
		done = 1;
217
		break;
218
	}
219
220
	while (ibuf->w.queued)
221
		if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
222
			err(1, "write error");
223
224
	while (!done) {
225
		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
226
			errx(1, "imsg_read error");
227
		if (n == 0)
228
			errx(1, "pipe closed");
229
230
		while (!done) {
231
			if ((n = imsg_get(ibuf, &imsg)) == -1)
232
				errx(1, "imsg_get error");
233
			if (n == 0)
234
				break;
235
			switch (res->action) {
236
			case SHOW:
237
			case SHOW_IFACE:
238
				done = show_interface_msg(&imsg, res);
239
				break;
240
			case SHOW_IFACE_DTAIL:
241
				done = show_interface_detail_msg(&imsg, res);
242
				break;
243
			case SHOW_NBR:
244
				done = show_nbr_msg(&imsg, res);
245
				break;
246
			case SHOW_TOPOLOGY:
247
				if (eigrp_addrisset(res->family, &res->addr))
248
					done = show_topology_detail_msg(&imsg,
249
					    res);
250
				else
251
					done = show_topology_msg(&imsg, res);
252
				break;
253
			case SHOW_FIB:
254
				done = show_fib_msg(&imsg, res);
255
				break;
256
			case SHOW_FIB_IFACE:
257
				done = show_fib_interface_msg(&imsg);
258
				break;
259
			case SHOW_STATS:
260
				done = show_stats_msg(&imsg, res);
261
				break;
262
			case CLEAR_NBR:
263
			case NONE:
264
			case FIB:
265
			case FIB_COUPLE:
266
			case FIB_DECOUPLE:
267
			case LOG_VERBOSE:
268
			case LOG_BRIEF:
269
			case RELOAD:
270
				break;
271
			}
272
			imsg_free(&imsg);
273
		}
274
	}
275
	close(ctl_sock);
276
	free(ibuf);
277
278
	return (0);
279
}
280
281
uint64_t
282
get_ifms_type(uint8_t if_type)
283
{
284
	switch (if_type) {
285
	case IFT_ETHER:
286
		return (IFM_ETHER);
287
	case IFT_FDDI:
288
		return (IFM_FDDI);
289
	case IFT_CARP:
290
		return (IFM_CARP);
291
	case IFT_PPP:
292
		return (IFM_TDM);
293
	default:
294
		return (0);
295
	}
296
}
297
298
int
299
show_interface_msg(struct imsg *imsg, struct parse_result *res)
300
{
301
	struct ctl_iface	*iface;
302
	char			*addr;
303
304
	switch (imsg->hdr.type) {
305
	case IMSG_CTL_SHOW_INTERFACE:
306
		if (imsg->hdr.len < IMSG_HEADER_SIZE +
307
		    sizeof(struct ctl_iface))
308
			errx(1, "wrong imsg len");
309
		iface = imsg->data;
310
311
		if (res->family != AF_UNSPEC && res->family != iface->af)
312
			break;
313
		if (res->as != 0 && res->as != iface->as)
314
			break;
315
316
		if (asprintf(&addr, "%s/%d", log_addr(iface->af, &iface->addr),
317
		    iface->prefixlen) == -1)
318
			err(1, NULL);
319
320
		printf("%-4s %-5u %-11s %-18s", af_name(iface->af), iface->as,
321
		    iface->name, addr);
322
		if (strlen(addr) > 18)
323
			printf("\n%41s", " ");
324
		printf(" %-10s %-8s %3u\n", get_linkstate(iface->if_type,
325
		    iface->linkstate), fmt_timeframe_core(iface->uptime),
326
		    iface->nbr_cnt);
327
		free(addr);
328
		break;
329
	case IMSG_CTL_END:
330
		printf("\n");
331
		return (1);
332
	default:
333
		break;
334
	}
335
336
	return (0);
337
}
338
339
int
340
show_interface_detail_msg(struct imsg *imsg, struct parse_result *res)
341
{
342
	struct ctl_iface	*iface;
343
344
	switch (imsg->hdr.type) {
345
	case IMSG_CTL_SHOW_INTERFACE:
346
		if (imsg->hdr.len < IMSG_HEADER_SIZE +
347
		    sizeof(struct ctl_iface))
348
			errx(1, "wrong imsg len");
349
		iface = imsg->data;
350
351
		if (res->family != AF_UNSPEC && res->family != iface->af)
352
			break;
353
		if (res->as != 0 && res->as != iface->as)
354
			break;
355
356
		printf("\n");
357
		printf("Interface %s, line protocol is %s\n",
358
		    iface->name, print_link(iface->flags));
359
		printf("  Autonomous System %u, Address Family %s\n",
360
		    iface->as, af_name(iface->af));
361
		printf("  Internet address %s/%d\n",
362
		    log_addr(iface->af, &iface->addr), iface->prefixlen);
363
		printf("  Linkstate %s, network type %s\n",
364
		    get_linkstate(iface->if_type, iface->linkstate),
365
		    if_type_name(iface->type));
366
		printf("  Delay %u usec, Bandwidth %u Kbit/sec\n",
367
		    iface->delay, iface->bandwidth);
368
		if (iface->passive)
369
			printf("  Passive interface (No Hellos)\n");
370
		else {
371
			printf("  Hello interval %u, Hello holdtime %u\n",
372
			    iface->hello_interval, iface->hello_holdtime);
373
			printf("  Split-horizon %s\n",
374
			    (iface->splithorizon) ? "enabled" : "disabled");
375
			printf("  Neighbor count is %d\n", iface->nbr_cnt);
376
		}
377
		printf("  Uptime %s\n", fmt_timeframe_core(iface->uptime));
378
		break;
379
	case IMSG_CTL_END:
380
		printf("\n");
381
		return (1);
382
	default:
383
		break;
384
	}
385
386
	return (0);
387
}
388
389
const char *
390
print_link(int state)
391
{
392
	if (state & IFF_UP)
393
		return ("UP");
394
	else
395
		return ("DOWN");
396
}
397
398
#define TF_BUFS	8
399
#define TF_LEN	9
400
401
const char *
402
fmt_timeframe_core(time_t t)
403
{
404
	char		*buf;
405
	static char	 tfbuf[TF_BUFS][TF_LEN];	/* ring buffer */
406
	static int	 idx = 0;
407
	unsigned int	 sec, min, hrs, day;
408
	unsigned long long	week;
409
410
	if (t == 0)
411
		return ("00:00:00");
412
413
	buf = tfbuf[idx++];
414
	if (idx == TF_BUFS)
415
		idx = 0;
416
417
	week = t;
418
419
	sec = week % 60;
420
	week /= 60;
421
	min = week % 60;
422
	week /= 60;
423
	hrs = week % 24;
424
	week /= 24;
425
	day = week % 7;
426
	week /= 7;
427
428
	if (week > 0)
429
		snprintf(buf, TF_LEN, "%02lluw%01ud%02uh", week, day, hrs);
430
	else if (day > 0)
431
		snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
432
	else
433
		snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
434
435
	return (buf);
436
}
437
438
int
439
show_nbr_msg(struct imsg *imsg, struct parse_result *res)
440
{
441
	struct ctl_nbr	*nbr;
442
	const char	*addr;
443
444
	switch (imsg->hdr.type) {
445
	case IMSG_CTL_SHOW_NBR:
446
		if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct ctl_nbr))
447
			errx(1, "wrong imsg len");
448
		nbr = imsg->data;
449
450
		if (res->family != AF_UNSPEC && res->family != nbr->af)
451
			break;
452
		if (res->as != 0 && res->as != nbr->as)
453
			break;
454
455
		addr = log_addr(nbr->af, &nbr->addr);
456
457
		printf("%-4s %-5u %-18s", af_name(nbr->af), nbr->as, addr);
458
		if (strlen(addr) > 18)
459
			printf("\n%29s", " ");
460
		printf(" %-11s %-10u %8s\n", nbr->ifname, nbr->hello_holdtime,
461
		    fmt_timeframe_core(nbr->uptime));
462
		break;
463
	case IMSG_CTL_END:
464
		printf("\n");
465
		return (1);
466
	default:
467
		break;
468
	}
469
470
	return (0);
471
}
472
473
static int
474
connected_check(int af, union eigrpd_addr *addr)
475
{
476
	switch (af) {
477
	case AF_INET:
478
		if (addr->v4.s_addr == INADDR_ANY)
479
			return (1);
480
		break;
481
	case AF_INET6:
482
		if (IN6_IS_ADDR_UNSPECIFIED(&addr->v6))
483
			return (1);
484
		break;
485
	default:
486
		break;
487
	}
488
489
	return (0);
490
}
491
492
int
493
show_topology_msg(struct imsg *imsg, struct parse_result *res)
494
{
495
	struct ctl_rt	*rt;
496
	char		*dstnet, *nexthop, *rdistance;
497
	char		 flag;
498
499
	switch (imsg->hdr.type) {
500
	case IMSG_CTL_SHOW_TOPOLOGY:
501
		if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct ctl_rt))
502
			errx(1, "wrong imsg len");
503
		rt = imsg->data;
504
505
		if (res->family != AF_UNSPEC && res->family != rt->af)
506
			break;
507
		if (res->as != 0 && res->as != rt->as)
508
			break;
509
510
		if (rt->state & DUAL_STA_ACTIVE_ALL)
511
			flag = 'A';
512
		else if (rt->flags & F_CTL_RT_SUCCESSOR)
513
			flag = 'S';
514
		else if (rt->flags & F_CTL_RT_FSUCCESSOR)
515
			flag = 'F';
516
		else
517
			flag = ' ';
518
519
		if (asprintf(&dstnet, "%s/%d", log_addr(rt->af, &rt->prefix),
520
		    rt->prefixlen) == -1)
521
			err(1, NULL);
522
523
		if (connected_check(rt->af, &rt->nexthop)) {
524
			if (asprintf(&nexthop, "Connected") == -1)
525
				err(1, NULL);
526
			if (asprintf(&rdistance, "-") == -1)
527
				err(1, NULL);
528
		} else {
529
			if (asprintf(&nexthop, "%s", log_addr(rt->af,
530
			    &rt->nexthop)) == -1)
531
				err(1, NULL);
532
			if (asprintf(&rdistance, "%u", rt->rdistance) == -1)
533
				err(1, NULL);
534
		}
535
536
		printf("%c %-4s %-5u %-18s", flag, af_name(rt->af), rt->as,
537
		    dstnet);
538
		if (strlen(dstnet) > 18)
539
			printf("\n%31s", " ");
540
		printf(" %-15s", nexthop);
541
		if (strlen(nexthop) > 15)
542
			printf("\n%47s", " ");
543
		printf(" %-12s %u/%s\n", rt->ifname, rt->distance, rdistance);
544
		free(dstnet);
545
		free(nexthop);
546
		free(rdistance);
547
		break;
548
	case IMSG_CTL_END:
549
		printf("\n");
550
		return (1);
551
	default:
552
		break;
553
	}
554
555
	return (0);
556
}
557
558
int
559
show_topology_detail_msg(struct imsg *imsg, struct parse_result *res)
560
{
561
	struct ctl_rt	*rt;
562
	char		*dstnet = NULL, *state = NULL, *type, *nexthop;
563
	struct in_addr	 addr;
564
565
	switch (imsg->hdr.type) {
566
	case IMSG_CTL_SHOW_TOPOLOGY:
567
		if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct ctl_rt))
568
			errx(1, "wrong imsg len");
569
		rt = imsg->data;
570
571
		if (res->family != AF_UNSPEC && res->family != rt->af)
572
			break;
573
		if (res->as != 0 && res->as != rt->as)
574
			break;
575
576
		if (rt->flags & F_CTL_RT_FIRST) {
577
			if (asprintf(&dstnet, "%s/%d", log_addr(rt->af,
578
			    &rt->prefix), rt->prefixlen) == -1)
579
				err(1, NULL);
580
581
			if (rt->state & DUAL_STA_ACTIVE_ALL) {
582
				if (asprintf(&state, "Active") == -1)
583
					err(1, NULL);
584
			} else {
585
				if (asprintf(&state, "Passive") == -1)
586
					err(1, NULL);
587
			}
588
		}
589
590
		if (rt->type == EIGRP_ROUTE_INTERNAL) {
591
			if (asprintf(&type, "Internal") == -1)
592
				err(1, NULL);
593
		} else {
594
			if (asprintf(&type, "External") == -1)
595
				err(1, NULL);
596
		}
597
598
		if (connected_check(rt->af, &rt->nexthop)) {
599
			if (asprintf(&nexthop, "Connected") == -1)
600
				err(1, NULL);
601
		} else {
602
			if (asprintf(&nexthop, "Neighbor %s", log_addr(rt->af,
603
			    &rt->nexthop)) == -1)
604
				err(1, NULL);
605
		}
606
607
		if (rt->flags & F_CTL_RT_FIRST) {
608
			printf("Network %s\n", dstnet);
609
			printf("Autonomous System %u, Address Family %s\n",
610
			    rt->as, af_name(rt->af));
611
			printf("DUAL State: %s, Feasible Distance: %u\n", state,
612
			    rt->fdistance);
613
			printf("Routes:\n");
614
		}
615
		printf("  Interface %s - %s\n", rt->ifname, nexthop);
616
		printf("    Distance: %u", rt->distance);
617
		if (!connected_check(rt->af, &rt->nexthop))
618
			printf(", Reported Distance: %u", rt->rdistance);
619
		printf(", route is %s\n", type);
620
		printf("    Vector metric:\n");
621
		printf("      Minimum bandwidth is %u Kbit\n",
622
		    rt->metric.bandwidth);
623
		printf("      Total delay is %u microseconds\n",
624
		    rt->metric.delay);
625
		printf("      Reliability is %u/255\n", rt->metric.reliability);
626
		printf("      Load is %u/255\n", rt->metric.load);
627
		printf("      Minimum MTU is %u\n", rt->metric.mtu);
628
		printf("      Hop count is %u\n", rt->metric.hop_count);
629
		if (rt->type == EIGRP_ROUTE_EXTERNAL) {
630
			addr.s_addr = htonl(rt->emetric.routerid);
631
			printf("    External data:\n");
632
			printf("      Originating router is %s\n",
633
			    inet_ntoa(addr));
634
			printf("      AS number of route is %u\n",
635
			    rt->emetric.as);
636
			printf("      External protocol is %s\n",
637
			    ext_proto_name(rt->emetric.protocol));
638
			printf("      External metric is %u\n",
639
			    rt->emetric.metric);
640
			printf("      Administrator tag is %u\n",
641
			    rt->emetric.tag);
642
		}
643
644
		printf("\n");
645
		free(dstnet);
646
		free(state);
647
		free(type);
648
		free(nexthop);
649
		break;
650
	case IMSG_CTL_END:
651
		return (1);
652
	default:
653
		break;
654
	}
655
656
	return (0);
657
}
658
659
void
660
show_fib_head(void)
661
{
662
	printf("flags: * = valid, D = EIGRP, C = Connected, S = Static\n");
663
	printf("%-6s %-4s %-20s %-17s\n", "Flags", "Prio", "Destination",
664
	    "Nexthop");
665
}
666
667
int
668
show_fib_msg(struct imsg *imsg, struct parse_result *res)
669
{
670
	struct kroute		*k;
671
	char			*p;
672
673
	switch (imsg->hdr.type) {
674
	case IMSG_CTL_KROUTE:
675
		if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute))
676
			errx(1, "wrong imsg len");
677
		k = imsg->data;
678
679
		if (res->family != AF_UNSPEC && res->family != k->af)
680
			break;
681
682
		if (k->flags & F_DOWN)
683
			printf(" ");
684
		else
685
			printf("*");
686
687
		if (!(k->flags & F_KERNEL))
688
			printf("D");
689
		else if (k->flags & F_CONNECTED)
690
			printf("C");
691
		else if (k->flags & F_STATIC)
692
			printf("S");
693
		else
694
			printf(" ");
695
696
		printf("%-5s", (k->flags & F_CTL_EXTERNAL) ? " EX" : "");
697
		printf("%4d ", k->priority);
698
		if (asprintf(&p, "%s/%u", log_addr(k->af, &k->prefix),
699
		    k->prefixlen) == -1)
700
			err(1, NULL);
701
		printf("%-20s ", p);
702
		if (strlen(p) > 20)
703
			printf("\n%33s", " ");
704
		free(p);
705
706
		if (eigrp_addrisset(k->af, &k->nexthop)) {
707
			switch (k->af) {
708
			case AF_INET:
709
				printf("%s", log_addr(k->af, &k->nexthop));
710
				break;
711
			case AF_INET6:
712
				printf("%s", log_in6addr_scope(&k->nexthop.v6,
713
				    k->ifindex));
714
				break;
715
			default:
716
				break;
717
			}
718
719
		} else if (k->flags & F_CONNECTED)
720
			printf("link#%u", k->ifindex);
721
		printf("\n");
722
723
		break;
724
	case IMSG_CTL_END:
725
		printf("\n");
726
		return (1);
727
	default:
728
		break;
729
	}
730
731
	return (0);
732
}
733
734
void
735
show_interface_head(void)
736
{
737
	printf("%-15s%-15s%s\n", "Interface", "Flags",
738
	    "Link state");
739
}
740
741
const struct if_status_description
742
		if_status_descriptions[] = LINK_STATE_DESCRIPTIONS;
743
const struct ifmedia_description
744
		ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS;
745
746
const char *
747
get_media_descr(uint64_t media_type)
748
{
749
	const struct ifmedia_description	*p;
750
751
	for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++)
752
		if (media_type == p->ifmt_word)
753
			return (p->ifmt_string);
754
755
	return ("unknown");
756
}
757
758
const char *
759
get_linkstate(uint8_t if_type, int link_state)
760
{
761
	const struct if_status_description *p;
762
	static char buf[8];
763
764
	for (p = if_status_descriptions; p->ifs_string != NULL; p++) {
765
		if (LINK_STATE_DESC_MATCH(p, if_type, link_state))
766
			return (p->ifs_string);
767
	}
768
	snprintf(buf, sizeof(buf), "[#%d]", link_state);
769
	return (buf);
770
}
771
772
void
773
print_baudrate(uint64_t baudrate)
774
{
775
	if (baudrate > IF_Gbps(1))
776
		printf("%llu GBit/s", baudrate / IF_Gbps(1));
777
	else if (baudrate > IF_Mbps(1))
778
		printf("%llu MBit/s", baudrate / IF_Mbps(1));
779
	else if (baudrate > IF_Kbps(1))
780
		printf("%llu KBit/s", baudrate / IF_Kbps(1));
781
	else
782
		printf("%llu Bit/s", baudrate);
783
}
784
785
int
786
show_fib_interface_msg(struct imsg *imsg)
787
{
788
	struct kif	*k;
789
	uint64_t	 ifms_type;
790
791
	switch (imsg->hdr.type) {
792
	case IMSG_CTL_IFINFO:
793
		if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kif))
794
			errx(1, "wrong imsg len");
795
		k = imsg->data;
796
		printf("%-15s", k->ifname);
797
		printf("%-15s", k->flags & IFF_UP ? "UP" : "");
798
		ifms_type = get_ifms_type(k->if_type);
799
		if (ifms_type)
800
			printf("%s, ", get_media_descr(ifms_type));
801
802
		printf("%s", get_linkstate(k->if_type, k->link_state));
803
804
		if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) {
805
			printf(", ");
806
			print_baudrate(k->baudrate);
807
		}
808
		printf("\n");
809
		break;
810
	case IMSG_CTL_END:
811
		printf("\n");
812
		return (1);
813
	default:
814
		break;
815
	}
816
817
	return (0);
818
}
819
820
int
821
show_stats_msg(struct imsg *imsg, struct parse_result *res)
822
{
823
	struct ctl_stats	*cs;
824
825
	switch (imsg->hdr.type) {
826
	case IMSG_CTL_SHOW_STATS:
827
		if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct ctl_stats))
828
			errx(1, "wrong imsg len");
829
		cs = imsg->data;
830
831
		if (res->family != AF_UNSPEC && res->family != cs->af)
832
			break;
833
		if (res->as != 0 && res->as != cs->as)
834
			break;
835
836
		printf("Address Family %s, Autonomous System %u\n",
837
		    af_name(cs->af), cs->as);
838
		printf("  Hellos sent/received: %u/%u\n",
839
		    cs->stats.hellos_sent, cs->stats.hellos_recv);
840
		printf("  Updates sent/received: %u/%u\n",
841
		    cs->stats.updates_sent, cs->stats.updates_recv);
842
		printf("  Queries sent/received: %u/%u\n",
843
		    cs->stats.queries_sent, cs->stats.queries_recv);
844
		printf("  Replies sent/received: %u/%u\n",
845
		    cs->stats.replies_sent, cs->stats.replies_recv);
846
		printf("  Acks sent/received: %u/%u\n",
847
		    cs->stats.acks_sent, cs->stats.acks_recv);
848
		printf("  SIA-Queries sent/received: %u/%u\n",
849
		    cs->stats.squeries_sent, cs->stats.squeries_recv);
850
		printf("  SIA-Replies sent/received: %u/%u\n",
851
		    cs->stats.sreplies_sent, cs->stats.sreplies_recv);
852
		break;
853
	case IMSG_CTL_END:
854
		printf("\n");
855
		return (1);
856
	default:
857
		break;
858
	}
859
860
	return (0);
861
}