GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ldpd/kroute.c Lines: 0 787 0.0 %
Date: 2017-11-07 Branches: 0 917 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: kroute.c,v 1.66 2017/07/24 11:00:01 friehm Exp $ */
2
3
/*
4
 * Copyright (c) 2015, 2016 Renato Westphal <renato@openbsd.org>
5
 * Copyright (c) 2009 Michele Marchetto <michele@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/ioctl.h>
25
#include <sys/sysctl.h>
26
#include <arpa/inet.h>
27
#include <net/if_dl.h>
28
#include <net/if_types.h>
29
#include <net/route.h>
30
#include <netmpls/mpls.h>
31
#include <errno.h>
32
#include <stdlib.h>
33
#include <string.h>
34
#include <unistd.h>
35
#include <limits.h>
36
37
#include "ldpd.h"
38
#include "log.h"
39
40
struct {
41
	uint32_t		rtseq;
42
	pid_t			pid;
43
	int			fib_sync;
44
	int			fd;
45
	int			ioctl_fd;
46
	struct event		ev;
47
	unsigned int		rdomain;
48
} kr_state;
49
50
struct kroute_node {
51
	TAILQ_ENTRY(kroute_node)	 entry;
52
	struct kroute_priority		*kprio;		/* back pointer */
53
	struct kroute			 r;
54
};
55
56
struct kroute_priority {
57
	TAILQ_ENTRY(kroute_priority)	 entry;
58
	struct kroute_prefix		*kp;		/* back pointer */
59
	uint8_t				 priority;
60
	TAILQ_HEAD(, kroute_node)	 nexthops;
61
};
62
63
struct kroute_prefix {
64
	RB_ENTRY(kroute_prefix)		 entry;
65
	int				 af;
66
	union ldpd_addr			 prefix;
67
	uint8_t				 prefixlen;
68
	TAILQ_HEAD(plist, kroute_priority) priorities;
69
};
70
RB_HEAD(kroute_tree, kroute_prefix);
71
RB_PROTOTYPE(kroute_tree, kroute_prefix, entry, kroute_compare)
72
73
struct kif_addr {
74
	TAILQ_ENTRY(kif_addr)	 entry;
75
	struct kaddr		 a;
76
};
77
78
struct kif_node {
79
	RB_ENTRY(kif_node)	 entry;
80
	TAILQ_HEAD(, kif_addr)	 addrs;
81
	struct kif		 k;
82
	struct kpw		*kpw;
83
};
84
RB_HEAD(kif_tree, kif_node);
85
RB_PROTOTYPE(kif_tree, kif_node, entry, kif_compare)
86
87
static void		 kr_dispatch_msg(int, short, void *);
88
static void		 kr_redist_remove(struct kroute *);
89
static int		 kr_redist_eval(struct kroute *);
90
static void		 kr_redistribute(struct kroute_prefix *);
91
static __inline int	 kroute_compare(struct kroute_prefix *,
92
			    struct kroute_prefix *);
93
static struct kroute_prefix	*kroute_find_prefix(int, union ldpd_addr *,
94
			    uint8_t);
95
static struct kroute_priority	*kroute_find_prio(struct kroute_prefix *,
96
			    uint8_t);
97
static struct kroute_node	*kroute_find_gw(struct kroute_priority *,
98
				    union ldpd_addr *);
99
static int		 kroute_insert(struct kroute *);
100
static int		 kroute_uninstall(struct kroute_node *);
101
static int		 kroute_remove(struct kroute *);
102
static void		 kroute_clear(void);
103
static __inline int	 kif_compare(struct kif_node *, struct kif_node *);
104
static struct kif_node	*kif_find(unsigned short);
105
static struct kif_node	*kif_insert(unsigned short);
106
static int		 kif_remove(struct kif_node *);
107
static struct kif_node	*kif_update(unsigned short, int, struct if_data *,
108
			    struct sockaddr_dl *, int *);
109
static struct kroute_priority	*kroute_match(int, union ldpd_addr *);
110
static uint8_t		 prefixlen_classful(in_addr_t);
111
static void		 get_rtaddrs(int, struct sockaddr *,
112
			    struct sockaddr **);
113
static void		 if_change(unsigned short, int, struct if_data *,
114
		 	   struct sockaddr_dl *);
115
static void		 if_newaddr(unsigned short, struct sockaddr *,
116
			    struct sockaddr *, struct sockaddr *);
117
static void		 if_deladdr(unsigned short, struct sockaddr *,
118
			    struct sockaddr *, struct sockaddr *);
119
static void		 if_announce(void *);
120
static int		 send_rtmsg(int, int, struct kroute *, int);
121
static int		 send_rtmsg_v4(int fd, int, struct kroute *, int);
122
static int		 send_rtmsg_v6(int fd, int, struct kroute *, int);
123
static int		 fetchtable(void);
124
static int		 fetchifs(void);
125
static int		 dispatch_rtmsg(void);
126
static int		 rtmsg_process(char *, size_t);
127
static int		 rtmsg_process_route(struct rt_msghdr *,
128
			    struct sockaddr *[RTAX_MAX]);
129
static int		 kmpw_install(const char *, struct kpw *);
130
static int		 kmpw_uninstall(const char *);
131
132
RB_GENERATE(kroute_tree, kroute_prefix, entry, kroute_compare)
133
RB_GENERATE(kif_tree, kif_node, entry, kif_compare)
134
135
static struct kroute_tree	 krt = RB_INITIALIZER(&krt);
136
static struct kif_tree		 kit = RB_INITIALIZER(&kit);
137
138
int
139
kif_init(void)
140
{
141
	if (fetchifs() == -1)
142
		return (-1);
143
144
	return (0);
145
}
146
147
int
148
kr_init(int fs, unsigned int rdomain)
149
{
150
	int		opt = 0, rcvbuf, default_rcvbuf;
151
	socklen_t	optlen;
152
	unsigned int	rtfilter;
153
154
	kr_state.fib_sync = fs;
155
	kr_state.rdomain = rdomain;
156
157
	if ((kr_state.fd = socket(AF_ROUTE,
158
	    SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) == -1) {
159
		log_warn("%s: socket", __func__);
160
		return (-1);
161
	}
162
163
	/* not interested in my own messages */
164
	if (setsockopt(kr_state.fd, SOL_SOCKET, SO_USELOOPBACK,
165
	    &opt, sizeof(opt)) == -1)
166
		log_warn("%s: setsockopt(SO_USELOOPBACK)", __func__);
167
168
	/* filter out unwanted messages */
169
	rtfilter = ROUTE_FILTER(RTM_ADD) | ROUTE_FILTER(RTM_GET) |
170
	    ROUTE_FILTER(RTM_CHANGE) | ROUTE_FILTER(RTM_DELETE) |
171
	    ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_NEWADDR) |
172
	    ROUTE_FILTER(RTM_DELADDR) | ROUTE_FILTER(RTM_IFANNOUNCE);
173
174
	if (setsockopt(kr_state.fd, PF_ROUTE, ROUTE_MSGFILTER,
175
	    &rtfilter, sizeof(rtfilter)) == -1)
176
		log_warn("%s: setsockopt(ROUTE_MSGFILTER)", __func__);
177
178
	/* grow receive buffer, don't wanna miss messages */
179
	optlen = sizeof(default_rcvbuf);
180
	if (getsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF,
181
	    &default_rcvbuf, &optlen) == -1)
182
		log_warn("%s: getsockopt SOL_SOCKET SO_RCVBUF", __func__);
183
	else
184
		for (rcvbuf = MAX_RTSOCK_BUF;
185
		    rcvbuf > default_rcvbuf &&
186
		    setsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF,
187
		    &rcvbuf, sizeof(rcvbuf)) == -1 && errno == ENOBUFS;
188
		    rcvbuf /= 2)
189
			;	/* nothing */
190
191
	kr_state.pid = getpid();
192
	kr_state.rtseq = 1;
193
194
	if (fetchtable() == -1)
195
		return (-1);
196
197
	event_set(&kr_state.ev, kr_state.fd, EV_READ | EV_PERSIST,
198
	    kr_dispatch_msg, NULL);
199
	event_add(&kr_state.ev, NULL);
200
201
	if ((kr_state.ioctl_fd = socket(AF_INET,
202
	    SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) == -1) {
203
		log_warn("%s: ioctl socket", __func__);
204
		return (-1);
205
	}
206
207
	return (0);
208
}
209
210
void
211
kif_redistribute(const char *ifname)
212
{
213
	struct kif_node		*kif;
214
	struct kif_addr		*ka;
215
216
	RB_FOREACH(kif, kif_tree, &kit) {
217
		if (kif->k.rdomain != kr_state.rdomain)
218
			continue;
219
220
		if (ifname && strcmp(kif->k.ifname, ifname) != 0)
221
			continue;
222
223
		TAILQ_FOREACH(ka, &kif->addrs, entry)
224
			main_imsg_compose_ldpe(IMSG_NEWADDR, 0, &ka->a,
225
			    sizeof(ka->a));
226
	}
227
}
228
229
int
230
kr_change(struct kroute *kr)
231
{
232
	struct kroute_prefix	*kp;
233
	struct kroute_priority	*kprio;
234
	struct kroute_node	*kn;
235
	int			 action = RTM_ADD;
236
237
	kp = kroute_find_prefix(kr->af, &kr->prefix, kr->prefixlen);
238
	if (kp == NULL)
239
		goto miss;
240
241
	kprio = kroute_find_prio(kp, kr->priority);
242
	if (kprio == NULL)
243
		goto miss;
244
245
	kn = kroute_find_gw(kprio, &kr->nexthop);
246
	if (kn == NULL)
247
		goto miss;
248
249
	if (kn->r.flags & F_LDPD_INSERTED)
250
		action = RTM_CHANGE;
251
252
	kn->r.local_label = kr->local_label;
253
	kn->r.remote_label = kr->remote_label;
254
	kn->r.flags = kn->r.flags | F_LDPD_INSERTED;
255
256
	/* send update */
257
	if (send_rtmsg(kr_state.fd, action, &kn->r, AF_MPLS) == -1)
258
		return (-1);
259
260
	if (ldp_addrisset(kn->r.af, &kn->r.nexthop) &&
261
	    kn->r.remote_label != NO_LABEL) {
262
		if (send_rtmsg(kr_state.fd, RTM_CHANGE, &kn->r, AF_INET) == -1)
263
			return (-1);
264
	}
265
266
	return (0);
267
268
 miss:
269
	log_warnx("%s: lost FEC %s/%d nexthop %s", __func__,
270
	    log_addr(kr->af, &kr->prefix), kr->prefixlen,
271
	    log_addr(kr->af, &kr->nexthop));
272
	return (-1);
273
}
274
275
int
276
kr_delete(struct kroute *kr)
277
{
278
	struct kroute_prefix	*kp;
279
	struct kroute_priority	*kprio;
280
	struct kroute_node	*kn;
281
	int			 update = 0;
282
283
	kp = kroute_find_prefix(kr->af, &kr->prefix, kr->prefixlen);
284
	if (kp == NULL)
285
		return (0);
286
	kprio = kroute_find_prio(kp, kr->priority);
287
	if (kprio == NULL)
288
		return (0);
289
	kn = kroute_find_gw(kprio, &kr->nexthop);
290
	if (kn == NULL)
291
		return (0);
292
293
	if (!(kn->r.flags & F_LDPD_INSERTED))
294
		return (0);
295
	if (ldp_addrisset(kn->r.af, &kn->r.nexthop) &&
296
	    kn->r.remote_label != NO_LABEL)
297
		update = 1;
298
299
	/* kill MPLS LSP */
300
	if (send_rtmsg(kr_state.fd, RTM_DELETE, &kn->r, AF_MPLS) == -1)
301
		return (-1);
302
303
	kn->r.flags &= ~F_LDPD_INSERTED;
304
	kn->r.local_label = NO_LABEL;
305
	kn->r.remote_label = NO_LABEL;
306
307
	if (update &&
308
	    send_rtmsg(kr_state.fd, RTM_CHANGE, &kn->r, AF_INET) == -1)
309
		return (-1);
310
311
	return (0);
312
}
313
314
void
315
kr_shutdown(void)
316
{
317
	kr_fib_decouple();
318
	kroute_clear();
319
	kif_clear();
320
}
321
322
void
323
kr_fib_couple(void)
324
{
325
	struct kroute_prefix	*kp;
326
	struct kroute_priority	*kprio;
327
	struct kroute_node	*kn;
328
	struct kif_node		*kif;
329
330
	if (kr_state.fib_sync == 1)	/* already coupled */
331
		return;
332
333
	kr_state.fib_sync = 1;
334
335
	RB_FOREACH(kp, kroute_tree, &krt) {
336
		kprio = TAILQ_FIRST(&kp->priorities);
337
		if (kprio == NULL)
338
			continue;
339
340
		TAILQ_FOREACH(kn, &kprio->nexthops, entry) {
341
			if (!(kn->r.flags & F_LDPD_INSERTED))
342
				continue;
343
344
			send_rtmsg(kr_state.fd, RTM_ADD, &kn->r, AF_MPLS);
345
346
			if (ldp_addrisset(kn->r.af, &kn->r.nexthop) &&
347
			    kn->r.remote_label != NO_LABEL) {
348
				send_rtmsg(kr_state.fd, RTM_CHANGE,
349
				    &kn->r, AF_INET);
350
			}
351
		}
352
	}
353
354
	RB_FOREACH(kif, kif_tree, &kit)
355
		if (kif->kpw)
356
			kmpw_install(kif->k.ifname, kif->kpw);
357
358
	log_info("kernel routing table coupled");
359
}
360
361
void
362
kr_fib_decouple(void)
363
{
364
	struct kroute_prefix	*kp;
365
	struct kroute_priority	*kprio;
366
	struct kroute_node	*kn;
367
	uint32_t		 rl;
368
	struct kif_node		*kif;
369
370
	if (kr_state.fib_sync == 0)	/* already decoupled */
371
		return;
372
373
	RB_FOREACH(kp, kroute_tree, &krt) {
374
		kprio = TAILQ_FIRST(&kp->priorities);
375
		if (kprio == NULL)
376
			continue;
377
378
		TAILQ_FOREACH(kn, &kprio->nexthops, entry) {
379
			if (!(kn->r.flags & F_LDPD_INSERTED))
380
				continue;
381
382
			send_rtmsg(kr_state.fd, RTM_DELETE,
383
			    &kn->r, AF_MPLS);
384
385
			if (ldp_addrisset(kn->r.af, &kn->r.nexthop) &&
386
			    kn->r.remote_label != NO_LABEL) {
387
				rl = kn->r.remote_label;
388
				kn->r.remote_label = NO_LABEL;
389
				send_rtmsg(kr_state.fd, RTM_CHANGE,
390
				    &kn->r, AF_INET);
391
				kn->r.remote_label = rl;
392
			}
393
		}
394
	}
395
396
	RB_FOREACH(kif, kif_tree, &kit)
397
		if (kif->kpw)
398
			kmpw_uninstall(kif->k.ifname);
399
400
	kr_state.fib_sync = 0;
401
	log_info("kernel routing table decoupled");
402
}
403
404
void
405
kr_change_egress_label(int af, int was_implicit)
406
{
407
	struct kroute_prefix	*kp;
408
	struct kroute_priority	*kprio;
409
	struct kroute_node	*kn;
410
411
	RB_FOREACH(kp, kroute_tree, &krt) {
412
		if (kp->af != af)
413
			continue;
414
415
		TAILQ_FOREACH(kprio, &kp->priorities, entry) {
416
			TAILQ_FOREACH(kn, &kprio->nexthops, entry) {
417
				if (kn->r.local_label > MPLS_LABEL_RESERVED_MAX)
418
					continue;
419
420
				if (!was_implicit) {
421
					kn->r.local_label = MPLS_LABEL_IMPLNULL;
422
					continue;
423
				}
424
425
				switch (kn->r.af) {
426
				case AF_INET:
427
					kn->r.local_label = MPLS_LABEL_IPV4NULL;
428
					break;
429
				case AF_INET6:
430
					kn->r.local_label = MPLS_LABEL_IPV6NULL;
431
					break;
432
				default:
433
					break;
434
				}
435
			}
436
		}
437
	}
438
}
439
440
/* ARGSUSED */
441
static void
442
kr_dispatch_msg(int fd, short event, void *bula)
443
{
444
	if (dispatch_rtmsg() == -1)
445
		event_loopexit(NULL);
446
}
447
448
void
449
kr_show_route(struct imsg *imsg)
450
{
451
	struct kroute_prefix	*kp;
452
	struct kroute_priority	*kprio;
453
	struct kroute_node	*kn;
454
	int			 flags;
455
	struct kroute		 kr;
456
457
	switch (imsg->hdr.type) {
458
	case IMSG_CTL_KROUTE:
459
		if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(flags)) {
460
			log_warnx("%s: wrong imsg len", __func__);
461
			return;
462
		}
463
		memcpy(&flags, imsg->data, sizeof(flags));
464
465
		RB_FOREACH(kp, kroute_tree, &krt)
466
			TAILQ_FOREACH(kprio, &kp->priorities, entry)
467
				TAILQ_FOREACH(kn, &kprio->nexthops, entry) {
468
					if (flags && !(kn->r.flags & flags))
469
						continue;
470
471
					main_imsg_compose_ldpe(IMSG_CTL_KROUTE,
472
					    imsg->hdr.pid, &kn->r,
473
					    sizeof(kn->r));
474
				}
475
		break;
476
	case IMSG_CTL_KROUTE_ADDR:
477
		if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(kr)) {
478
			log_warnx("%s: wrong imsg len", __func__);
479
			return;
480
		}
481
		memcpy(&kr, imsg->data, sizeof(kr));
482
483
		kprio = kroute_match(kr.af, &kr.prefix);
484
		if (kprio == NULL)
485
			break;
486
487
		TAILQ_FOREACH(kn, &kprio->nexthops, entry)
488
			main_imsg_compose_ldpe(IMSG_CTL_KROUTE, imsg->hdr.pid,
489
			    &kn->r, sizeof(kn->r));
490
		break;
491
	default:
492
		log_debug("%s: error handling imsg", __func__);
493
		break;
494
	}
495
	main_imsg_compose_ldpe(IMSG_CTL_END, imsg->hdr.pid, NULL, 0);
496
}
497
498
void
499
kr_ifinfo(char *ifname, pid_t pid)
500
{
501
	struct kif_node	*kif;
502
503
	RB_FOREACH(kif, kif_tree, &kit)
504
		if (ifname == NULL || !strcmp(ifname, kif->k.ifname)) {
505
			main_imsg_compose_ldpe(IMSG_CTL_IFINFO,
506
			    pid, &kif->k, sizeof(kif->k));
507
		}
508
509
	main_imsg_compose_ldpe(IMSG_CTL_END, pid, NULL, 0);
510
}
511
512
static void
513
kr_redist_remove(struct kroute *kr)
514
{
515
	/* was the route redistributed? */
516
	if ((kr->flags & F_REDISTRIBUTED) == 0)
517
		return;
518
519
	/* remove redistributed flag */
520
	kr->flags &= ~F_REDISTRIBUTED;
521
	main_imsg_compose_lde(IMSG_NETWORK_DEL, 0, kr, sizeof(*kr));
522
}
523
524
static int
525
kr_redist_eval(struct kroute *kr)
526
{
527
	/* was the route redistributed? */
528
	if (kr->flags & F_REDISTRIBUTED)
529
		goto dont_redistribute;
530
531
	/* Dynamic routes are not redistributable. */
532
	if (kr->flags & F_DYNAMIC)
533
		goto dont_redistribute;
534
535
	/* filter-out non-redistributable addresses */
536
	if (bad_addr(kr->af, &kr->prefix) ||
537
	    (kr->af == AF_INET6 && IN6_IS_SCOPE_EMBED(&kr->prefix.v6)))
538
		goto dont_redistribute;
539
540
	/* do not redistribute the default route */
541
	if (kr->prefixlen == 0)
542
		goto dont_redistribute;
543
544
	/*
545
	 * Consider networks with nexthop loopback as not redistributable
546
	 * unless it is a reject or blackhole route.
547
	 */
548
	switch (kr->af) {
549
	case AF_INET:
550
		if (kr->nexthop.v4.s_addr == htonl(INADDR_LOOPBACK) &&
551
		    !(kr->flags & (F_BLACKHOLE|F_REJECT)))
552
			goto dont_redistribute;
553
		break;
554
	case AF_INET6:
555
		if (IN6_IS_ADDR_LOOPBACK(&kr->nexthop.v6) &&
556
		    !(kr->flags & (F_BLACKHOLE|F_REJECT)))
557
			goto dont_redistribute;
558
		break;
559
	default:
560
		log_debug("%s: unexpected address-family", __func__);
561
		break;
562
	}
563
564
	/* prefix should be redistributed */
565
	kr->flags |= F_REDISTRIBUTED;
566
	main_imsg_compose_lde(IMSG_NETWORK_ADD, 0, kr, sizeof(*kr));
567
	return (1);
568
569
 dont_redistribute:
570
	return (0);
571
}
572
573
static void
574
kr_redistribute(struct kroute_prefix *kp)
575
{
576
	struct kroute_priority	*kprio;
577
	struct kroute_node	*kn;
578
579
	TAILQ_FOREACH_REVERSE(kprio, &kp->priorities, plist, entry) {
580
		if (kprio == TAILQ_FIRST(&kp->priorities)) {
581
			TAILQ_FOREACH(kn, &kprio->nexthops, entry)
582
				kr_redist_eval(&kn->r);
583
		} else {
584
			TAILQ_FOREACH(kn, &kprio->nexthops, entry)
585
				kr_redist_remove(&kn->r);
586
		}
587
	}
588
}
589
590
/* rb-tree compare */
591
static __inline int
592
kroute_compare(struct kroute_prefix *a, struct kroute_prefix *b)
593
{
594
	int		 addrcmp;
595
596
	if (a->af < b->af)
597
		return (-1);
598
	if (a->af > b->af)
599
		return (1);
600
601
	addrcmp = ldp_addrcmp(a->af, &a->prefix, &b->prefix);
602
	if (addrcmp != 0)
603
		return (addrcmp);
604
605
	if (a->prefixlen < b->prefixlen)
606
		return (-1);
607
	if (a->prefixlen > b->prefixlen)
608
		return (1);
609
610
	return (0);
611
}
612
613
/* tree management */
614
static struct kroute_prefix *
615
kroute_find_prefix(int af, union ldpd_addr *prefix, uint8_t prefixlen)
616
{
617
	struct kroute_prefix	 s;
618
619
	s.af = af;
620
	s.prefix = *prefix;
621
	s.prefixlen = prefixlen;
622
623
	return (RB_FIND(kroute_tree, &krt, &s));
624
}
625
626
static struct kroute_priority *
627
kroute_find_prio(struct kroute_prefix *kp, uint8_t prio)
628
{
629
	struct kroute_priority	*kprio;
630
631
	/* RTP_ANY here picks the lowest priority node */
632
	if (prio == RTP_ANY)
633
		return (TAILQ_FIRST(&kp->priorities));
634
635
	TAILQ_FOREACH(kprio, &kp->priorities, entry)
636
		if (kprio->priority == prio)
637
			return (kprio);
638
639
	return (NULL);
640
}
641
642
static struct kroute_node *
643
kroute_find_gw(struct kroute_priority *kprio, union ldpd_addr *nh)
644
{
645
	struct kroute_node	*kn;
646
647
	TAILQ_FOREACH(kn, &kprio->nexthops, entry)
648
		if (ldp_addrcmp(kprio->kp->af, &kn->r.nexthop, nh) == 0)
649
			return (kn);
650
651
	return (NULL);
652
}
653
654
static int
655
kroute_insert(struct kroute *kr)
656
{
657
	struct kroute_prefix	*kp;
658
	struct kroute_priority	*kprio, *tmp;
659
	struct kroute_node	*kn;
660
661
	kp = kroute_find_prefix(kr->af, &kr->prefix, kr->prefixlen);
662
	if (kp == NULL) {
663
		kp = calloc(1, sizeof((*kp)));
664
		if (kp == NULL)
665
			fatal(__func__);
666
		kp->af = kr->af;
667
		kp->prefix = kr->prefix;
668
		kp->prefixlen = kr->prefixlen;
669
		TAILQ_INIT(&kp->priorities);
670
		RB_INSERT(kroute_tree, &krt, kp);
671
	}
672
673
	kprio = kroute_find_prio(kp, kr->priority);
674
	if (kprio == NULL) {
675
		kprio = calloc(1, sizeof(*kprio));
676
		if (kprio == NULL)
677
			fatal(__func__);
678
		kprio->kp = kp;
679
		kprio->priority = kr->priority;
680
		TAILQ_INIT(&kprio->nexthops);
681
682
		/* lower priorities first */
683
		TAILQ_FOREACH(tmp, &kp->priorities, entry)
684
			if (tmp->priority > kprio->priority)
685
				break;
686
		if (tmp)
687
			TAILQ_INSERT_BEFORE(tmp, kprio, entry);
688
		else
689
			TAILQ_INSERT_TAIL(&kp->priorities, kprio, entry);
690
	}
691
692
	kn = kroute_find_gw(kprio, &kr->nexthop);
693
	if (kn == NULL) {
694
		kn = calloc(1, sizeof(*kn));
695
		if (kn == NULL)
696
			fatal(__func__);
697
		kn->kprio = kprio;
698
		kn->r = *kr;
699
		TAILQ_INSERT_TAIL(&kprio->nexthops, kn, entry);
700
	}
701
702
	kr_redistribute(kp);
703
	return (0);
704
}
705
706
static int
707
kroute_uninstall(struct kroute_node *kn)
708
{
709
	/* kill MPLS LSP if one was installed */
710
	if (kn->r.flags & F_LDPD_INSERTED)
711
		if (send_rtmsg(kr_state.fd, RTM_DELETE, &kn->r, AF_MPLS) ==
712
		    -1)
713
			return (-1);
714
715
	return (0);
716
}
717
718
static int
719
kroute_remove(struct kroute *kr)
720
{
721
	struct kroute_prefix	*kp;
722
	struct kroute_priority	*kprio;
723
	struct kroute_node	*kn;
724
725
	kp = kroute_find_prefix(kr->af, &kr->prefix, kr->prefixlen);
726
	if (kp == NULL)
727
		goto notfound;
728
	kprio = kroute_find_prio(kp, kr->priority);
729
	if (kprio == NULL)
730
		goto notfound;
731
	kn = kroute_find_gw(kprio, &kr->nexthop);
732
	if (kn == NULL)
733
		goto notfound;
734
735
	kr_redist_remove(&kn->r);
736
	kroute_uninstall(kn);
737
738
	TAILQ_REMOVE(&kprio->nexthops, kn, entry);
739
	free(kn);
740
741
	if (TAILQ_EMPTY(&kprio->nexthops)) {
742
		TAILQ_REMOVE(&kp->priorities, kprio, entry);
743
		free(kprio);
744
	}
745
746
	if (TAILQ_EMPTY(&kp->priorities)) {
747
		if (RB_REMOVE(kroute_tree, &krt, kp) == NULL) {
748
			log_warnx("%s failed for %s/%u", __func__,
749
			    log_addr(kr->af, &kr->prefix), kp->prefixlen);
750
			return (-1);
751
		}
752
		free(kp);
753
	} else
754
		kr_redistribute(kp);
755
756
	return (0);
757
758
 notfound:
759
	log_warnx("%s failed to find %s/%u", __func__,
760
	    log_addr(kr->af, &kr->prefix), kr->prefixlen);
761
	return (-1);
762
}
763
764
static void
765
kroute_clear(void)
766
{
767
	struct kroute_prefix	*kp;
768
	struct kroute_priority	*kprio;
769
	struct kroute_node	*kn;
770
771
	while ((kp = RB_MIN(kroute_tree, &krt)) != NULL) {
772
		while ((kprio = TAILQ_FIRST(&kp->priorities)) != NULL) {
773
			while ((kn = TAILQ_FIRST(&kprio->nexthops)) != NULL) {
774
				kr_redist_remove(&kn->r);
775
				kroute_uninstall(kn);
776
				TAILQ_REMOVE(&kprio->nexthops, kn, entry);
777
				free(kn);
778
			}
779
			TAILQ_REMOVE(&kp->priorities, kprio, entry);
780
			free(kprio);
781
		}
782
		RB_REMOVE(kroute_tree, &krt, kp);
783
		free(kp);
784
	}
785
}
786
787
static __inline int
788
kif_compare(struct kif_node *a, struct kif_node *b)
789
{
790
	return (b->k.ifindex - a->k.ifindex);
791
}
792
793
/* tree management */
794
static struct kif_node *
795
kif_find(unsigned short ifindex)
796
{
797
	struct kif_node	s;
798
799
	memset(&s, 0, sizeof(s));
800
	s.k.ifindex = ifindex;
801
802
	return (RB_FIND(kif_tree, &kit, &s));
803
}
804
805
struct kif *
806
kif_findname(char *ifname)
807
{
808
	struct kif_node	*kif;
809
810
	RB_FOREACH(kif, kif_tree, &kit)
811
		if (!strcmp(ifname, kif->k.ifname))
812
			return (&kif->k);
813
814
	return (NULL);
815
}
816
817
static struct kif_node *
818
kif_insert(unsigned short ifindex)
819
{
820
	struct kif_node	*kif;
821
822
	if ((kif = calloc(1, sizeof(struct kif_node))) == NULL)
823
		return (NULL);
824
825
	kif->k.ifindex = ifindex;
826
	TAILQ_INIT(&kif->addrs);
827
828
	if (RB_INSERT(kif_tree, &kit, kif) != NULL)
829
		fatalx("kif_insert: RB_INSERT");
830
831
	return (kif);
832
}
833
834
static int
835
kif_remove(struct kif_node *kif)
836
{
837
	struct kif_addr	*ka;
838
839
	if (RB_REMOVE(kif_tree, &kit, kif) == NULL) {
840
		log_warnx("RB_REMOVE(kif_tree, &kit, kif)");
841
		return (-1);
842
	}
843
844
	while ((ka = TAILQ_FIRST(&kif->addrs)) != NULL) {
845
		main_imsg_compose_ldpe(IMSG_DELADDR, 0, &ka->a, sizeof(ka->a));
846
		TAILQ_REMOVE(&kif->addrs, ka, entry);
847
		free(ka);
848
	}
849
	free(kif);
850
	return (0);
851
}
852
853
void
854
kif_clear(void)
855
{
856
	struct kif_node	*kif;
857
858
	while ((kif = RB_MIN(kif_tree, &kit)) != NULL)
859
		kif_remove(kif);
860
}
861
862
static struct kif_node *
863
kif_update(unsigned short ifindex, int flags, struct if_data *ifd,
864
    struct sockaddr_dl *sdl, int *link_old)
865
{
866
	struct kif_node		*kif;
867
868
	if ((kif = kif_find(ifindex)) == NULL) {
869
		if ((kif = kif_insert(ifindex)) == NULL)
870
			return (NULL);
871
	} else
872
		*link_old = (kif->k.flags & IFF_UP) &&
873
		    LINK_STATE_IS_UP(kif->k.link_state);
874
875
	kif->k.flags = flags;
876
	kif->k.link_state = ifd->ifi_link_state;
877
	if (sdl)
878
		memcpy(kif->k.mac, LLADDR(sdl), sizeof(kif->k.mac));
879
	kif->k.if_type = ifd->ifi_type;
880
	kif->k.baudrate = ifd->ifi_baudrate;
881
	kif->k.mtu = ifd->ifi_mtu;
882
	kif->k.rdomain = ifd->ifi_rdomain;
883
884
	if (sdl && sdl->sdl_family == AF_LINK) {
885
		if (sdl->sdl_nlen >= sizeof(kif->k.ifname))
886
			memcpy(kif->k.ifname, sdl->sdl_data,
887
			    sizeof(kif->k.ifname) - 1);
888
		else if (sdl->sdl_nlen > 0)
889
			memcpy(kif->k.ifname, sdl->sdl_data,
890
			    sdl->sdl_nlen);
891
		/* string already terminated via calloc() */
892
	}
893
894
	return (kif);
895
}
896
897
static struct kroute_priority *
898
kroute_match(int af, union ldpd_addr *key)
899
{
900
	int			 i, maxprefixlen;
901
	struct kroute_prefix	*kp;
902
	struct kroute_priority	*kprio;
903
	union ldpd_addr		 addr;
904
905
	switch (af) {
906
	case AF_INET:
907
		maxprefixlen = 32;
908
		break;
909
	case AF_INET6:
910
		maxprefixlen = 128;
911
		break;
912
	default:
913
		log_warnx("%s: unknown af", __func__);
914
		return (NULL);
915
	}
916
917
	for (i = maxprefixlen; i >= 0; i--) {
918
		ldp_applymask(af, &addr, key, i);
919
920
		kp = kroute_find_prefix(af, &addr, i);
921
		if (kp == NULL)
922
			continue;
923
924
		kprio = kroute_find_prio(kp, RTP_ANY);
925
		if (kprio != NULL)
926
			return (kprio);
927
	}
928
929
	return (NULL);
930
}
931
932
/* misc */
933
static uint8_t
934
prefixlen_classful(in_addr_t ina)
935
{
936
	/* it hurt to write this. */
937
938
	if (ina >= 0xf0000000U)		/* class E */
939
		return (32);
940
	else if (ina >= 0xe0000000U)	/* class D */
941
		return (4);
942
	else if (ina >= 0xc0000000U)	/* class C */
943
		return (24);
944
	else if (ina >= 0x80000000U)	/* class B */
945
		return (16);
946
	else				/* class A */
947
		return (8);
948
}
949
950
#define ROUNDUP(a) \
951
	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
952
953
static void
954
get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
955
{
956
	int	i;
957
958
	for (i = 0; i < RTAX_MAX; i++) {
959
		if (addrs & (1 << i)) {
960
			rti_info[i] = sa;
961
			sa = (struct sockaddr *)((char *)(sa) +
962
			    ROUNDUP(sa->sa_len));
963
		} else
964
			rti_info[i] = NULL;
965
	}
966
}
967
968
static void
969
if_change(unsigned short ifindex, int flags, struct if_data *ifd,
970
    struct sockaddr_dl *sdl)
971
{
972
	struct kif_node		*kif;
973
	struct kif_addr		*ka;
974
	int			 link_old = 0, link_new;
975
976
	kif = kif_update(ifindex, flags, ifd, sdl, &link_old);
977
	if (!kif) {
978
		log_warn("%s: kif_update(%u)", __func__, ifindex);
979
		return;
980
	}
981
	link_new = (kif->k.flags & IFF_UP) &&
982
	    LINK_STATE_IS_UP(kif->k.link_state);
983
984
	if (link_new == link_old)
985
		return;
986
987
	main_imsg_compose_ldpe(IMSG_IFSTATUS, 0, &kif->k, sizeof(struct kif));
988
	if (link_new) {
989
		TAILQ_FOREACH(ka, &kif->addrs, entry)
990
			main_imsg_compose_ldpe(IMSG_NEWADDR, 0, &ka->a,
991
			    sizeof(ka->a));
992
	} else {
993
		TAILQ_FOREACH(ka, &kif->addrs, entry)
994
			main_imsg_compose_ldpe(IMSG_DELADDR, 0, &ka->a,
995
			    sizeof(ka->a));
996
	}
997
}
998
999
static void
1000
if_newaddr(unsigned short ifindex, struct sockaddr *ifa, struct sockaddr *mask,
1001
    struct sockaddr *brd)
1002
{
1003
	struct kif_node		*kif;
1004
	struct sockaddr_in	*ifa4, *mask4, *brd4;
1005
	struct sockaddr_in6	*ifa6, *mask6, *brd6;
1006
	struct kif_addr		*ka;
1007
1008
	if (ifa == NULL)
1009
		return;
1010
	if ((kif = kif_find(ifindex)) == NULL) {
1011
		log_warnx("%s: corresponding if %d not found", __func__,
1012
		    ifindex);
1013
		return;
1014
	}
1015
1016
	switch (ifa->sa_family) {
1017
	case AF_INET:
1018
		ifa4 = (struct sockaddr_in *) ifa;
1019
		mask4 = (struct sockaddr_in *) mask;
1020
		brd4 = (struct sockaddr_in *) brd;
1021
1022
		/* filter out unwanted addresses */
1023
		if (bad_addr_v4(ifa4->sin_addr))
1024
			return;
1025
1026
		if ((ka = calloc(1, sizeof(struct kif_addr))) == NULL)
1027
			fatal("if_newaddr");
1028
		ka->a.addr.v4 = ifa4->sin_addr;
1029
		if (mask4)
1030
			ka->a.prefixlen =
1031
			    mask2prefixlen(mask4->sin_addr.s_addr);
1032
		if (brd4)
1033
			ka->a.dstbrd.v4 = brd4->sin_addr;
1034
		break;
1035
	case AF_INET6:
1036
		ifa6 = (struct sockaddr_in6 *) ifa;
1037
		mask6 = (struct sockaddr_in6 *) mask;
1038
		brd6 = (struct sockaddr_in6 *) brd;
1039
1040
		/* We only care about link-local and global-scope. */
1041
		if (bad_addr_v6(&ifa6->sin6_addr))
1042
			return;
1043
1044
		clearscope(&ifa6->sin6_addr);
1045
1046
		if ((ka = calloc(1, sizeof(struct kif_addr))) == NULL)
1047
			fatal("if_newaddr");
1048
		ka->a.addr.v6 = ifa6->sin6_addr;
1049
		if (mask6)
1050
			ka->a.prefixlen = mask2prefixlen6(mask6);
1051
		if (brd6)
1052
			ka->a.dstbrd.v6 = brd6->sin6_addr;
1053
		break;
1054
	default:
1055
		return;
1056
	}
1057
1058
	ka->a.ifindex = ifindex;
1059
	ka->a.af = ifa->sa_family;
1060
	TAILQ_INSERT_TAIL(&kif->addrs, ka, entry);
1061
1062
	/* notify ldpe about new address */
1063
	main_imsg_compose_ldpe(IMSG_NEWADDR, 0, &ka->a, sizeof(ka->a));
1064
}
1065
1066
static void
1067
if_deladdr(unsigned short ifindex, struct sockaddr *ifa, struct sockaddr *mask,
1068
    struct sockaddr *brd)
1069
{
1070
	struct kif_node		*kif;
1071
	struct sockaddr_in	*ifa4, *mask4, *brd4;
1072
	struct sockaddr_in6	*ifa6, *mask6, *brd6;
1073
	struct kaddr		 k;
1074
	struct kif_addr		*ka, *nka;
1075
1076
	if (ifa == NULL)
1077
		return;
1078
	if ((kif = kif_find(ifindex)) == NULL) {
1079
		log_warnx("%s: corresponding if %d not found", __func__,
1080
		    ifindex);
1081
		return;
1082
	}
1083
1084
	memset(&k, 0, sizeof(k));
1085
	k.af = ifa->sa_family;
1086
	switch (ifa->sa_family) {
1087
	case AF_INET:
1088
		ifa4 = (struct sockaddr_in *) ifa;
1089
		mask4 = (struct sockaddr_in *) mask;
1090
		brd4 = (struct sockaddr_in *) brd;
1091
1092
		/* filter out unwanted addresses */
1093
		if (bad_addr_v4(ifa4->sin_addr))
1094
			return;
1095
1096
		k.addr.v4 = ifa4->sin_addr;
1097
		if (mask4)
1098
			k.prefixlen = mask2prefixlen(mask4->sin_addr.s_addr);
1099
		if (brd4)
1100
			k.dstbrd.v4 = brd4->sin_addr;
1101
		break;
1102
	case AF_INET6:
1103
		ifa6 = (struct sockaddr_in6 *) ifa;
1104
		mask6 = (struct sockaddr_in6 *) mask;
1105
		brd6 = (struct sockaddr_in6 *) brd;
1106
1107
		/* We only care about link-local and global-scope. */
1108
		if (bad_addr_v6(&ifa6->sin6_addr))
1109
			return;
1110
1111
		clearscope(&ifa6->sin6_addr);
1112
1113
		k.addr.v6 = ifa6->sin6_addr;
1114
		if (mask6)
1115
			k.prefixlen = mask2prefixlen6(mask6);
1116
		if (brd6)
1117
			k.dstbrd.v6 = brd6->sin6_addr;
1118
		break;
1119
	default:
1120
		return;
1121
	}
1122
1123
	for (ka = TAILQ_FIRST(&kif->addrs); ka != NULL; ka = nka) {
1124
		nka = TAILQ_NEXT(ka, entry);
1125
1126
		if (ka->a.af != k.af ||
1127
		    ka->a.prefixlen != k.prefixlen ||
1128
		    ldp_addrcmp(ka->a.af, &ka->a.addr, &k.addr))
1129
			continue;
1130
1131
		/* notify ldpe about removed address */
1132
		main_imsg_compose_ldpe(IMSG_DELADDR, 0, &ka->a, sizeof(ka->a));
1133
		TAILQ_REMOVE(&kif->addrs, ka, entry);
1134
		free(ka);
1135
		return;
1136
	}
1137
}
1138
1139
static void
1140
if_announce(void *msg)
1141
{
1142
	struct if_announcemsghdr	*ifan;
1143
	struct kif_node			*kif;
1144
1145
	ifan = msg;
1146
1147
	switch (ifan->ifan_what) {
1148
	case IFAN_ARRIVAL:
1149
		kif = kif_insert(ifan->ifan_index);
1150
		if (kif)
1151
			strlcpy(kif->k.ifname, ifan->ifan_name,
1152
			    sizeof(kif->k.ifname));
1153
		break;
1154
	case IFAN_DEPARTURE:
1155
		kif = kif_find(ifan->ifan_index);
1156
		if (kif)
1157
			kif_remove(kif);
1158
		break;
1159
	}
1160
}
1161
1162
/* rtsock */
1163
static int
1164
send_rtmsg(int fd, int action, struct kroute *kr, int family)
1165
{
1166
	switch (kr->af) {
1167
	case AF_INET:
1168
		return (send_rtmsg_v4(fd, action, kr, family));
1169
	case AF_INET6:
1170
		return (send_rtmsg_v6(fd, action, kr, family));
1171
	default:
1172
		fatalx("send_rtmsg: unknown af");
1173
	}
1174
}
1175
1176
static int
1177
send_rtmsg_v4(int fd, int action, struct kroute *kr, int family)
1178
{
1179
	struct iovec		iov[5];
1180
	struct rt_msghdr	hdr;
1181
	struct sockaddr_mpls	label_in, label_out;
1182
	struct sockaddr_in	dst, mask, nexthop;
1183
	int			iovcnt = 0;
1184
1185
	if (kr_state.fib_sync == 0)
1186
		return (0);
1187
1188
	/*
1189
	 * Reserved labels (implicit and explicit NULL) should not be added
1190
	 * to the FIB.
1191
	 */
1192
	if (family == AF_MPLS && kr->local_label < MPLS_LABEL_RESERVED_MAX)
1193
		return (0);
1194
1195
	/* initialize header */
1196
	memset(&hdr, 0, sizeof(hdr));
1197
	hdr.rtm_version = RTM_VERSION;
1198
1199
	hdr.rtm_type = action;
1200
	hdr.rtm_flags = RTF_UP;
1201
	hdr.rtm_fmask = RTF_MPLS;
1202
	hdr.rtm_seq = kr_state.rtseq++;	/* overflow doesn't matter */
1203
	hdr.rtm_msglen = sizeof(hdr);
1204
	hdr.rtm_hdrlen = sizeof(struct rt_msghdr);
1205
	hdr.rtm_priority = kr->priority;
1206
	hdr.rtm_tableid = kr_state.rdomain;	/* rtableid */
1207
	/* adjust iovec */
1208
	iov[iovcnt].iov_base = &hdr;
1209
	iov[iovcnt++].iov_len = sizeof(hdr);
1210
1211
	if (family == AF_MPLS) {
1212
		memset(&label_in, 0, sizeof(label_in));
1213
		label_in.smpls_len = sizeof(label_in);
1214
		label_in.smpls_family = AF_MPLS;
1215
		label_in.smpls_label =
1216
		    htonl(kr->local_label << MPLS_LABEL_OFFSET);
1217
		/* adjust header */
1218
		hdr.rtm_flags |= RTF_MPLS | RTF_MPATH;
1219
		hdr.rtm_addrs |= RTA_DST;
1220
		hdr.rtm_msglen += sizeof(label_in);
1221
		/* adjust iovec */
1222
		iov[iovcnt].iov_base = &label_in;
1223
		iov[iovcnt++].iov_len = sizeof(label_in);
1224
	} else {
1225
		memset(&dst, 0, sizeof(dst));
1226
		dst.sin_len = sizeof(dst);
1227
		dst.sin_family = AF_INET;
1228
		dst.sin_addr = kr->prefix.v4;
1229
		/* adjust header */
1230
		hdr.rtm_addrs |= RTA_DST;
1231
		hdr.rtm_msglen += sizeof(dst);
1232
		/* adjust iovec */
1233
		iov[iovcnt].iov_base = &dst;
1234
		iov[iovcnt++].iov_len = sizeof(dst);
1235
	}
1236
1237
	memset(&nexthop, 0, sizeof(nexthop));
1238
	nexthop.sin_len = sizeof(nexthop);
1239
	nexthop.sin_family = AF_INET;
1240
	nexthop.sin_addr = kr->nexthop.v4;
1241
	/* adjust header */
1242
	hdr.rtm_flags |= RTF_GATEWAY;
1243
	hdr.rtm_addrs |= RTA_GATEWAY;
1244
	hdr.rtm_msglen += sizeof(nexthop);
1245
	/* adjust iovec */
1246
	iov[iovcnt].iov_base = &nexthop;
1247
	iov[iovcnt++].iov_len = sizeof(nexthop);
1248
1249
	if (family == AF_INET) {
1250
		memset(&mask, 0, sizeof(mask));
1251
		mask.sin_len = sizeof(mask);
1252
		mask.sin_family = AF_INET;
1253
		mask.sin_addr.s_addr = prefixlen2mask(kr->prefixlen);
1254
		/* adjust header */
1255
		hdr.rtm_addrs |= RTA_NETMASK;
1256
		hdr.rtm_msglen += sizeof(mask);
1257
		/* adjust iovec */
1258
		iov[iovcnt].iov_base = &mask;
1259
		iov[iovcnt++].iov_len = sizeof(mask);
1260
	}
1261
1262
	/* If action is RTM_DELETE we have to get rid of MPLS infos */
1263
	if (kr->remote_label != NO_LABEL && action != RTM_DELETE) {
1264
		memset(&label_out, 0, sizeof(label_out));
1265
		label_out.smpls_len = sizeof(label_out);
1266
		label_out.smpls_family = AF_MPLS;
1267
		label_out.smpls_label =
1268
		    htonl(kr->remote_label << MPLS_LABEL_OFFSET);
1269
		/* adjust header */
1270
		hdr.rtm_addrs |= RTA_SRC;
1271
		hdr.rtm_flags |= RTF_MPLS;
1272
		hdr.rtm_msglen += sizeof(label_out);
1273
		/* adjust iovec */
1274
		iov[iovcnt].iov_base = &label_out;
1275
		iov[iovcnt++].iov_len = sizeof(label_out);
1276
1277
		if (kr->remote_label == MPLS_LABEL_IMPLNULL) {
1278
			if (family == AF_MPLS)
1279
				hdr.rtm_mpls = MPLS_OP_POP;
1280
			else
1281
				return (0);
1282
		} else {
1283
			if (family == AF_MPLS)
1284
				hdr.rtm_mpls = MPLS_OP_SWAP;
1285
			else
1286
				hdr.rtm_mpls = MPLS_OP_PUSH;
1287
		}
1288
	}
1289
1290
 retry:
1291
	if (writev(fd, iov, iovcnt) == -1) {
1292
		if (errno == ESRCH) {
1293
			if (hdr.rtm_type == RTM_CHANGE && family == AF_MPLS) {
1294
				hdr.rtm_type = RTM_ADD;
1295
				goto retry;
1296
			} else if (hdr.rtm_type == RTM_DELETE) {
1297
				log_info("route %s/%u vanished before delete",
1298
				    inet_ntoa(kr->prefix.v4), kr->prefixlen);
1299
				return (-1);
1300
			}
1301
		}
1302
		log_warn("%s action %u, af %s, prefix %s/%u", __func__,
1303
		    hdr.rtm_type, af_name(family), inet_ntoa(kr->prefix.v4),
1304
		    kr->prefixlen);
1305
		return (-1);
1306
	}
1307
1308
	return (0);
1309
}
1310
1311
static int
1312
send_rtmsg_v6(int fd, int action, struct kroute *kr, int family)
1313
{
1314
	return (0);
1315
}
1316
1317
static int
1318
fetchtable(void)
1319
{
1320
	size_t			 len;
1321
	int			 mib[7];
1322
	char			*buf;
1323
	int			 rv;
1324
1325
	mib[0] = CTL_NET;
1326
	mib[1] = PF_ROUTE;
1327
	mib[2] = 0;
1328
	mib[3] = 0;
1329
	mib[4] = NET_RT_DUMP;
1330
	mib[5] = 0;
1331
	mib[6] = kr_state.rdomain;	/* rtableid */
1332
1333
	if (sysctl(mib, 7, NULL, &len, NULL, 0) == -1) {
1334
		log_warn("sysctl");
1335
		return (-1);
1336
	}
1337
	if ((buf = malloc(len)) == NULL) {
1338
		log_warn(__func__);
1339
		return (-1);
1340
	}
1341
	if (sysctl(mib, 7, buf, &len, NULL, 0) == -1) {
1342
		log_warn("sysctl");
1343
		free(buf);
1344
		return (-1);
1345
	}
1346
1347
	rv = rtmsg_process(buf, len);
1348
	free(buf);
1349
1350
	return (rv);
1351
}
1352
1353
static int
1354
fetchifs(void)
1355
{
1356
	size_t			 len;
1357
	int			 mib[6];
1358
	char			*buf;
1359
	int			 rv;
1360
1361
	mib[0] = CTL_NET;
1362
	mib[1] = PF_ROUTE;
1363
	mib[2] = 0;
1364
	mib[3] = 0;	/* wildcard */
1365
	mib[4] = NET_RT_IFLIST;
1366
	mib[5] = 0;
1367
1368
	if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) {
1369
		log_warn("sysctl");
1370
		return (-1);
1371
	}
1372
	if ((buf = malloc(len)) == NULL) {
1373
		log_warn(__func__);
1374
		return (-1);
1375
	}
1376
	if (sysctl(mib, 6, buf, &len, NULL, 0) == -1) {
1377
		log_warn("sysctl");
1378
		free(buf);
1379
		return (-1);
1380
	}
1381
1382
	rv = rtmsg_process(buf, len);
1383
	free(buf);
1384
1385
	return (rv);
1386
}
1387
1388
static int
1389
dispatch_rtmsg(void)
1390
{
1391
	char			 buf[RT_BUF_SIZE];
1392
	ssize_t			 n;
1393
1394
	if ((n = read(kr_state.fd, &buf, sizeof(buf))) == -1) {
1395
		if (errno == EAGAIN || errno == EINTR)
1396
			return (0);
1397
		log_warn("%s: read error", __func__);
1398
		return (-1);
1399
	}
1400
1401
	if (n == 0) {
1402
		log_warnx("routing socket closed");
1403
		return (-1);
1404
	}
1405
1406
	return (rtmsg_process(buf, n));
1407
}
1408
1409
static int
1410
rtmsg_process(char *buf, size_t len)
1411
{
1412
	struct rt_msghdr	*rtm;
1413
	struct if_msghdr	 ifm;
1414
	struct ifa_msghdr	*ifam;
1415
	struct sockaddr		*sa, *rti_info[RTAX_MAX];
1416
	size_t			 offset;
1417
	char			*next;
1418
1419
	for (offset = 0; offset < len; offset += rtm->rtm_msglen) {
1420
		next = buf + offset;
1421
		rtm = (struct rt_msghdr *)next;
1422
		if (len < offset + sizeof(unsigned short) ||
1423
		    len < offset + rtm->rtm_msglen)
1424
			fatalx("rtmsg_process: partial rtm in buffer");
1425
		if (rtm->rtm_version != RTM_VERSION)
1426
			continue;
1427
1428
		sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
1429
		get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
1430
1431
		switch (rtm->rtm_type) {
1432
		case RTM_ADD:
1433
		case RTM_GET:
1434
		case RTM_CHANGE:
1435
		case RTM_DELETE:
1436
			if (rtm->rtm_errno)		/* failed attempts... */
1437
				continue;
1438
1439
			if (rtm->rtm_tableid != kr_state.rdomain)
1440
				continue;
1441
1442
			if (rtm->rtm_type == RTM_GET &&
1443
			    rtm->rtm_pid != kr_state.pid)
1444
				continue;
1445
1446
			/* Skip ARP/ND cache and broadcast routes. */
1447
			if (rtm->rtm_flags & (RTF_LLINFO|RTF_BROADCAST))
1448
				continue;
1449
1450
			/* LDP should follow the IGP and ignore BGP routes */
1451
			if (rtm->rtm_priority == RTP_BGP)
1452
				continue;
1453
1454
			if (rtmsg_process_route(rtm, rti_info) == -1)
1455
				return (-1);
1456
		}
1457
1458
		switch (rtm->rtm_type) {
1459
		case RTM_IFINFO:
1460
			memcpy(&ifm, next, sizeof(ifm));
1461
			if_change(ifm.ifm_index, ifm.ifm_flags, &ifm.ifm_data,
1462
			    (struct sockaddr_dl *)rti_info[RTAX_IFP]);
1463
			break;
1464
		case RTM_NEWADDR:
1465
			ifam = (struct ifa_msghdr *)rtm;
1466
			if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA |
1467
			    RTA_BRD)) == 0)
1468
				break;
1469
1470
			if_newaddr(ifam->ifam_index,
1471
			    (struct sockaddr *)rti_info[RTAX_IFA],
1472
			    (struct sockaddr *)rti_info[RTAX_NETMASK],
1473
			    (struct sockaddr *)rti_info[RTAX_BRD]);
1474
			break;
1475
		case RTM_DELADDR:
1476
			ifam = (struct ifa_msghdr *)rtm;
1477
			if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA |
1478
			    RTA_BRD)) == 0)
1479
				break;
1480
1481
			if_deladdr(ifam->ifam_index,
1482
			    (struct sockaddr *)rti_info[RTAX_IFA],
1483
			    (struct sockaddr *)rti_info[RTAX_NETMASK],
1484
			    (struct sockaddr *)rti_info[RTAX_BRD]);
1485
			break;
1486
		case RTM_IFANNOUNCE:
1487
			if_announce(next);
1488
			break;
1489
		default:
1490
			/* ignore for now */
1491
			break;
1492
		}
1493
	}
1494
1495
	return (offset);
1496
}
1497
1498
static int
1499
rtmsg_process_route(struct rt_msghdr *rtm, struct sockaddr *rti_info[RTAX_MAX])
1500
{
1501
	struct sockaddr		*sa;
1502
	struct sockaddr_in	*sa_in;
1503
	struct sockaddr_in6	*sa_in6;
1504
	struct kroute		 kr;
1505
	struct kroute_prefix	*kp;
1506
	struct kroute_priority	*kprio;
1507
	struct kroute_node	*kn;
1508
1509
	if ((sa = rti_info[RTAX_DST]) == NULL)
1510
		return (-1);
1511
1512
	memset(&kr, 0, sizeof(kr));
1513
	kr.af = sa->sa_family;
1514
	switch (kr.af) {
1515
	case AF_INET:
1516
		kr.prefix.v4 = ((struct sockaddr_in *)sa)->sin_addr;
1517
		sa_in = (struct sockaddr_in *) rti_info[RTAX_NETMASK];
1518
		if (sa_in != NULL && sa_in->sin_len != 0)
1519
			kr.prefixlen = mask2prefixlen(sa_in->sin_addr.s_addr);
1520
		else if (rtm->rtm_flags & RTF_HOST)
1521
			kr.prefixlen = 32;
1522
		else if (kr.prefix.v4.s_addr == INADDR_ANY)
1523
			kr.prefixlen = 0;
1524
		else
1525
			kr.prefixlen = prefixlen_classful(kr.prefix.v4.s_addr);
1526
		break;
1527
	case AF_INET6:
1528
		kr.prefix.v6 = ((struct sockaddr_in6 *)sa)->sin6_addr;
1529
		sa_in6 = (struct sockaddr_in6 *)rti_info[RTAX_NETMASK];
1530
		if (sa_in6 != NULL && sa_in6->sin6_len != 0)
1531
			kr.prefixlen = mask2prefixlen6(sa_in6);
1532
		else if (rtm->rtm_flags & RTF_HOST)
1533
			kr.prefixlen = 128;
1534
		else if (IN6_IS_ADDR_UNSPECIFIED(&kr.prefix.v6))
1535
			kr.prefixlen = 0;
1536
		else
1537
			fatalx("in6 net addr without netmask");
1538
		break;
1539
	default:
1540
		return (0);
1541
	}
1542
	kr.ifindex = rtm->rtm_index;
1543
	if ((sa = rti_info[RTAX_GATEWAY]) != NULL) {
1544
		switch (sa->sa_family) {
1545
		case AF_INET:
1546
			kr.nexthop.v4 = ((struct sockaddr_in *)sa)->sin_addr;
1547
			break;
1548
		case AF_INET6:
1549
			sa_in6 = (struct sockaddr_in6 *)sa;
1550
			recoverscope(sa_in6);
1551
			kr.nexthop.v6 = sa_in6->sin6_addr;
1552
			if (sa_in6->sin6_scope_id)
1553
				kr.ifindex = sa_in6->sin6_scope_id;
1554
			break;
1555
		case AF_LINK:
1556
			kr.flags |= F_CONNECTED;
1557
			break;
1558
		}
1559
	}
1560
1561
	if (rtm->rtm_flags & RTF_STATIC)
1562
		kr.flags |= F_STATIC;
1563
	if (rtm->rtm_flags & RTF_BLACKHOLE)
1564
		kr.flags |= F_BLACKHOLE;
1565
	if (rtm->rtm_flags & RTF_REJECT)
1566
		kr.flags |= F_REJECT;
1567
	if (rtm->rtm_flags & RTF_DYNAMIC)
1568
		kr.flags |= F_DYNAMIC;
1569
	/* routes attached to connected or loopback interfaces */
1570
	if (rtm->rtm_flags & RTF_CONNECTED ||
1571
	    ldp_addrcmp(kr.af, &kr.prefix, &kr.nexthop) == 0)
1572
		kr.flags |= F_CONNECTED;
1573
	kr.priority = rtm->rtm_priority;
1574
1575
	if (rtm->rtm_type == RTM_CHANGE) {
1576
		/*
1577
		 * The kernel doesn't allow RTM_CHANGE for multipath routes.
1578
		 * If we got this message we know that the route has only one
1579
		 * nexthop and we should remove it before installing the same
1580
		 * route with the new nexthop.
1581
		 */
1582
		kp = kroute_find_prefix(kr.af, &kr.prefix, kr.prefixlen);
1583
		if (kp) {
1584
			kprio = kroute_find_prio(kp, kr.priority);
1585
			if (kprio) {
1586
				kn = TAILQ_FIRST(&kprio->nexthops);
1587
				if (kn)
1588
					kroute_remove(&kn->r);
1589
			}
1590
		}
1591
	}
1592
1593
	kn = NULL;
1594
	kp = kroute_find_prefix(kr.af, &kr.prefix, kr.prefixlen);
1595
	if (kp) {
1596
		kprio = kroute_find_prio(kp, kr.priority);
1597
		if (kprio)
1598
			kn = kroute_find_gw(kprio, &kr.nexthop);
1599
	}
1600
1601
	if (rtm->rtm_type == RTM_DELETE) {
1602
		if (kn == NULL)
1603
			return (0);
1604
		return (kroute_remove(&kr));
1605
	}
1606
1607
	if (!ldp_addrisset(kr.af, &kr.nexthop) && !(kr.flags & F_CONNECTED)) {
1608
		log_warnx("%s: no nexthop for %s/%u", __func__,
1609
		    log_addr(kr.af, &kr.prefix), kr.prefixlen);
1610
		return (-1);
1611
	}
1612
1613
	if (kn != NULL) {
1614
		/* update route */
1615
		kn->r = kr;
1616
		kr_redistribute(kp);
1617
	} else {
1618
		kr.local_label = NO_LABEL;
1619
		kr.remote_label = NO_LABEL;
1620
		kroute_insert(&kr);
1621
	}
1622
1623
	return (0);
1624
}
1625
1626
int
1627
kmpw_set(struct kpw *kpw)
1628
{
1629
	struct kif_node		*kif;
1630
1631
	kif = kif_find(kpw->ifindex);
1632
	if (kif == NULL) {
1633
		log_warnx("%s: failed to find mpw by index (%u)", __func__,
1634
		    kpw->ifindex);
1635
		return (-1);
1636
	}
1637
1638
	if (kif->kpw == NULL)
1639
		kif->kpw = malloc(sizeof(*kif->kpw));
1640
	*kif->kpw = *kpw;
1641
1642
	return (kmpw_install(kif->k.ifname, kpw));
1643
}
1644
1645
int
1646
kmpw_unset(struct kpw *kpw)
1647
{
1648
	struct kif_node		*kif;
1649
1650
	kif = kif_find(kpw->ifindex);
1651
	if (kif == NULL) {
1652
		log_warnx("%s: failed to find mpw by index (%u)", __func__,
1653
		    kpw->ifindex);
1654
		return (-1);
1655
	}
1656
1657
	if (kif->kpw == NULL) {
1658
		log_warnx("%s: %s is not set", __func__, kif->k.ifname);
1659
		return (-1);
1660
	}
1661
1662
	free(kif->kpw);
1663
	kif->kpw = NULL;
1664
	return (kmpw_uninstall(kif->k.ifname));
1665
}
1666
1667
static int
1668
kmpw_install(const char *ifname, struct kpw *kpw)
1669
{
1670
	struct ifreq		 ifr;
1671
	struct ifmpwreq		 imr;
1672
1673
	memset(&imr, 0, sizeof(imr));
1674
	switch (kpw->pw_type) {
1675
	case PW_TYPE_ETHERNET:
1676
		imr.imr_type = IMR_TYPE_ETHERNET;
1677
		break;
1678
	case PW_TYPE_ETHERNET_TAGGED:
1679
		imr.imr_type = IMR_TYPE_ETHERNET_TAGGED;
1680
		break;
1681
	default:
1682
		log_warnx("%s: unhandled pseudowire type (%#X)", __func__,
1683
		    kpw->pw_type);
1684
		return (-1);
1685
	}
1686
1687
	if (kpw->flags & F_PW_CWORD)
1688
		imr.imr_flags |= IMR_FLAG_CONTROLWORD;
1689
1690
	memcpy(&imr.imr_nexthop, addr2sa(kpw->af, &kpw->nexthop, 0),
1691
	    sizeof(imr.imr_nexthop));
1692
1693
	imr.imr_lshim.shim_label = kpw->local_label;
1694
	imr.imr_rshim.shim_label = kpw->remote_label;
1695
1696
	memset(&ifr, 0, sizeof(ifr));
1697
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1698
	ifr.ifr_data = (caddr_t) &imr;
1699
	if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr)) {
1700
		log_warn("ioctl SIOCSETMPWCFG");
1701
		return (-1);
1702
	}
1703
1704
	return (0);
1705
}
1706
1707
static int
1708
kmpw_uninstall(const char *ifname)
1709
{
1710
	struct ifreq		 ifr;
1711
	struct ifmpwreq		 imr;
1712
1713
	memset(&ifr, 0, sizeof(ifr));
1714
	memset(&imr, 0, sizeof(imr));
1715
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1716
	ifr.ifr_data = (caddr_t) &imr;
1717
	if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr)) {
1718
		log_warn("ioctl SIOCSETMPWCFG");
1719
		return (-1);
1720
	}
1721
1722
	return (0);
1723
}