GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ospf6d/database.c Lines: 0 169 0.0 %
Date: 2017-11-07 Branches: 0 126 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: database.c,v 1.15 2014/10/25 03:23:49 lteo Exp $ */
2
3
/*
4
 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
5
 * Copyright (c) 2004, 2005, 2007 Esben Norby <norby@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <sys/types.h>
21
#include <sys/socket.h>
22
#include <netinet/in.h>
23
#include <netinet/ip.h>
24
#include <arpa/inet.h>
25
#include <stdlib.h>
26
#include <string.h>
27
#include <unistd.h>
28
29
#include "ospf6d.h"
30
#include "ospf6.h"
31
#include "log.h"
32
#include "ospfe.h"
33
34
extern struct ospfd_conf	*oeconf;
35
36
void	db_sum_list_next(struct nbr *);
37
38
/* database description packet handling */
39
int
40
send_db_description(struct nbr *nbr)
41
{
42
	struct in6_addr		 dst;
43
	struct db_dscrp_hdr	 dd_hdr;
44
	struct lsa_entry	*le, *nle;
45
	struct ibuf		*buf;
46
	int			 ret = 0;
47
	u_int8_t		 bits = 0;
48
49
	if ((buf = ibuf_open(nbr->iface->mtu - sizeof(struct ip))) == NULL)
50
		fatal("send_db_description");
51
52
	/* OSPF header */
53
	if (gen_ospf_hdr(buf, nbr->iface, PACKET_TYPE_DD))
54
		goto fail;
55
56
	/* reserve space for database description header */
57
	if (ibuf_reserve(buf, sizeof(dd_hdr)) == NULL)
58
		goto fail;
59
60
	switch (nbr->state) {
61
	case NBR_STA_DOWN:
62
	case NBR_STA_ATTEMPT:
63
	case NBR_STA_INIT:
64
	case NBR_STA_2_WAY:
65
	case NBR_STA_SNAP:
66
		log_debug("send_db_description: cannot send packet in state %s,"
67
		    " neighbor ID %s", nbr_state_name(nbr->state),
68
		    inet_ntoa(nbr->id));
69
		ret = -1;
70
		goto done;
71
	case NBR_STA_XSTRT:
72
		bits |= OSPF_DBD_MS | OSPF_DBD_M | OSPF_DBD_I;
73
		nbr->dd_more = 1;
74
		break;
75
	case NBR_STA_XCHNG:
76
		if (nbr->dd_master)
77
			bits |= OSPF_DBD_MS;
78
		else
79
			bits &= ~OSPF_DBD_MS;
80
81
		if (TAILQ_EMPTY(&nbr->db_sum_list)) {
82
			bits &= ~OSPF_DBD_M;
83
			nbr->dd_more = 0;
84
		} else {
85
			bits |= OSPF_DBD_M;
86
			nbr->dd_more = 1;
87
		}
88
89
		bits &= ~OSPF_DBD_I;
90
91
		/* build LSA list */
92
		for (le = TAILQ_FIRST(&nbr->db_sum_list); le != NULL &&
93
		    buf->wpos + sizeof(struct lsa_hdr) < buf->max; le = nle) {
94
			nbr->dd_end = nle = TAILQ_NEXT(le, entry);
95
			if (ibuf_add(buf, le->le_lsa, sizeof(struct lsa_hdr)))
96
				goto fail;
97
		}
98
		break;
99
	case NBR_STA_LOAD:
100
	case NBR_STA_FULL:
101
		if (nbr->dd_master)
102
			bits |= OSPF_DBD_MS;
103
		else
104
			bits &= ~OSPF_DBD_MS;
105
		bits &= ~OSPF_DBD_M;
106
		bits &= ~OSPF_DBD_I;
107
108
		nbr->dd_more = 0;
109
		break;
110
	default:
111
		fatalx("send_db_description: unknown neighbor state");
112
	}
113
114
	bzero(&dd_hdr, sizeof(dd_hdr));
115
116
	switch (nbr->iface->type) {
117
	case IF_TYPE_POINTOPOINT:
118
		inet_pton(AF_INET6, AllSPFRouters, &dst);
119
		dd_hdr.iface_mtu = htons(nbr->iface->mtu);
120
		break;
121
	case IF_TYPE_BROADCAST:
122
		dst = nbr->addr;
123
		dd_hdr.iface_mtu = htons(nbr->iface->mtu);
124
		break;
125
	case IF_TYPE_NBMA:
126
	case IF_TYPE_POINTOMULTIPOINT:
127
		/* XXX not supported */
128
		break;
129
	case IF_TYPE_VIRTUALLINK:
130
		dst = nbr->iface->dst;
131
		dd_hdr.iface_mtu = 0;
132
		break;
133
	default:
134
		fatalx("send_db_description: unknown interface type");
135
	}
136
137
	dd_hdr.opts = htonl(area_ospf_options(area_find(oeconf,
138
	    nbr->iface->area_id)));
139
	dd_hdr.bits = bits;
140
	dd_hdr.dd_seq_num = htonl(nbr->dd_seq_num);
141
142
	memcpy(ibuf_seek(buf, sizeof(struct ospf_hdr), sizeof(dd_hdr)),
143
	    &dd_hdr, sizeof(dd_hdr));
144
145
	/* calculate checksum */
146
	if (upd_ospf_hdr(buf, nbr->iface))
147
		goto fail;
148
149
	/* transmit packet */
150
	ret = send_packet(nbr->iface, buf->buf, buf->wpos, &dst);
151
done:
152
	ibuf_free(buf);
153
	return (ret);
154
fail:
155
	log_warn("send_db_description");
156
	ibuf_free(buf);
157
	return (-1);
158
}
159
160
void
161
recv_db_description(struct nbr *nbr, char *buf, u_int16_t len)
162
{
163
	struct db_dscrp_hdr	 dd_hdr;
164
	int			 dupe = 0;
165
166
	if (len < sizeof(dd_hdr)) {
167
		log_warnx("recv_db_description: "
168
		    "bad packet size, neighbor ID %s", inet_ntoa(nbr->id));
169
		return;
170
	}
171
	memcpy(&dd_hdr, buf, sizeof(dd_hdr));
172
	buf += sizeof(dd_hdr);
173
	len -= sizeof(dd_hdr);
174
175
	/* db description packet sanity checks */
176
	if (ntohs(dd_hdr.iface_mtu) > nbr->iface->mtu) {
177
		log_warnx("recv_db_description: invalid MTU %d sent by "
178
		    "neighbor ID %s, expected %d", ntohs(dd_hdr.iface_mtu),
179
		    inet_ntoa(nbr->id), nbr->iface->mtu);
180
		return;
181
	}
182
183
	if (nbr->last_rx_options == dd_hdr.opts &&
184
	    nbr->last_rx_bits == dd_hdr.bits &&
185
	    ntohl(dd_hdr.dd_seq_num) == nbr->dd_seq_num - nbr->dd_master ?
186
	    1 : 0) {
187
		log_debug("recv_db_description: dupe from ID %s",
188
		    inet_ntoa(nbr->id));
189
		dupe = 1;
190
	}
191
192
	switch (nbr->state) {
193
	case NBR_STA_DOWN:
194
	case NBR_STA_ATTEMPT:
195
	case NBR_STA_2_WAY:
196
	case NBR_STA_SNAP:
197
		log_debug("recv_db_description: packet ignored in state %s, "
198
		    "neighbor ID %s", nbr_state_name(nbr->state),
199
		    inet_ntoa(nbr->id));
200
		return;
201
	case NBR_STA_INIT:
202
		/* evaluate dr and bdr after issuing a 2-Way event */
203
		nbr_fsm(nbr, NBR_EVT_2_WAY_RCVD);
204
		if_fsm(nbr->iface, IF_EVT_NBR_CHNG);
205
		if (nbr->state != NBR_STA_XSTRT)
206
			return;
207
		/* FALLTHROUGH */
208
	case NBR_STA_XSTRT:
209
		if (dupe)
210
			return;
211
		/*
212
		 * check bits: either I,M,MS or only M
213
		 */
214
		if (dd_hdr.bits == (OSPF_DBD_I | OSPF_DBD_M | OSPF_DBD_MS)) {
215
			/* if nbr Router ID is larger than own -> slave */
216
			if ((ntohl(nbr->id.s_addr)) >
217
			    ntohl(ospfe_router_id())) {
218
				/* slave */
219
				nbr->dd_master = 0;
220
				nbr->dd_seq_num = ntohl(dd_hdr.dd_seq_num);
221
222
				/* event negotiation done */
223
				nbr_fsm(nbr, NBR_EVT_NEG_DONE);
224
			}
225
		} else if (!(dd_hdr.bits & (OSPF_DBD_I | OSPF_DBD_MS))) {
226
			/* M only case: we are master */
227
			if (ntohl(dd_hdr.dd_seq_num) != nbr->dd_seq_num) {
228
				log_warnx("recv_db_description: invalid "
229
				    "seq num, mine %x his %x",
230
				    nbr->dd_seq_num, ntohl(dd_hdr.dd_seq_num));
231
				return;
232
			}
233
			nbr->dd_seq_num++;
234
235
			/* event negotiation done */
236
			nbr_fsm(nbr, NBR_EVT_NEG_DONE);
237
238
			/* this packet may already have data so pass it on */
239
			if (len > 0) {
240
				nbr->dd_pending++;
241
				ospfe_imsg_compose_rde(IMSG_DD, nbr->peerid,
242
				    0, buf, len);
243
			}
244
		} else {
245
			/* ignore packet */
246
			log_debug("recv_db_description: packet ignored in "
247
			    "state %s (bad flags), neighbor ID %s",
248
			    nbr_state_name(nbr->state), inet_ntoa(nbr->id));
249
		}
250
		break;
251
	case NBR_STA_XCHNG:
252
	case NBR_STA_LOAD:
253
	case NBR_STA_FULL:
254
		if (dd_hdr.bits & OSPF_DBD_I ||
255
		    !(dd_hdr.bits & OSPF_DBD_MS) == !nbr->dd_master) {
256
			log_warnx("recv_db_description: seq num mismatch, "
257
			    "bad flags");
258
			nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS);
259
			return;
260
		}
261
262
		if (nbr->last_rx_options != dd_hdr.opts) {
263
			log_warnx("recv_db_description: seq num mismatch, "
264
			    "bad options");
265
			nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS);
266
			return;
267
		}
268
269
		if (dupe) {
270
			if (!nbr->dd_master)
271
				/* retransmit */
272
				start_db_tx_timer(nbr);
273
			return;
274
		}
275
276
		if (nbr->state != NBR_STA_XCHNG) {
277
			log_warnx("recv_db_description: invalid "
278
			    "seq num, mine %x his %x",
279
			    nbr->dd_seq_num, ntohl(dd_hdr.dd_seq_num));
280
			nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS);
281
			return;
282
		}
283
284
		/* sanity check dd seq number */
285
		if (nbr->dd_master) {
286
			/* master */
287
			if (ntohl(dd_hdr.dd_seq_num) != nbr->dd_seq_num) {
288
				log_warnx("recv_db_description: invalid "
289
				    "seq num, mine %x his %x",
290
				    nbr->dd_seq_num, ntohl(dd_hdr.dd_seq_num));
291
				nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS);
292
				return;
293
			}
294
			nbr->dd_seq_num++;
295
		} else {
296
			/* slave */
297
			if (ntohl(dd_hdr.dd_seq_num) != nbr->dd_seq_num + 1) {
298
				log_warnx("recv_db_description: invalid "
299
				    "seq num, mine %x his %x",
300
				    nbr->dd_seq_num, ntohl(dd_hdr.dd_seq_num));
301
				nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS);
302
				return;
303
			}
304
			nbr->dd_seq_num = ntohl(dd_hdr.dd_seq_num);
305
		}
306
307
		/* forward to RDE and let it decide which LSAs to request */
308
		if (len > 0) {
309
			nbr->dd_pending++;
310
			ospfe_imsg_compose_rde(IMSG_DD, nbr->peerid, 0,
311
			    buf, len);
312
		}
313
314
		/* next packet */
315
		db_sum_list_next(nbr);
316
		start_db_tx_timer(nbr);
317
318
		if (!(dd_hdr.bits & OSPF_DBD_M) &&
319
		    TAILQ_EMPTY(&nbr->db_sum_list))
320
			if (!nbr->dd_master || !nbr->dd_more)
321
				nbr_fsm(nbr, NBR_EVT_XCHNG_DONE);
322
		break;
323
	default:
324
		fatalx("recv_db_description: unknown neighbor state");
325
	}
326
327
	nbr->last_rx_options = dd_hdr.opts;
328
	nbr->last_rx_bits = dd_hdr.bits;
329
}
330
331
void
332
db_sum_list_add(struct nbr *nbr, struct lsa_hdr *lsa)
333
{
334
	struct lsa_entry	*le;
335
336
	if ((le = calloc(1, sizeof(*le))) == NULL)
337
		fatal("db_sum_list_add");
338
339
	TAILQ_INSERT_TAIL(&nbr->db_sum_list, le, entry);
340
	le->le_lsa = lsa;
341
}
342
343
void
344
db_sum_list_next(struct nbr *nbr)
345
{
346
	struct lsa_entry	*le;
347
348
	while ((le = TAILQ_FIRST(&nbr->db_sum_list)) != nbr->dd_end) {
349
		TAILQ_REMOVE(&nbr->db_sum_list, le, entry);
350
		free(le->le_lsa);
351
		free(le);
352
	}
353
}
354
355
void
356
db_sum_list_clr(struct nbr *nbr)
357
{
358
	nbr->dd_end = NULL;
359
	db_sum_list_next(nbr);
360
}
361
362
/* timers */
363
/* ARGSUSED */
364
void
365
db_tx_timer(int fd, short event, void *arg)
366
{
367
	struct nbr *nbr = arg;
368
	struct timeval tv;
369
370
	switch (nbr->state) {
371
	case NBR_STA_DOWN:
372
	case NBR_STA_ATTEMPT:
373
	case NBR_STA_INIT:
374
	case NBR_STA_2_WAY:
375
	case NBR_STA_SNAP:
376
		return ;
377
	case NBR_STA_XSTRT:
378
	case NBR_STA_XCHNG:
379
	case NBR_STA_LOAD:
380
	case NBR_STA_FULL:
381
		send_db_description(nbr);
382
		break;
383
	default:
384
		log_debug("db_tx_timer: unknown neighbor state, "
385
		    "neighbor ID %s", inet_ntoa(nbr->id));
386
		break;
387
	}
388
389
	/* reschedule db_tx_timer but only in master mode */
390
	if (nbr->dd_master) {
391
		timerclear(&tv);
392
		tv.tv_sec = nbr->iface->rxmt_interval;
393
		if (evtimer_add(&nbr->db_tx_timer, &tv) == -1)
394
			fatal("db_tx_timer");
395
	}
396
}
397
398
void
399
start_db_tx_timer(struct nbr *nbr)
400
{
401
	struct timeval	tv;
402
403
	if (nbr == nbr->iface->self)
404
		return;
405
406
	timerclear(&tv);
407
	if (evtimer_add(&nbr->db_tx_timer, &tv) == -1)
408
		fatal("start_db_tx_timer");
409
}
410
411
void
412
stop_db_tx_timer(struct nbr *nbr)
413
{
414
	if (nbr == nbr->iface->self)
415
		return;
416
417
	if (evtimer_del(&nbr->db_tx_timer) == -1)
418
		fatal("stop_db_tx_timer");
419
}