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

Line Branch Exec Source
1
/*	$OpenBSD: ripd.c,v 1.30 2016/09/03 10:28:08 renato Exp $ */
2
3
/*
4
 * Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it>
5
 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
6
 * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
7
 * Copyright (c) 2003, 2004 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/queue.h>
25
#include <sys/time.h>
26
#include <sys/stat.h>
27
#include <sys/wait.h>
28
#include <sys/sysctl.h>
29
30
#include <netinet/in.h>
31
#include <arpa/inet.h>
32
33
#include <event.h>
34
#include <err.h>
35
#include <errno.h>
36
#include <pwd.h>
37
#include <stdio.h>
38
#include <stdlib.h>
39
#include <string.h>
40
#include <signal.h>
41
#include <unistd.h>
42
43
#include "rip.h"
44
#include "ripd.h"
45
#include "ripe.h"
46
#include "log.h"
47
#include "control.h"
48
#include "rde.h"
49
50
__dead void		 usage(void);
51
void			 main_sig_handler(int, short, void *);
52
__dead void		 ripd_shutdown(void);
53
void			 main_dispatch_ripe(int, short, void *);
54
void			 main_dispatch_rde(int, short, void *);
55
56
int			 pipe_parent2ripe[2];
57
int			 pipe_parent2rde[2];
58
int			 pipe_ripe2rde[2];
59
60
struct ripd_conf	*conf = NULL;
61
struct imsgev		*iev_ripe;
62
struct imsgev		*iev_rde;
63
64
pid_t			 ripe_pid = 0;
65
pid_t			 rde_pid = 0;
66
67
__dead void
68
usage(void)
69
{
70
	extern char *__progname;
71
72
	fprintf(stderr,
73
	    "usage: %s [-dnv] [-D macro=value] [-f file] [-s socket]\n",
74
	    __progname);
75
	exit(1);
76
}
77
78
/* ARGSUSED */
79
void
80
main_sig_handler(int sig, short event, void *arg)
81
{
82
	/* signal handler rules don't apply, libevent decouples for us */
83
	switch (sig) {
84
	case SIGTERM:
85
	case SIGINT:
86
		ripd_shutdown();
87
		/* NOTREACHED */
88
	case SIGHUP:
89
		/* reconfigure */
90
		/* ... */
91
		break;
92
	default:
93
		fatalx("unexpected signal");
94
		/* NOTREACHED */
95
	}
96
}
97
98
int
99
main(int argc, char *argv[])
100
{
101
	struct event	 ev_sigint, ev_sigterm, ev_sighup;
102
	int		 mib[4];
103
	int		 debug = 0;
104
	int		 ipforwarding;
105
	int		 ch;
106
	int		 opts = 0;
107
	char		*conffile;
108
	char 		*sockname;
109
	size_t		 len;
110
111
	conffile = CONF_FILE;
112
	ripd_process = PROC_MAIN;
113
	log_procname = log_procnames[ripd_process];
114
	sockname = RIPD_SOCKET;
115
116
	log_init(1);	/* log to stderr until daemonized */
117
	log_verbose(1);
118
119
	while ((ch = getopt(argc, argv, "cdD:f:ns:v")) != -1) {
120
		switch (ch) {
121
		case 'c':
122
			opts |= RIPD_OPT_FORCE_DEMOTE;
123
			break;
124
		case 'd':
125
			debug = 1;
126
			break;
127
		case 'D':
128
			if (cmdline_symset(optarg) < 0)
129
				log_warnx("could not parse macro definition %s",
130
				    optarg);
131
			break;
132
		case 'f':
133
			conffile = optarg;
134
			break;
135
		case 'n':
136
			opts |= RIPD_OPT_NOACTION;
137
			break;
138
		case 's':
139
			sockname = optarg;
140
			break;
141
		case 'v':
142
			if (opts & RIPD_OPT_VERBOSE)
143
				opts |= RIPD_OPT_VERBOSE2;
144
			opts |= RIPD_OPT_VERBOSE;
145
			break;
146
		default:
147
			usage();
148
			/* NOTREACHED */
149
		}
150
	}
151
152
	argc -= optind;
153
	argv += optind;
154
	if (argc > 0)
155
		usage();
156
157
	mib[0] = CTL_NET;
158
	mib[1] = PF_INET;
159
	mib[2] = IPPROTO_IP;
160
	mib[3] = IPCTL_FORWARDING;
161
	len = sizeof(ipforwarding);
162
	if (sysctl(mib, 4, &ipforwarding, &len, NULL, 0) == -1)
163
		err(1, "sysctl");
164
165
	if (!ipforwarding)
166
		log_warnx("WARNING: IP forwarding NOT enabled");
167
168
	/* fetch interfaces early */
169
	kif_init();
170
171
	/* parse config file */
172
	if ((conf = parse_config(conffile, opts)) == NULL )
173
		exit(1);
174
	conf->csock = sockname;
175
176
	if (conf->opts & RIPD_OPT_NOACTION) {
177
		if (conf->opts & RIPD_OPT_VERBOSE)
178
			print_config(conf);
179
		else
180
			fprintf(stderr, "configuration OK\n");
181
		exit(0);
182
	}
183
184
	/* check for root privileges */
185
	if (geteuid())
186
		errx(1, "need root privileges");
187
188
	/* check for ripd user */
189
	if (getpwnam(RIPD_USER) == NULL)
190
		errx(1, "unknown user %s", RIPD_USER);
191
192
	log_init(debug);
193
	log_verbose(conf->opts & RIPD_OPT_VERBOSE);
194
195
	if (!debug)
196
		daemon(1, 0);
197
198
	log_info("startup");
199
200
	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
201
	    PF_UNSPEC, pipe_parent2ripe) == -1)
202
		fatal("socketpair");
203
	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
204
	    PF_UNSPEC, pipe_parent2rde) == -1)
205
		fatal("socketpair");
206
	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
207
	    PF_UNSPEC, pipe_ripe2rde) == -1)
208
		fatal("socketpair");
209
210
	/* start children */
211
	rde_pid = rde(conf, pipe_parent2rde, pipe_ripe2rde, pipe_parent2ripe);
212
	ripe_pid = ripe(conf, pipe_parent2ripe, pipe_ripe2rde, pipe_parent2rde);
213
214
	event_init();
215
216
	/* setup signal handler */
217
	signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL);
218
	signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL);
219
	signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL);
220
	signal_add(&ev_sigint, NULL);
221
	signal_add(&ev_sigterm, NULL);
222
	signal_add(&ev_sighup, NULL);
223
	signal(SIGPIPE, SIG_IGN);
224
225
	/* setup pipes to children */
226
	close(pipe_parent2ripe[1]);
227
	close(pipe_parent2rde[1]);
228
	close(pipe_ripe2rde[0]);
229
	close(pipe_ripe2rde[1]);
230
231
	if ((iev_ripe = malloc(sizeof(struct imsgev))) == NULL ||
232
	    (iev_rde = malloc(sizeof(struct imsgev))) == NULL)
233
		fatal(NULL);
234
	imsg_init(&iev_ripe->ibuf, pipe_parent2ripe[0]);
235
	iev_ripe->handler = main_dispatch_ripe;
236
	imsg_init(&iev_rde->ibuf, pipe_parent2rde[0]);
237
	iev_rde->handler = main_dispatch_rde;
238
239
	/* setup event handler */
240
	iev_ripe->events = EV_READ;
241
	event_set(&iev_ripe->ev, iev_ripe->ibuf.fd, iev_ripe->events,
242
	    iev_ripe->handler, iev_ripe);
243
	event_add(&iev_ripe->ev, NULL);
244
245
	iev_rde->events = EV_READ;
246
	event_set(&iev_rde->ev, iev_rde->ibuf.fd, iev_rde->events,
247
	    iev_rde->handler, iev_rde);
248
	event_add(&iev_rde->ev, NULL);
249
250
	if (kr_init(!(conf->flags & RIPD_FLAG_NO_FIB_UPDATE),
251
	    conf->rdomain) == -1)
252
		fatalx("kr_init failed");
253
254
	event_dispatch();
255
256
	ripd_shutdown();
257
	/* NOTREACHED */
258
	return (0);
259
}
260
261
__dead void
262
ripd_shutdown(void)
263
{
264
	struct iface	*i;
265
	pid_t		 pid;
266
	int		 status;
267
268
	/* close pipes */
269
	msgbuf_clear(&iev_ripe->ibuf.w);
270
	close(iev_ripe->ibuf.fd);
271
	msgbuf_clear(&iev_rde->ibuf.w);
272
	close(iev_rde->ibuf.fd);
273
274
	while ((i = LIST_FIRST(&conf->iface_list)) != NULL) {
275
		LIST_REMOVE(i, entry);
276
		if_del(i);
277
	}
278
279
	control_cleanup(conf->csock);
280
	kr_shutdown();
281
282
	log_debug("waiting for children to terminate");
283
	do {
284
		pid = wait(&status);
285
		if (pid == -1) {
286
			if (errno != EINTR && errno != ECHILD)
287
				fatal("wait");
288
		} else if (WIFSIGNALED(status))
289
			log_warnx("%s terminated; signal %d",
290
			    (pid == rde_pid) ? "route decision engine" :
291
			    "rip engine", WTERMSIG(status));
292
	} while (pid != -1 || (pid == -1 && errno == EINTR));
293
294
	free(iev_ripe);
295
	free(iev_rde);
296
	free(conf);
297
298
	log_info("terminating");
299
	exit(0);
300
}
301
302
/* imsg handling */
303
/* ARGSUSED */
304
void
305
main_dispatch_ripe(int fd, short event, void *bula)
306
{
307
	struct imsgev		*iev = bula;
308
	struct imsgbuf		*ibuf = &iev->ibuf;
309
	struct imsg		 imsg;
310
	struct demote_msg	 dmsg;
311
	ssize_t			 n;
312
	int			 shut = 0, verbose;
313
314
	if (event & EV_READ) {
315
		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
316
			fatal("imsg_read error");
317
		if (n == 0)	/* connection closed */
318
			shut = 1;
319
	}
320
	if (event & EV_WRITE) {
321
		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
322
			fatal("msgbuf_write");
323
		if (n == 0)	/* connection closed */
324
			shut = 1;
325
	}
326
327
	for (;;) {
328
		if ((n = imsg_get(ibuf, &imsg)) == -1)
329
			fatal("imsg_get");
330
331
		if (n == 0)
332
			break;
333
334
		switch (imsg.hdr.type) {
335
		case IMSG_CTL_RELOAD:
336
			/* XXX reconfig */
337
			break;
338
		case IMSG_CTL_FIB_COUPLE:
339
			kr_fib_couple();
340
			break;
341
		case IMSG_CTL_FIB_DECOUPLE:
342
			kr_fib_decouple();
343
			break;
344
		case IMSG_CTL_KROUTE:
345
		case IMSG_CTL_KROUTE_ADDR:
346
			kr_show_route(&imsg);
347
			break;
348
		case IMSG_CTL_IFINFO:
349
			if (imsg.hdr.len == IMSG_HEADER_SIZE)
350
				kr_ifinfo(NULL, imsg.hdr.pid);
351
			else if (imsg.hdr.len == IMSG_HEADER_SIZE + IFNAMSIZ)
352
				kr_ifinfo(imsg.data, imsg.hdr.pid);
353
			else
354
				log_warnx("IFINFO request with wrong len");
355
			break;
356
		case IMSG_DEMOTE:
357
			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(dmsg))
358
				fatalx("invalid size of OE request");
359
			memcpy(&dmsg, imsg.data, sizeof(dmsg));
360
			carp_demote_set(dmsg.demote_group, dmsg.level);
361
			break;
362
		case IMSG_CTL_LOG_VERBOSE:
363
			/* already checked by ripe */
364
			memcpy(&verbose, imsg.data, sizeof(verbose));
365
			log_verbose(verbose);
366
			break;
367
		default:
368
			log_debug("main_dispatch_ripe: error handling imsg %d",
369
			    imsg.hdr.type);
370
			break;
371
		}
372
		imsg_free(&imsg);
373
	}
374
	if (!shut)
375
		imsg_event_add(iev);
376
	else {
377
		/* this pipe is dead, so remove the event handler */
378
		event_del(&iev->ev);
379
		event_loopexit(NULL);
380
	}
381
}
382
383
/* ARGSUSED */
384
void
385
main_dispatch_rde(int fd, short event, void *bula)
386
{
387
	struct imsgev	*iev = bula;
388
	struct imsgbuf	*ibuf = &iev->ibuf;
389
	struct imsg	 imsg;
390
	ssize_t		 n;
391
	int		 shut = 0;
392
393
	if (event & EV_READ) {
394
		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
395
			fatal("imsg_read error");
396
		if (n == 0)	/* connection closed */
397
			shut = 1;
398
	}
399
	if (event & EV_WRITE) {
400
		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
401
			fatal("msgbuf_write");
402
		if (n == 0)	/* connection closed */
403
			shut = 1;
404
	}
405
406
	for (;;) {
407
		if ((n = imsg_get(ibuf, &imsg)) == -1)
408
			fatal("imsg_get");
409
410
		if (n == 0)
411
			break;
412
413
		switch (imsg.hdr.type) {
414
		case IMSG_KROUTE_CHANGE:
415
			if (kr_change(imsg.data))
416
				log_warn("main_dispatch_rde: error changing "
417
				    "route");
418
			break;
419
		case IMSG_KROUTE_DELETE:
420
			if (kr_delete(imsg.data))
421
				log_warn("main_dispatch_rde: error deleting "
422
				    "route");
423
			break;
424
		default:
425
			log_debug("main_dispatch_rde: error handling imsg %d",
426
			    imsg.hdr.type);
427
			break;
428
		}
429
		imsg_free(&imsg);
430
	}
431
	if (!shut)
432
		imsg_event_add(iev);
433
	else {
434
		/* this pipe is dead, so remove the event handler */
435
		event_del(&iev->ev);
436
		event_loopexit(NULL);
437
	}
438
}
439
440
void
441
main_imsg_compose_ripe(int type, pid_t pid, void *data, u_int16_t datalen)
442
{
443
	imsg_compose_event(iev_ripe, type, 0, pid, -1, data, datalen);
444
}
445
446
void
447
main_imsg_compose_rde(int type, pid_t pid, void *data, u_int16_t datalen)
448
{
449
	imsg_compose_event(iev_rde, type, 0, pid, -1, data, datalen);
450
}
451
452
int
453
rip_redistribute(struct kroute *kr)
454
{
455
	struct redistribute	*r;
456
	u_int8_t		 is_default = 0;
457
458
	if (kr->flags & F_RIPD_INSERTED)
459
		return (1);
460
461
	/* only allow 0.0.0.0/0 via REDIST_DEFAULT */
462
	if (kr->prefix.s_addr == INADDR_ANY && kr->netmask.s_addr == INADDR_ANY)
463
		is_default = 1;
464
465
	SIMPLEQ_FOREACH(r, &conf->redist_list, entry) {
466
		switch (r->type & ~REDIST_NO) {
467
		case REDIST_LABEL:
468
			if (kr->rtlabel == r->label)
469
				return (r->type & REDIST_NO ? 0 : 1);
470
			break;
471
		case REDIST_STATIC:
472
			/*
473
			 * Dynamic routes are not redistributable. Placed here
474
			 * so that link local addresses can be redistributed
475
			 * via a rtlabel.
476
			 */
477
			if (is_default)
478
				continue;
479
			if (kr->flags & F_DYNAMIC)
480
				continue;
481
			if (kr->flags & F_STATIC)
482
				return (r->type & REDIST_NO ? 0 : 1);
483
			break;
484
		case REDIST_CONNECTED:
485
			if (is_default)
486
				continue;
487
			if (kr->flags & F_DYNAMIC)
488
				continue;
489
			if (kr->flags & F_CONNECTED)
490
				return (r->type & REDIST_NO ? 0 : 1);
491
			break;
492
		case REDIST_ADDR:
493
			if (kr->flags & F_DYNAMIC)
494
				continue;
495
496
			if (r->addr.s_addr == INADDR_ANY &&
497
			    r->mask.s_addr == INADDR_ANY) {
498
				if (is_default)
499
					return (r->type & REDIST_NO? 0 : 1);
500
				else
501
					return (0);
502
			}
503
504
			if ((kr->prefix.s_addr & r->mask.s_addr) ==
505
			    (r->addr.s_addr & r->mask.s_addr) &&
506
			    (kr->netmask.s_addr & r->mask.s_addr) ==
507
			    r->mask.s_addr)
508
				return (r->type & REDIST_NO? 0 : 1);
509
			break;
510
		case REDIST_DEFAULT:
511
			if (is_default)
512
				return (r->type & REDIST_NO? 0 : 1);
513
			break;
514
		}
515
	}
516
517
	return (0);
518
}
519
520
void
521
imsg_event_add(struct imsgev *iev)
522
{
523
	if (iev->handler == NULL) {
524
		imsg_flush(&iev->ibuf);
525
		return;
526
	}
527
528
	iev->events = EV_READ;
529
	if (iev->ibuf.w.queued)
530
		iev->events |= EV_WRITE;
531
532
	event_del(&iev->ev);
533
	event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev);
534
	event_add(&iev->ev, NULL);
535
}
536
537
int
538
imsg_compose_event(struct imsgev *iev, u_int16_t type,
539
    u_int32_t peerid, pid_t pid, int fd, void *data, u_int16_t datalen)
540
{
541
	int	ret;
542
543
	if ((ret = imsg_compose(&iev->ibuf, type, peerid,
544
	    pid, fd, data, datalen)) != -1)
545
		imsg_event_add(iev);
546
	return (ret);
547
}