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

Line Branch Exec Source
1
/*	$OpenBSD: lsack.c,v 1.6 2014/10/25 03:23:49 lteo Exp $ */
2
3
/*
4
 * Copyright (c) 2004, 2005, 2007 Esben Norby <norby@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/socket.h>
21
#include <netinet/in.h>
22
#include <netinet/ip.h>
23
#include <arpa/inet.h>
24
25
#include <stdlib.h>
26
#include <string.h>
27
28
#include "ospf6d.h"
29
#include "ospf6.h"
30
#include "log.h"
31
#include "ospfe.h"
32
33
void	 start_ls_ack_tx_timer_now(struct iface *);
34
35
/* link state acknowledgement packet handling */
36
int
37
send_ls_ack(struct iface *iface, struct in6_addr addr, void *data, size_t len)
38
{
39
	struct ibuf	*buf;
40
	int		 ret;
41
42
	/* XXX IBUF_READ_SIZE */
43
	if ((buf = ibuf_dynamic(PKG_DEF_SIZE, IBUF_READ_SIZE)) == NULL)
44
		fatal("send_ls_ack");
45
46
	/* OSPF header */
47
	if (gen_ospf_hdr(buf, iface, PACKET_TYPE_LS_ACK))
48
		goto fail;
49
50
	/* LS ack(s) */
51
	if (ibuf_add(buf, data, len))
52
		goto fail;
53
54
	/* calculate checksum */
55
	if (upd_ospf_hdr(buf, iface))
56
		goto fail;
57
58
	ret = send_packet(iface, buf->buf, buf->wpos, &addr);
59
60
	ibuf_free(buf);
61
	return (ret);
62
fail:
63
	log_warn("send_ls_ack");
64
	ibuf_free(buf);
65
	return (-1);
66
}
67
68
void
69
recv_ls_ack(struct nbr *nbr, char *buf, u_int16_t len)
70
{
71
	struct lsa_hdr	 lsa_hdr;
72
73
	switch (nbr->state) {
74
	case NBR_STA_DOWN:
75
	case NBR_STA_ATTEMPT:
76
	case NBR_STA_INIT:
77
	case NBR_STA_2_WAY:
78
	case NBR_STA_XSTRT:
79
	case NBR_STA_SNAP:
80
		log_debug("recv_ls_ack: packet ignored in state %s, "
81
		    "neighbor ID %s", nbr_state_name(nbr->state),
82
		    inet_ntoa(nbr->id));
83
		break;
84
	case NBR_STA_XCHNG:
85
	case NBR_STA_LOAD:
86
	case NBR_STA_FULL:
87
		while (len >= sizeof(lsa_hdr)) {
88
			memcpy(&lsa_hdr, buf, sizeof(lsa_hdr));
89
90
			if (lsa_hdr_check(nbr, &lsa_hdr)) {
91
				/* try both list in case of DROTHER */
92
				if (nbr->iface->state & IF_STA_DROTHER)
93
					(void)ls_retrans_list_del(
94
					    nbr->iface->self, &lsa_hdr);
95
				(void)ls_retrans_list_del(nbr, &lsa_hdr);
96
			}
97
98
			buf += sizeof(lsa_hdr);
99
			len -= sizeof(lsa_hdr);
100
		}
101
		if (len > 0) {
102
			log_warnx("recv_ls_ack: bad packet size, "
103
			    "neighbor ID %s", inet_ntoa(nbr->id));
104
			return;
105
		}
106
		break;
107
	default:
108
		fatalx("recv_ls_ack: unknown neighbor state");
109
	}
110
}
111
112
int
113
lsa_hdr_check(struct nbr *nbr, struct lsa_hdr *lsa_hdr)
114
{
115
	/* invalid age */
116
	if ((ntohs(lsa_hdr->age) < 1) || (ntohs(lsa_hdr->age) > MAX_AGE)) {
117
		log_debug("lsa_hdr_check: invalid age, neighbor ID %s",
118
		     inet_ntoa(nbr->id));
119
		return (0);
120
	}
121
122
	/* invalid type */
123
	switch (ntohs(lsa_hdr->type)) {
124
	case LSA_TYPE_LINK:
125
	case LSA_TYPE_ROUTER:
126
	case LSA_TYPE_NETWORK:
127
	case LSA_TYPE_INTER_A_PREFIX:
128
	case LSA_TYPE_INTER_A_ROUTER:
129
	case LSA_TYPE_INTRA_A_PREFIX:
130
	case LSA_TYPE_EXTERNAL:
131
		break;
132
	default:
133
		log_debug("lsa_hdr_check: invalid LSA type %d, neighbor ID %s",
134
		    lsa_hdr->type, inet_ntoa(nbr->id));
135
		return (0);
136
	}
137
138
	/* invalid sequence number */
139
	if (ntohl(lsa_hdr->seq_num) == RESV_SEQ_NUM) {
140
		log_debug("ls_hdr_check: invalid seq num, neighbor ID %s",
141
			inet_ntoa(nbr->id));
142
		return (0);
143
	}
144
145
	return (1);
146
}
147
148
/* link state ack list */
149
void
150
ls_ack_list_add(struct iface *iface, struct lsa_hdr *lsa)
151
{
152
	struct lsa_entry	*le;
153
154
	if (lsa == NULL)
155
		fatalx("ls_ack_list_add: no LSA header");
156
157
	if ((le = calloc(1, sizeof(*le))) == NULL)
158
		fatal("ls_ack_list_add");
159
160
	if (ls_ack_list_empty(iface))
161
		start_ls_ack_tx_timer(iface);
162
163
	TAILQ_INSERT_TAIL(&iface->ls_ack_list, le, entry);
164
	le->le_lsa = lsa;
165
	iface->ls_ack_cnt++;
166
167
	/* reschedule now if we have enough for a full packet */
168
	if (iface->ls_ack_cnt >
169
	    ((iface->mtu - PACKET_HDR) / sizeof(struct lsa_hdr))) {
170
		start_ls_ack_tx_timer_now(iface);
171
	}
172
}
173
174
void
175
ls_ack_list_free(struct iface *iface, struct lsa_entry *le)
176
{
177
	TAILQ_REMOVE(&iface->ls_ack_list, le, entry);
178
	free(le->le_lsa);
179
	free(le);
180
181
	iface->ls_ack_cnt--;
182
}
183
184
void
185
ls_ack_list_clr(struct iface *iface)
186
{
187
	struct lsa_entry	*le;
188
189
	while ((le = TAILQ_FIRST(&iface->ls_ack_list)) != NULL) {
190
		TAILQ_REMOVE(&iface->ls_ack_list, le, entry);
191
		free(le->le_lsa);
192
		free(le);
193
	}
194
	iface->ls_ack_cnt = 0;
195
}
196
197
int
198
ls_ack_list_empty(struct iface *iface)
199
{
200
	return (TAILQ_EMPTY(&iface->ls_ack_list));
201
}
202
203
/* timers */
204
/* ARGSUSED */
205
void
206
ls_ack_tx_timer(int fd, short event, void *arg)
207
{
208
	struct in6_addr		 addr;
209
	struct iface		*iface = arg;
210
	struct lsa_hdr		*lsa_hdr;
211
	struct lsa_entry	*le, *nle;
212
	struct nbr		*nbr;
213
	char			*buf;
214
	char			*ptr;
215
	int			 cnt = 0;
216
217
	if ((buf = calloc(1, READ_BUF_SIZE)) == NULL)
218
		fatal("ls_ack_tx_timer");
219
220
	while (!ls_ack_list_empty(iface)) {
221
		ptr = buf;
222
		cnt = 0;
223
		for (le = TAILQ_FIRST(&iface->ls_ack_list); le != NULL &&
224
		    (ptr - buf < iface->mtu - PACKET_HDR); le = nle) {
225
			nle = TAILQ_NEXT(le, entry);
226
			memcpy(ptr, le->le_lsa, sizeof(struct lsa_hdr));
227
			ptr += sizeof(*lsa_hdr);
228
			ls_ack_list_free(iface, le);
229
			cnt++;
230
		}
231
232
		/* send LS ack(s) but first set correct destination */
233
		switch (iface->type) {
234
		case IF_TYPE_POINTOPOINT:
235
			inet_pton(AF_INET6, AllSPFRouters, &addr);
236
			send_ls_ack(iface, addr, buf, ptr - buf);
237
			break;
238
		case IF_TYPE_BROADCAST:
239
			if (iface->state & IF_STA_DRORBDR)
240
				inet_pton(AF_INET6, AllSPFRouters, &addr);
241
			else
242
				inet_pton(AF_INET6, AllDRouters, &addr);
243
244
			send_ls_ack(iface, addr, buf, ptr - buf);
245
			break;
246
		case IF_TYPE_NBMA:
247
		case IF_TYPE_POINTOMULTIPOINT:
248
		case IF_TYPE_VIRTUALLINK:
249
			LIST_FOREACH(nbr, &iface->nbr_list, entry) {
250
				if (nbr == iface->self)
251
					continue;
252
				if (!(nbr->state & NBR_STA_FLOOD))
253
					continue;
254
				send_ls_ack(iface, nbr->addr, buf, ptr - buf);
255
			}
256
			break;
257
		default:
258
			fatalx("lsa_ack_tx_timer: unknown interface type");
259
		}
260
	}
261
262
	free(buf);
263
}
264
265
void
266
start_ls_ack_tx_timer(struct iface *iface)
267
{
268
	struct timeval tv;
269
270
	timerclear(&tv);
271
	tv.tv_sec = iface->rxmt_interval / 2;
272
273
	if (evtimer_add(&iface->lsack_tx_timer, &tv) == -1)
274
		fatal("start_ls_ack_tx_timer");
275
}
276
277
void
278
start_ls_ack_tx_timer_now(struct iface *iface)
279
{
280
	struct timeval tv;
281
282
	timerclear(&tv);
283
	if (evtimer_add(&iface->lsack_tx_timer, &tv) == -1)
284
		fatal("start_ls_ack_tx_timer_now");
285
}
286
287
void
288
stop_ls_ack_tx_timer(struct iface *iface)
289
{
290
	if (evtimer_del(&iface->lsack_tx_timer) == -1)
291
		fatal("stop_ls_ack_tx_timer");
292
}