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

Line Branch Exec Source
1
/*	$OpenBSD: ripctl.c,v 1.17 2016/08/02 16:05:32 jca Exp $
2
 *
3
 * Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it>
4
 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
5
 * Copyright (c) 2004, 2005 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 <arpa/inet.h>
26
#include <net/if_media.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 "rip.h"
37
#include "ripd.h"
38
#include "ripe.h"
39
#include "parser.h"
40
41
__dead void	 usage(void);
42
const char	*fmt_timeframe_core(time_t);
43
const char	*get_linkstate(uint8_t, int);
44
int		 show_interface_msg(struct imsg *);
45
uint64_t	 get_ifms_type(uint8_t);
46
int		 show_rib_msg(struct imsg *);
47
int		 show_nbr_msg(struct imsg *);
48
void		 show_fib_head(void);
49
int		 show_fib_msg(struct imsg *);
50
void		 show_interface_head(void);
51
int		 show_fib_interface_msg(struct imsg *);
52
const char	*get_media_descr(uint64_t);
53
void		 print_baudrate(uint64_t);
54
55
struct imsgbuf	*ibuf;
56
57
__dead void
58
usage(void)
59
{
60
	extern char *__progname;
61
62
	fprintf(stderr, "usage: %s [-s socket] command [argument ...]\n",
63
	    __progname);
64
	exit(1);
65
}
66
67
int
68
main(int argc, char *argv[])
69
{
70
	struct sockaddr_un	 sun;
71
	struct parse_result	*res;
72
	struct imsg		 imsg;
73
	unsigned int		 ifidx = 0;
74
	int			 ctl_sock;
75
	int			 done = 0, verbose = 0;
76
	int			 n;
77
	int			 ch;
78
	char			*sockname = RIPD_SOCKET;
79
80
	while ((ch = getopt(argc, argv, "s:")) != -1) {
81
		switch (ch) {
82
		case 's':
83
			sockname = optarg;
84
			break;
85
		default:
86
			usage();
87
			/* NOTREACHED */
88
		}
89
	}
90
91
	argc -= optind;
92
	argv += optind;
93
94
	/* parse options */
95
	if ((res = parse(argc, argv)) == NULL)
96
		exit(1);
97
98
	/* connect to ripd control socket */
99
	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
100
		err(1, "socket");
101
102
	bzero(&sun, sizeof(sun));
103
	sun.sun_family = AF_UNIX;
104
	strlcpy(sun.sun_path, sockname, sizeof(sun.sun_path));
105
	if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1)
106
		err(1, "connect: %s", sockname);
107
108
	if (pledge("stdio flock rpath cpath wpath", NULL) == -1)
109
		err(1, "pledge");
110
111
	if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
112
		err(1, NULL);
113
	imsg_init(ibuf, ctl_sock);
114
	done = 0;
115
116
	/* process user request */
117
	switch (res->action) {
118
	case NONE:
119
		usage();
120
		/* not reached */
121
	case SHOW:
122
	case SHOW_IFACE:
123
		printf("%-11s %-18s %-10s %-10s %-8s\n",
124
		    "Interface", "Address", "State", "Linkstate",
125
		    "Uptime");
126
		if (*res->ifname) {
127
			ifidx = if_nametoindex(res->ifname);
128
			if (ifidx == 0)
129
				errx(1, "no such interface %s", res->ifname);
130
		}
131
		imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1,
132
		    &ifidx, sizeof(ifidx));
133
		break;
134
	case SHOW_NBR:
135
		printf("%-15s %-15s %-15s %-9s %-10s\n", "ID",
136
		    "State", "Address", "Iface", "Uptime");
137
		imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0);
138
		break;
139
	case SHOW_RIB:
140
		printf("%-20s %-17s %-7s\n", "Destination",
141
		    "Nexthop", "Cost");
142
		imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, -1, NULL, 0);
143
		break;
144
	case SHOW_FIB:
145
		if (!res->addr.s_addr)
146
			imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0, -1,
147
			    &res->flags, sizeof(res->flags));
148
		else
149
			imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1,
150
			    &res->addr, sizeof(res->addr));
151
		show_fib_head();
152
		break;
153
	case SHOW_FIB_IFACE:
154
		if (*res->ifname)
155
			imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1,
156
			    res->ifname, sizeof(res->ifname));
157
		else
158
			imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1, NULL, 0);
159
		show_interface_head();
160
		break;
161
	case FIB:
162
		errx(1, "fib couple|decouple");
163
		break;
164
	case FIB_COUPLE:
165
		imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, -1, NULL, 0);
166
		printf("couple request sent.\n");
167
		done = 1;
168
		break;
169
	case FIB_DECOUPLE:
170
		imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, -1, NULL, 0);
171
		printf("decouple request sent.\n");
172
		done = 1;
173
		break;
174
	case LOG_VERBOSE:
175
		verbose = 1;
176
		/* FALLTHROUGH */
177
	case LOG_BRIEF:
178
		imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1,
179
		    &verbose, sizeof(verbose));
180
		printf("logging request sent.\n");
181
		done = 1;
182
		break;
183
	case RELOAD:
184
		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0);
185
		printf("reload request sent.\n");
186
		done = 1;
187
		break;
188
	}
189
190
	while (ibuf->w.queued)
191
		if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
192
			err(1, "write error");
193
194
	while (!done) {
195
		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
196
			errx(1, "imsg_read error");
197
		if (n == 0)
198
			errx(1, "pipe closed");
199
200
		while (!done) {
201
			if ((n = imsg_get(ibuf, &imsg)) == -1)
202
				errx(1, "imsg_get error");
203
			if (n == 0)
204
				break;
205
			switch (res->action) {
206
			case SHOW:
207
			case SHOW_IFACE:
208
				done = show_interface_msg(&imsg);
209
				break;
210
			case SHOW_NBR:
211
				done = show_nbr_msg(&imsg);
212
				break;
213
			case SHOW_RIB:
214
				done = show_rib_msg(&imsg);
215
				break;
216
			case SHOW_FIB:
217
				done = show_fib_msg(&imsg);
218
				break;
219
			case SHOW_FIB_IFACE:
220
				done = show_fib_interface_msg(&imsg);
221
				break;
222
			case NONE:
223
			case FIB:
224
			case FIB_COUPLE:
225
			case FIB_DECOUPLE:
226
			case LOG_VERBOSE:
227
			case LOG_BRIEF:
228
			case RELOAD:
229
				break;
230
			}
231
			imsg_free(&imsg);
232
		}
233
	}
234
	close(ctl_sock);
235
	free(ibuf);
236
237
	return (0);
238
}
239
240
uint64_t
241
get_ifms_type(uint8_t if_type)
242
{
243
	switch (if_type) {
244
	case IFT_ETHER:
245
		return (IFM_ETHER);
246
		break;
247
	case IFT_FDDI:
248
		return (IFM_FDDI);
249
		break;
250
	case IFT_CARP:
251
		return (IFM_CARP);
252
		break;
253
	default:
254
		return (0);
255
		break;
256
	}
257
}
258
259
#define	TF_BUFS	8
260
#define	TF_LEN	9
261
262
const char *
263
fmt_timeframe_core(time_t t)
264
{
265
	char		*buf;
266
	static char	 tfbuf[TF_BUFS][TF_LEN];	/* ring buffer */
267
	static int	 idx = 0;
268
	unsigned int	 sec, min, hrs, day;
269
	unsigned long long	week;
270
271
	if (t == 0)
272
		return ("Stopped");
273
274
	buf = tfbuf[idx++];
275
	if (idx == TF_BUFS)
276
		idx = 0;
277
278
	week = t;
279
280
	sec = week % 60;
281
	week /= 60;
282
	min = week % 60;
283
	week /= 60;
284
	hrs = week % 24;
285
	week /= 24;
286
	day = week % 7;
287
	week /= 7;
288
289
	if (week > 0)
290
		snprintf(buf, TF_LEN, "%02lluw%01ud%02uh", week, day, hrs);
291
	else if (day > 0)
292
		snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
293
	else
294
		snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
295
296
	return (buf);
297
}
298
299
/* prototype defined in ripd.h and shared with the kroute.c version */
300
u_int8_t
301
mask2prefixlen(in_addr_t ina)
302
{
303
	if (ina == 0)
304
		return (0);
305
	else
306
		return (33 - ffs(ntohl(ina)));
307
}
308
309
int
310
show_interface_msg(struct imsg *imsg)
311
{
312
	struct ctl_iface	*iface;
313
	char			*netid;
314
315
	switch (imsg->hdr.type) {
316
	case IMSG_CTL_SHOW_IFACE:
317
		iface = imsg->data;
318
319
		if (asprintf(&netid, "%s/%d", inet_ntoa(iface->addr),
320
		    mask2prefixlen(iface->mask.s_addr)) == -1)
321
			err(1, NULL);
322
		printf("%-11s %-18s %-10s %-10s %-8s\n",
323
		    iface->name, netid, if_state_name(iface->state),
324
		    get_linkstate(iface->if_type, iface->linkstate),
325
		    iface->uptime == 0 ? "00:00:00" :
326
		    fmt_timeframe_core(iface->uptime));
327
		free(netid);
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_rib_msg(struct imsg *imsg)
341
{
342
	struct ctl_rt	*rt;
343
	char		*dstnet;
344
345
	switch (imsg->hdr.type) {
346
	case IMSG_CTL_SHOW_RIB:
347
		rt = imsg->data;
348
		if (asprintf(&dstnet, "%s/%d", inet_ntoa(rt->prefix),
349
		    mask2prefixlen(rt->netmask.s_addr)) == -1)
350
			err(1, NULL);
351
352
		printf("%-20s %-17s %-7d\n", dstnet,
353
		    inet_ntoa(rt->nexthop),
354
		    rt->metric);
355
		free(dstnet);
356
357
		break;
358
	case IMSG_CTL_END:
359
		printf("\n");
360
		return (1);
361
	default:
362
		break;
363
	}
364
365
	return (0);
366
}
367
368
int
369
show_nbr_msg(struct imsg *imsg)
370
{
371
	struct ctl_nbr	*nbr;
372
	char		*state;
373
374
	switch (imsg->hdr.type) {
375
	case IMSG_CTL_SHOW_NBR:
376
		nbr = imsg->data;
377
		if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state),
378
		    if_state_name(nbr->iface_state)) == -1)
379
			err(1, NULL);
380
		printf("%-15s %-16s", inet_ntoa(nbr->id),
381
		    state);
382
		printf("%-15s %-10s", inet_ntoa(nbr->addr), nbr->name);
383
		printf("%-15s\n", nbr->uptime == 0 ? "-" :
384
		    fmt_timeframe_core(nbr->uptime));
385
		free(state);
386
		break;
387
	case IMSG_CTL_END:
388
		printf("\n");
389
		return (1);
390
	default:
391
		break;
392
	}
393
394
	return (0);
395
}
396
397
void
398
show_fib_head(void)
399
{
400
	printf("flags: * = valid, R = RIP, C = Connected, S = Static\n");
401
	printf("%-6s %-20s %-17s\n", "Flags", "Destination", "Nexthop");
402
}
403
404
int
405
show_fib_msg(struct imsg *imsg)
406
{
407
	struct kroute		*k;
408
	char			*p;
409
410
	switch (imsg->hdr.type) {
411
	case IMSG_CTL_KROUTE:
412
		if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute))
413
			errx(1, "wrong imsg len");
414
		k = imsg->data;
415
416
		if (k->flags & F_DOWN)
417
			printf(" ");
418
		else
419
			printf("*");
420
421
		if (k->flags & F_RIPD_INSERTED)
422
			printf("R");
423
		else if (k->flags & F_CONNECTED)
424
			printf("C");
425
		else if (k->flags & F_STATIC)
426
			printf("S");
427
		else
428
			printf(" ");
429
430
		printf("     ");
431
		if (asprintf(&p, "%s/%u", inet_ntoa(k->prefix),
432
		    mask2prefixlen(k->netmask.s_addr)) == -1)
433
			err(1, NULL);
434
		printf("%-20s ", p);
435
		free(p);
436
437
		if (k->nexthop.s_addr)
438
			printf("%s", inet_ntoa(k->nexthop));
439
		else if (k->flags & F_CONNECTED)
440
			printf("link#%u", k->ifindex);
441
		printf("\n");
442
443
		break;
444
	case IMSG_CTL_END:
445
		printf("\n");
446
		return (1);
447
	default:
448
		break;
449
	}
450
451
	return (0);
452
}
453
454
void
455
show_interface_head(void)
456
{
457
	printf("%-15s%-15s%s\n", "Interface", "Flags",
458
	    "Link state");
459
}
460
461
int
462
show_fib_interface_msg(struct imsg *imsg)
463
{
464
	struct kif	*k;
465
	uint64_t	 ifms_type;
466
467
	switch (imsg->hdr.type) {
468
	case IMSG_CTL_IFINFO:
469
		k = imsg->data;
470
		printf("%-15s", k->ifname);
471
		printf("%-15s", k->flags & IFF_UP ? "UP" : "");
472
		ifms_type = get_ifms_type(k->if_type);
473
		if (ifms_type)
474
			printf("%s, ", get_media_descr(ifms_type));
475
476
		printf("%s", get_linkstate(k->if_type, k->link_state));
477
478
		if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) {
479
			printf(", ");
480
			print_baudrate(k->baudrate);
481
		}
482
		printf("\n");
483
		break;
484
	case IMSG_CTL_END:
485
		printf("\n");
486
		return (1);
487
	default:
488
		break;
489
	}
490
491
	return (0);
492
}
493
494
const struct if_status_description
495
		if_status_descriptions[] = LINK_STATE_DESCRIPTIONS;
496
const struct ifmedia_description
497
		ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS;
498
499
const char *
500
get_media_descr(uint64_t media_type)
501
{
502
	const struct ifmedia_description	*p;
503
504
	for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++)
505
		if (media_type == p->ifmt_word)
506
			return (p->ifmt_string);
507
508
	return ("unknown");
509
}
510
511
const char *
512
get_linkstate(uint8_t if_type, int link_state)
513
{
514
	const struct if_status_description *p;
515
	static char buf[8];
516
517
	for (p = if_status_descriptions; p->ifs_string != NULL; p++) {
518
		if (LINK_STATE_DESC_MATCH(p, if_type, link_state))
519
			return (p->ifs_string);
520
	}
521
	snprintf(buf, sizeof(buf), "[#%d]", link_state);
522
	return (buf);
523
}
524
525
void
526
print_baudrate(uint64_t baudrate)
527
{
528
	if (baudrate > IF_Gbps(1))
529
		printf("%llu GBit/s", baudrate / IF_Gbps(1));
530
	else if (baudrate > IF_Mbps(1))
531
		printf("%llu MBit/s", baudrate / IF_Mbps(1));
532
	else if (baudrate > IF_Kbps(1))
533
		printf("%llu KBit/s", baudrate / IF_Kbps(1));
534
	else
535
		printf("%llu Bit/s", baudrate);
536
}