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

Line Branch Exec Source
1
/*	$OpenBSD: adjacency.c,v 1.26 2016/06/18 17:31:32 renato Exp $ */
2
3
/*
4
 * Copyright (c) 2013, 2015 Renato Westphal <renato@openbsd.org>
5
 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
6
 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
7
 * Copyright (c) 2004, 2005, 2008 Esben Norby <norby@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 <arpa/inet.h>
24
#include <stdlib.h>
25
#include <string.h>
26
27
#include "ldpd.h"
28
#include "ldpe.h"
29
#include "log.h"
30
31
static void	 adj_del_single(struct adj *);
32
static void	 adj_itimer(int, short, void *);
33
static void	 tnbr_del(struct tnbr *);
34
static void	 tnbr_hello_timer(int, short, void *);
35
static void	 tnbr_start_hello_timer(struct tnbr *);
36
static void	 tnbr_stop_hello_timer(struct tnbr *);
37
38
struct adj *
39
adj_new(struct in_addr lsr_id, struct hello_source *source,
40
    union ldpd_addr *addr)
41
{
42
	struct adj	*adj;
43
44
	log_debug("%s: lsr-id %s, %s", __func__, inet_ntoa(lsr_id),
45
	    log_hello_src(source));
46
47
	if ((adj = calloc(1, sizeof(*adj))) == NULL)
48
		fatal(__func__);
49
50
	adj->lsr_id = lsr_id;
51
	adj->nbr = NULL;
52
	adj->source = *source;
53
	adj->trans_addr = *addr;
54
55
	evtimer_set(&adj->inactivity_timer, adj_itimer, adj);
56
57
	LIST_INSERT_HEAD(&global.adj_list, adj, global_entry);
58
59
	switch (source->type) {
60
	case HELLO_LINK:
61
		LIST_INSERT_HEAD(&source->link.ia->adj_list, adj, ia_entry);
62
		break;
63
	case HELLO_TARGETED:
64
		source->target->adj = adj;
65
		break;
66
	}
67
68
	return (adj);
69
}
70
71
static void
72
adj_del_single(struct adj *adj)
73
{
74
	log_debug("%s: lsr-id %s, %s (%s)", __func__, inet_ntoa(adj->lsr_id),
75
	    log_hello_src(&adj->source), af_name(adj_get_af(adj)));
76
77
	adj_stop_itimer(adj);
78
79
	LIST_REMOVE(adj, global_entry);
80
	if (adj->nbr)
81
		LIST_REMOVE(adj, nbr_entry);
82
	switch (adj->source.type) {
83
	case HELLO_LINK:
84
		LIST_REMOVE(adj, ia_entry);
85
		break;
86
	case HELLO_TARGETED:
87
		adj->source.target->adj = NULL;
88
		break;
89
	}
90
91
	free(adj);
92
}
93
94
void
95
adj_del(struct adj *adj, uint32_t notif_status)
96
{
97
	struct nbr	*nbr = adj->nbr;
98
	struct adj	*atmp;
99
100
	adj_del_single(adj);
101
102
	/*
103
	 * If the neighbor still exists but none of its remaining
104
	 * adjacencies (if any) are from the preferred address-family,
105
	 * then delete it.
106
	 */
107
	if (nbr && nbr_adj_count(nbr, nbr->af) == 0) {
108
		LIST_FOREACH_SAFE(adj, &nbr->adj_list, nbr_entry, atmp)
109
			adj_del_single(adj);
110
		session_shutdown(nbr, notif_status, 0, 0);
111
		nbr_del(nbr);
112
	}
113
}
114
115
struct adj *
116
adj_find(struct hello_source *source)
117
{
118
	struct adj *adj;
119
120
	LIST_FOREACH(adj, &global.adj_list, global_entry) {
121
		if (adj->source.type != source->type)
122
			continue;
123
124
		switch (source->type) {
125
		case HELLO_LINK:
126
			if (ldp_addrcmp(source->link.ia->af,
127
			    &adj->source.link.src_addr,
128
			    &source->link.src_addr) == 0)
129
				return (adj);
130
			break;
131
		case HELLO_TARGETED:
132
			if (adj->source.target == source->target)
133
				return (adj);
134
			break;
135
		}
136
	}
137
138
	return (NULL);
139
}
140
141
int
142
adj_get_af(struct adj *adj)
143
{
144
	switch (adj->source.type) {
145
	case HELLO_LINK:
146
		return (adj->source.link.ia->af);
147
	case HELLO_TARGETED:
148
		return (adj->source.target->af);
149
	default:
150
		fatalx("adj_get_af: unknown hello type");
151
	}
152
}
153
154
/* adjacency timers */
155
156
/* ARGSUSED */
157
static void
158
adj_itimer(int fd, short event, void *arg)
159
{
160
	struct adj *adj = arg;
161
162
	log_debug("%s: lsr-id %s", __func__, inet_ntoa(adj->lsr_id));
163
164
	if (adj->source.type == HELLO_TARGETED) {
165
		if (!(adj->source.target->flags & F_TNBR_CONFIGURED) &&
166
		    adj->source.target->pw_count == 0) {
167
			/* remove dynamic targeted neighbor */
168
			tnbr_del(adj->source.target);
169
			return;
170
		}
171
		adj->source.target->adj = NULL;
172
	}
173
174
	adj_del(adj, S_HOLDTIME_EXP);
175
}
176
177
void
178
adj_start_itimer(struct adj *adj)
179
{
180
	struct timeval	tv;
181
182
	timerclear(&tv);
183
	tv.tv_sec = adj->holdtime;
184
	if (evtimer_add(&adj->inactivity_timer, &tv) == -1)
185
		fatal(__func__);
186
}
187
188
void
189
adj_stop_itimer(struct adj *adj)
190
{
191
	if (evtimer_pending(&adj->inactivity_timer, NULL) &&
192
	    evtimer_del(&adj->inactivity_timer) == -1)
193
		fatal(__func__);
194
}
195
196
/* targeted neighbors */
197
198
struct tnbr *
199
tnbr_new(struct ldpd_conf *xconf, int af, union ldpd_addr *addr)
200
{
201
	struct tnbr		*tnbr;
202
203
	if ((tnbr = calloc(1, sizeof(*tnbr))) == NULL)
204
		fatal(__func__);
205
206
	tnbr->af = af;
207
	tnbr->addr = *addr;
208
	tnbr->state = TNBR_STA_DOWN;
209
	tnbr->hello_holdtime = (ldp_af_conf_get(xconf, af))->thello_holdtime;
210
	tnbr->hello_interval = (ldp_af_conf_get(xconf, af))->thello_interval;
211
212
	return (tnbr);
213
}
214
215
static void
216
tnbr_del(struct tnbr *tnbr)
217
{
218
	tnbr_stop_hello_timer(tnbr);
219
	if (tnbr->adj)
220
		adj_del(tnbr->adj, S_SHUTDOWN);
221
	LIST_REMOVE(tnbr, entry);
222
	free(tnbr);
223
}
224
225
struct tnbr *
226
tnbr_find(struct ldpd_conf *xconf, int af, union ldpd_addr *addr)
227
{
228
	struct tnbr *tnbr;
229
230
	LIST_FOREACH(tnbr, &xconf->tnbr_list, entry)
231
		if (af == tnbr->af &&
232
		    ldp_addrcmp(af, addr, &tnbr->addr) == 0)
233
			return (tnbr);
234
235
	return (NULL);
236
}
237
238
struct tnbr *
239
tnbr_check(struct tnbr *tnbr)
240
{
241
	if (!(tnbr->flags & (F_TNBR_CONFIGURED|F_TNBR_DYNAMIC)) &&
242
	    tnbr->pw_count == 0) {
243
		tnbr_del(tnbr);
244
		return (NULL);
245
	}
246
247
	return (tnbr);
248
}
249
250
void
251
tnbr_update(struct tnbr *tnbr)
252
{
253
	int			 socket_ok, rtr_id_ok;
254
255
	if ((ldp_af_global_get(&global, tnbr->af))->ldp_edisc_socket != -1)
256
		socket_ok = 1;
257
	else
258
		socket_ok = 0;
259
260
	if (leconf->rtr_id.s_addr != INADDR_ANY)
261
		rtr_id_ok = 1;
262
	else
263
		rtr_id_ok = 0;
264
265
	if (tnbr->state == TNBR_STA_DOWN) {
266
		if (!socket_ok || !rtr_id_ok)
267
			return;
268
269
		tnbr->state = TNBR_STA_ACTIVE;
270
		send_hello(HELLO_TARGETED, NULL, tnbr);
271
272
		evtimer_set(&tnbr->hello_timer, tnbr_hello_timer, tnbr);
273
		tnbr_start_hello_timer(tnbr);
274
	} else if (tnbr->state == TNBR_STA_ACTIVE) {
275
		if (socket_ok && rtr_id_ok)
276
			return;
277
278
		tnbr->state = TNBR_STA_DOWN;
279
		tnbr_stop_hello_timer(tnbr);
280
	}
281
}
282
283
void
284
tnbr_update_all(int af)
285
{
286
	struct tnbr		*tnbr;
287
288
	/* update targeted neighbors */
289
	LIST_FOREACH(tnbr, &leconf->tnbr_list, entry)
290
		if (tnbr->af == af || af == AF_UNSPEC)
291
			tnbr_update(tnbr);
292
}
293
294
/* target neighbors timers */
295
296
/* ARGSUSED */
297
static void
298
tnbr_hello_timer(int fd, short event, void *arg)
299
{
300
	struct tnbr	*tnbr = arg;
301
302
	send_hello(HELLO_TARGETED, NULL, tnbr);
303
	tnbr_start_hello_timer(tnbr);
304
}
305
306
static void
307
tnbr_start_hello_timer(struct tnbr *tnbr)
308
{
309
	struct timeval	 tv;
310
311
	timerclear(&tv);
312
	tv.tv_sec = tnbr->hello_interval;
313
	if (evtimer_add(&tnbr->hello_timer, &tv) == -1)
314
		fatal(__func__);
315
}
316
317
static void
318
tnbr_stop_hello_timer(struct tnbr *tnbr)
319
{
320
	if (evtimer_pending(&tnbr->hello_timer, NULL) &&
321
	    evtimer_del(&tnbr->hello_timer) == -1)
322
		fatal(__func__);
323
}
324
325
struct ctl_adj *
326
adj_to_ctl(struct adj *adj)
327
{
328
	static struct ctl_adj	 actl;
329
330
	actl.af = adj_get_af(adj);
331
	actl.id = adj->lsr_id;
332
	actl.type = adj->source.type;
333
	switch (adj->source.type) {
334
	case HELLO_LINK:
335
		memcpy(actl.ifname, adj->source.link.ia->iface->name,
336
		    sizeof(actl.ifname));
337
		break;
338
	case HELLO_TARGETED:
339
		actl.src_addr = adj->source.target->addr;
340
		break;
341
	}
342
	actl.holdtime = adj->holdtime;
343
	actl.trans_addr = adj->trans_addr;
344
345
	return (&actl);
346
}