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

Line Branch Exec Source
1
/*	$OpenBSD: dvmrpctl.c,v 1.15 2015/12/05 13:11:00 claudio Exp $ */
2
3
/*
4
 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
5
 * Copyright (c) 2004, 2005, 2006 Esben Norby <norby@openbsd.org>
6
 * Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
7
 *
8
 * Permission to use, copy, modify, and distribute this software for any
9
 * purpose with or without fee is hereby granted, provided that the above
10
 * copyright notice and this permission notice appear in all copies.
11
 *
12
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
 */
20
21
#include <sys/types.h>
22
#include <sys/socket.h>
23
#include <sys/un.h>
24
#include <netinet/in.h>
25
#include <netinet/ip_mroute.h>
26
#include <arpa/inet.h>
27
#include <net/if_types.h>
28
29
#include <err.h>
30
#include <errno.h>
31
#include <stdio.h>
32
#include <stdlib.h>
33
#include <string.h>
34
#include <unistd.h>
35
36
#include "igmp.h"
37
#include "dvmrp.h"
38
#include "dvmrpd.h"
39
#include "dvmrpe.h"
40
#include "parser.h"
41
#include "log.h"
42
43
__dead void	 usage(void);
44
int		 show_summary_msg(struct imsg *);
45
int		 show_interface_msg(struct imsg *);
46
int		 show_interface_detail_msg(struct imsg *);
47
int		 show_igmp_msg(struct imsg *);
48
const char	*print_if_type(enum iface_type type);
49
const char	*print_nbr_state(int);
50
const char	*print_link(int);
51
const char	*fmt_timeframe(time_t t);
52
const char	*fmt_timeframe_core(time_t t);
53
int		 show_nbr_msg(struct imsg *);
54
const char	*print_dvmrp_options(u_int8_t);
55
int		 show_nbr_detail_msg(struct imsg *);
56
int		 show_rib_msg(struct imsg *);
57
int		 show_rib_detail_msg(struct imsg *);
58
int		 show_mfc_msg(struct imsg *);
59
int		 show_mfc_detail_msg(struct imsg *);
60
const char *	 get_linkstate(uint8_t, int);
61
62
struct imsgbuf	*ibuf;
63
64
__dead void
65
usage(void)
66
{
67
	extern char *__progname;
68
69
	fprintf(stderr, "usage: %s command [argument ...]\n", __progname);
70
	exit(1);
71
}
72
73
int
74
main(int argc, char *argv[])
75
{
76
	struct sockaddr_un	 sun;
77
	struct parse_result	*res;
78
	struct imsg		 imsg;
79
	unsigned int		 ifidx = 0;
80
	int			 ctl_sock;
81
	int			 done = 0, verbose = 0;
82
	int			 n;
83
84
	/* parse options */
85
	if ((res = parse(argc - 1, argv + 1)) == NULL)
86
		exit(1);
87
88
	/* connect to dvmrpd control socket */
89
	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
90
		err(1, "socket");
91
92
	bzero(&sun, sizeof(sun));
93
	sun.sun_family = AF_UNIX;
94
	strlcpy(sun.sun_path, DVMRPD_SOCKET, sizeof(sun.sun_path));
95
	if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1)
96
		err(1, "connect: %s", DVMRPD_SOCKET);
97
98
	if (pledge("stdio flock rpath cpath wpath", NULL) == -1)
99
		err(1, "pledge");
100
101
	if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
102
		fatal(NULL);
103
	imsg_init(ibuf, ctl_sock);
104
	done = 0;
105
106
	/* process user request */
107
	switch (res->action) {
108
	case NONE:
109
		usage();
110
		/* NOTREACHED */
111
	case SHOW:
112
	case SHOW_SUM:
113
		imsg_compose(ibuf, IMSG_CTL_SHOW_SUM, 0, 0, -1, NULL, 0);
114
		break;
115
	case SHOW_IFACE:
116
		printf("%-11s %-18s %-10s %-10s %-10s %-8s %s\n",
117
		    "Interface", "Address", "State", "ProbeTimer", "Linkstate",
118
		    "Uptime", "Groups");
119
		/* FALLTHROUGH */
120
	case SHOW_IFACE_DTAIL:
121
		if (*res->ifname) {
122
			ifidx = if_nametoindex(res->ifname);
123
			if (ifidx == 0)
124
				errx(1, "no such interface %s", res->ifname);
125
		}
126
		imsg_compose(ibuf, IMSG_CTL_SHOW_IFACE, 0, 0, -1, &ifidx,
127
		    sizeof(ifidx));
128
		break;
129
	case SHOW_IGMP:
130
		if (*res->ifname) {
131
			ifidx = if_nametoindex(res->ifname);
132
			if (ifidx == 0)
133
				errx(1, "no such interface %s", res->ifname);
134
		}
135
		imsg_compose(ibuf, IMSG_CTL_SHOW_IGMP, 0, 0, -1, &ifidx,
136
		    sizeof(ifidx));
137
		break;
138
	case SHOW_NBR:
139
		printf("%-15s %-10s %-9s %-15s %-11s %-8s\n", "ID", "State",
140
		    "DeadTime", "Address", "Interface", "Uptime");
141
		/* FALLTHROUGH */
142
	case SHOW_NBR_DTAIL:
143
		imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0);
144
		break;
145
	case SHOW_RIB:
146
		printf("%-20s %-17s %-7s %-10s %-s\n", "Destination", "Nexthop",
147
		    "Cost", "Uptime", "Expire");
148
		/* FALLTHROUGH */
149
	case SHOW_RIB_DTAIL:
150
		imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, -1, NULL, 0);
151
		break;
152
	case SHOW_MFC:
153
		printf("%-16s %-16s %-9s %-9s %-4s %-10s %-10s\n", "Group",
154
		    "Origin", "Incoming", "Outgoing", "TTL", "Uptime",
155
		    "Expire");
156
		/* FALLTHROUGH */
157
	case SHOW_MFC_DTAIL:
158
		imsg_compose(ibuf, IMSG_CTL_SHOW_MFC, 0, 0, -1, NULL, 0);
159
		break;
160
	case LOG_VERBOSE:
161
		verbose = 1;
162
		/* FALLTHROUGH */
163
	case LOG_BRIEF:
164
		imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1,
165
		    &verbose, sizeof(verbose));
166
		printf("logging request sent.\n");
167
		done = 1;
168
		break;
169
	case RELOAD:
170
		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0);
171
		printf("reload request sent.\n");
172
		done = 1;
173
		break;
174
	}
175
176
	while (ibuf->w.queued)
177
		if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
178
			err(1, "write error");
179
180
	while (!done) {
181
		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
182
			errx(1, "imsg_read error");
183
		if (n == 0)
184
			errx(1, "pipe closed");
185
186
		while (!done) {
187
			if ((n = imsg_get(ibuf, &imsg)) == -1)
188
				errx(1, "imsg_get error");
189
			if (n == 0)
190
				break;
191
			switch (res->action) {
192
			case SHOW:
193
			case SHOW_SUM:
194
				done = show_summary_msg(&imsg);
195
				break;
196
			case SHOW_IFACE:
197
				done = show_interface_msg(&imsg);
198
				break;
199
			case SHOW_IFACE_DTAIL:
200
				done = show_interface_detail_msg(&imsg);
201
				break;
202
			case SHOW_IGMP:
203
				done = show_igmp_msg(&imsg);
204
				break;
205
			case SHOW_NBR:
206
				done = show_nbr_msg(&imsg);
207
				break;
208
			case SHOW_NBR_DTAIL:
209
				done = show_nbr_detail_msg(&imsg);
210
				break;
211
			case SHOW_RIB:
212
				done = show_rib_msg(&imsg);
213
				break;
214
			case SHOW_RIB_DTAIL:
215
				done = show_rib_detail_msg(&imsg);
216
				break;
217
			case SHOW_MFC:
218
				done = show_mfc_msg(&imsg);
219
				break;
220
			case SHOW_MFC_DTAIL:
221
				done = show_mfc_detail_msg(&imsg);
222
				break;
223
			case NONE:
224
			case LOG_VERBOSE:
225
			case LOG_BRIEF:
226
			case RELOAD:
227
				break;
228
			}
229
			imsg_free(&imsg);
230
		}
231
	}
232
	close(ctl_sock);
233
	free(ibuf);
234
235
	return (0);
236
}
237
238
int
239
show_summary_msg(struct imsg *imsg)
240
{
241
	struct ctl_sum		*sum;
242
243
	switch (imsg->hdr.type) {
244
	case IMSG_CTL_SHOW_SUM:
245
		sum = imsg->data;
246
		printf("Router ID: %s\n", inet_ntoa(sum->rtr_id));
247
		printf("Hold time is %d sec(s)\n", sum->hold_time);
248
		break;
249
	case IMSG_CTL_END:
250
		printf("\n");
251
		return (1);
252
	default:
253
		break;
254
	}
255
256
	return (0);
257
}
258
259
int
260
show_interface_msg(struct imsg *imsg)
261
{
262
	struct ctl_iface	*iface;
263
	char			*netid;
264
265
	switch (imsg->hdr.type) {
266
	case IMSG_CTL_SHOW_IFACE:
267
		iface = imsg->data;
268
269
		if (asprintf(&netid, "%s/%d", inet_ntoa(iface->addr),
270
		    mask2prefixlen(iface->mask.s_addr)) == -1)
271
			err(1, NULL);
272
		printf("%-11s %-18s %-10s %-10s %-10s %-8s %5d\n",
273
		    iface->name, netid, if_state_name(iface->state),
274
		    iface->probe_timer == 0 ? "00:00:00" :
275
		    fmt_timeframe_core(iface->probe_timer),
276
		    get_linkstate(iface->if_type, iface->linkstate),
277
		    iface->uptime == 0 ? "00:00:00" :
278
		    fmt_timeframe_core(iface->uptime), iface->group_cnt);
279
		free(netid);
280
		break;
281
	case IMSG_CTL_END:
282
		printf("\n");
283
		return (1);
284
	default:
285
		break;
286
	}
287
288
	return (0);
289
}
290
291
int
292
show_interface_detail_msg(struct imsg *imsg)
293
{
294
	struct ctl_iface	*iface;
295
296
	switch (imsg->hdr.type) {
297
	case IMSG_CTL_SHOW_IFACE:
298
		iface = imsg->data;
299
300
		printf("\n");
301
		printf("Interface %s, line protocol is %s\n",
302
		    iface->name, print_link(iface->flags));
303
		printf("  Internet address %s/%d\n",
304
		    inet_ntoa(iface->addr),
305
		    mask2prefixlen(iface->mask.s_addr));
306
		printf("  Linkstate %s\n",
307
		    get_linkstate(iface->if_type, iface->linkstate));
308
		printf("  Network type %s, cost: %d\n",
309
		    if_type_name(iface->type), iface->metric);
310
		printf("  State %s, querier ", if_state_name(iface->state));
311
		if (iface->state == IF_STA_QUERIER)
312
			printf("%s\n", inet_ntoa(iface->addr));
313
		else
314
			printf("%s\n", inet_ntoa(iface->querier));
315
		printf("  Generation ID %d\n", iface->gen_id);
316
		printf("  Timer intervals configured, "
317
		    "probe %d, dead %d\n", iface->probe_interval,
318
		    iface->dead_interval);
319
		if (iface->passive)
320
			printf("    Passive interface (No Hellos)\n");
321
		else if (iface->probe_timer < 0)
322
			printf("    Hello timer not running\n");
323
		else
324
			printf("    Hello timer due in %s\n",
325
			    fmt_timeframe_core(iface->probe_timer));
326
		printf("    Uptime %s\n", iface->uptime == 0 ?
327
		    "00:00:00" : fmt_timeframe_core(iface->uptime));
328
		printf("  Adjacent neighbor count is "
329
		    "%d\n", iface->adj_cnt);
330
		break;
331
	case IMSG_CTL_END:
332
		printf("\n");
333
		return (1);
334
	default:
335
		break;
336
	}
337
338
	return (0);
339
}
340
341
int
342
show_igmp_msg(struct imsg *imsg)
343
{
344
	struct ctl_iface	*iface;
345
	struct ctl_group	*group;
346
	char			*netid;
347
348
	switch (imsg->hdr.type) {
349
	case IMSG_CTL_SHOW_IFACE:
350
		iface = imsg->data;
351
		if (asprintf(&netid, "%s/%d", inet_ntoa(iface->addr),
352
		    mask2prefixlen(iface->mask.s_addr)) == -1)
353
			err(1, NULL);
354
		printf("\nInterface %s, address %s, state %s, groups %d\n",
355
		    iface->name, netid, if_state_name(iface->state),
356
		    iface->group_cnt);
357
		free(netid);
358
		printf("  %-16s %-10s %-10s %-10s\n", "Group", "State",
359
		    "DeadTimer", "Uptime");
360
		break;
361
	case IMSG_CTL_SHOW_IGMP:
362
		group = imsg->data;
363
		printf("  %-16s %-10s %-10s %-10s\n", inet_ntoa(group->addr),
364
		    group_state_name(group->state),
365
		    group->dead_timer == 0 ? "00:00:00" :
366
		    fmt_timeframe_core(group->dead_timer),
367
		    group->uptime == 0 ? "00:00:00" :
368
		    fmt_timeframe_core(group->uptime));
369
		break;
370
	case IMSG_CTL_END:
371
		printf("\n");
372
		return (1);
373
	default:
374
		break;
375
	}
376
377
	return (0);
378
}
379
380
const char *
381
print_if_type(enum iface_type type)
382
{
383
	switch (type) {
384
	case IF_TYPE_POINTOPOINT:
385
		return ("POINTOPOINT");
386
	case IF_TYPE_BROADCAST:
387
		return ("BROADCAST");
388
	default:
389
		return ("UNKNOWN");
390
	}
391
}
392
393
const char *
394
print_nbr_state(int state)
395
{
396
	switch (state) {
397
	case NBR_STA_DOWN:
398
		return ("DOWN");
399
	case NBR_STA_1_WAY:
400
		return ("1-WAY");
401
	case NBR_STA_2_WAY:
402
		return ("2-WAY");
403
	default:
404
		return ("UNKNOWN");
405
	}
406
}
407
408
const char *
409
print_link(int state)
410
{
411
	if (state & IFF_UP)
412
		return ("UP");
413
	else
414
		return ("DOWN");
415
}
416
417
#define TF_BUFS	8
418
#define TF_LEN	9
419
420
const char *
421
fmt_timeframe(time_t t)
422
{
423
	if (t == 0)
424
		return ("Never");
425
	else
426
		return (fmt_timeframe_core(time(NULL) - t));
427
}
428
429
const char *
430
fmt_timeframe_core(time_t t)
431
{
432
	char		*buf;
433
	static char	 tfbuf[TF_BUFS][TF_LEN];	/* ring buffer */
434
	static int	 idx = 0;
435
	unsigned int	 sec, min, hrs, day;
436
	unsigned long long	week;
437
438
	if (t == 0)
439
		return ("Stopped");
440
441
	buf = tfbuf[idx++];
442
	if (idx == TF_BUFS)
443
		idx = 0;
444
445
	week = t;
446
447
	sec = week % 60;
448
	week /= 60;
449
	min = week % 60;
450
	week /= 60;
451
	hrs = week % 24;
452
	week /= 24;
453
	day = week % 7;
454
	week /= 7;
455
456
	if (week > 0)
457
		snprintf(buf, TF_LEN, "%02lluw%01ud%02uh", week, day, hrs);
458
	else if (day > 0)
459
		snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
460
	else
461
		snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
462
463
	return (buf);
464
}
465
466
/* prototype defined in dvmrpd.h and shared with the kroute.c version */
467
u_int8_t
468
mask2prefixlen(in_addr_t ina)
469
{
470
	if (ina == 0)
471
		return (0);
472
	else
473
		return (33 - ffs(ntohl(ina)));
474
}
475
476
int
477
show_nbr_msg(struct imsg *imsg)
478
{
479
	struct ctl_nbr	*nbr;
480
481
	switch (imsg->hdr.type) {
482
	case IMSG_CTL_SHOW_NBR:
483
		nbr = imsg->data;
484
		printf("%-15s %-10s %-10s", inet_ntoa(nbr->id),
485
		    print_nbr_state(nbr->state),
486
		    fmt_timeframe_core(nbr->dead_timer));
487
		printf("%-15s %-11s %s\n", inet_ntoa(nbr->addr),
488
		    nbr->name, fmt_timeframe_core(nbr->uptime));
489
		break;
490
	case IMSG_CTL_END:
491
		printf("\n");
492
		return (1);
493
	default:
494
		break;
495
	}
496
497
	return (0);
498
}
499
500
const char *
501
print_dvmrp_options(u_int8_t opts)
502
{
503
	static char	optbuf[32];
504
505
	snprintf(optbuf, sizeof(optbuf), "*|*|%s|%s|%s|%s|%s|%s",
506
	    opts & DVMRP_CAP_NETMASK ? "N" : "-",
507
	    opts & DVMRP_CAP_SNMP ? "S" : "-",
508
	    opts & DVMRP_CAP_MTRACE ? "M" : "-",
509
	    opts & DVMRP_CAP_GENID ? "G" : "-",
510
	    opts & DVMRP_CAP_PRUNE ? "P" : "-",
511
	    opts & DVMRP_CAP_LEAF ? "L" : "-");
512
	return (optbuf);
513
}
514
515
int
516
show_nbr_detail_msg(struct imsg *imsg)
517
{
518
	struct ctl_nbr	*nbr;
519
520
	switch (imsg->hdr.type) {
521
	case IMSG_CTL_SHOW_NBR:
522
		nbr = imsg->data;
523
		break;
524
	case IMSG_CTL_END:
525
		printf("\n");
526
		return (1);
527
	default:
528
		break;
529
	}
530
531
	return (0);
532
}
533
534
int
535
show_rib_msg(struct imsg *imsg)
536
{
537
	struct ctl_rt	*rt;
538
	char		*dstnet;
539
540
	switch (imsg->hdr.type) {
541
	case IMSG_CTL_SHOW_RIB:
542
		rt = imsg->data;
543
		if (asprintf(&dstnet, "%s/%d", inet_ntoa(rt->prefix),
544
		    rt->prefixlen) == -1)
545
			err(1, NULL);
546
547
		printf("%-20s %-17s %-7d %-9s %9s\n", dstnet,
548
		    inet_ntoa(rt->nexthop),
549
		    rt->cost, rt->uptime == 0 ? "-" :
550
		    fmt_timeframe_core(rt->uptime),
551
		    rt->expire == 0 ? "00:00:00" :
552
		    fmt_timeframe_core(rt->expire));
553
		free(dstnet);
554
555
		break;
556
	case IMSG_CTL_END:
557
		printf("\n");
558
		return (1);
559
	default:
560
		break;
561
	}
562
563
	return (0);
564
}
565
566
int
567
show_rib_detail_msg(struct imsg *imsg)
568
{
569
570
	switch (imsg->hdr.type) {
571
	case IMSG_CTL_SHOW_RIB:
572
		break;
573
	case IMSG_CTL_END:
574
		printf("\n");
575
		return (1);
576
	default:
577
		break;
578
	}
579
580
	return (0);
581
}
582
583
int
584
show_mfc_msg(struct imsg *imsg)
585
{
586
	char		 iname[IF_NAMESIZE];
587
	char		 oname[IF_NAMESIZE] = "-";
588
	struct ctl_mfc	*mfc;
589
	int		 i;
590
591
592
	switch (imsg->hdr.type) {
593
	case IMSG_CTL_SHOW_MFC:
594
		mfc = imsg->data;
595
		if_indextoname(mfc->ifindex, iname);
596
597
		/* search for first entry with ttl > 0 */
598
		for (i = 0; i < MAXVIFS; i++) {
599
			if (mfc->ttls[i] > 0) {
600
				if_indextoname(i, oname);
601
				i++;
602
				break;
603
			}
604
		}
605
606
		/* display first entry with uptime */
607
		printf("%-16s ", inet_ntoa(mfc->group));
608
		printf("%-16s %-9s %-9s %-4d %-10s %-10s\n",
609
		    inet_ntoa(mfc->origin), iname, oname, mfc->ttls[i - 1],
610
		    mfc->uptime == 0 ? "-" : fmt_timeframe_core(mfc->uptime),
611
		    mfc->expire == 0 ? "-" : fmt_timeframe_core(mfc->expire));
612
613
		/* display remaining entries with ttl > 0 */
614
		for (; i < MAXVIFS; i++) {
615
			if (mfc->ttls[i] > 0) {
616
				if_indextoname(i, oname);
617
				printf("%43s %-9s %-4d\n", " ", oname,
618
				    mfc->ttls[i]);
619
			}
620
		}
621
		break;
622
	case IMSG_CTL_END:
623
		printf("\n");
624
		return (1);
625
	default:
626
		break;
627
	}
628
629
	return (0);
630
}
631
632
int
633
show_mfc_detail_msg(struct imsg *imsg)
634
{
635
636
	switch (imsg->hdr.type) {
637
	case IMSG_CTL_SHOW_MFC:
638
		break;
639
	case IMSG_CTL_END:
640
		printf("\n");
641
		return (1);
642
	default:
643
		break;
644
	}
645
646
	return (0);
647
}
648
649
const struct if_status_description
650
		if_status_descriptions[] = LINK_STATE_DESCRIPTIONS;
651
652
const char *
653
get_linkstate(uint8_t if_type, int link_state)
654
{
655
	const struct if_status_description *p;
656
	static char buf[8];
657
658
	for (p = if_status_descriptions; p->ifs_string != NULL; p++) {
659
		if (LINK_STATE_DESC_MATCH(p, if_type, link_state))
660
			return (p->ifs_string);
661
	}
662
	snprintf(buf, sizeof(buf), "[#%d]", link_state);
663
	return (buf);
664
}