GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ospf6d/lsreq.c Lines: 0 90 0.0 %
Date: 2017-11-13 Branches: 0 80 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: lsreq.c,v 1.8 2013/03/22 14:26:35 sthen 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 <arpa/inet.h>
23
#include <stdlib.h>
24
25
#include "ospf6d.h"
26
#include "ospf6.h"
27
#include "log.h"
28
#include "ospfe.h"
29
30
extern struct imsgev		*iev_rde;
31
32
/* link state request packet handling */
33
int
34
send_ls_req(struct nbr *nbr)
35
{
36
	struct in6_addr		 dst;
37
	struct ls_req_hdr	 ls_req_hdr;
38
	struct lsa_entry	*le, *nle;
39
	struct ibuf		*buf;
40
	int			 ret;
41
42
	if ((buf = ibuf_open(nbr->iface->mtu - sizeof(struct ip))) == NULL)
43
		fatal("send_ls_req");
44
45
	switch (nbr->iface->type) {
46
	case IF_TYPE_POINTOPOINT:
47
		inet_pton(AF_INET6, AllSPFRouters, &dst);
48
		break;
49
	case IF_TYPE_BROADCAST:
50
	case IF_TYPE_NBMA:
51
	case IF_TYPE_POINTOMULTIPOINT:
52
	case IF_TYPE_VIRTUALLINK:
53
		dst = nbr->addr;
54
		break;
55
	default:
56
		fatalx("send_ls_req: unknown interface type");
57
	}
58
59
	/* OSPF header */
60
	if (gen_ospf_hdr(buf, nbr->iface, PACKET_TYPE_LS_REQUEST))
61
		goto fail;
62
63
	/* LSA header(s) */
64
	for (le = TAILQ_FIRST(&nbr->ls_req_list); le != NULL &&
65
	    buf->wpos + sizeof(struct ls_req_hdr) < buf->max; le = nle) {
66
		nbr->ls_req = nle = TAILQ_NEXT(le, entry);
67
		ls_req_hdr.zero = 0;
68
		ls_req_hdr.type = le->le_lsa->type;
69
		ls_req_hdr.ls_id = le->le_lsa->ls_id;
70
		ls_req_hdr.adv_rtr = le->le_lsa->adv_rtr;
71
		if (ibuf_add(buf, &ls_req_hdr, sizeof(ls_req_hdr)))
72
			goto fail;
73
	}
74
75
	/* calculate checksum */
76
	if (upd_ospf_hdr(buf, nbr->iface))
77
		goto fail;
78
79
	ret = send_packet(nbr->iface, buf->buf, buf->wpos, &dst);
80
81
	ibuf_free(buf);
82
	return (ret);
83
fail:
84
	log_warn("send_ls_req");
85
	ibuf_free(buf);
86
	return (-1);
87
}
88
89
void
90
recv_ls_req(struct nbr *nbr, char *buf, u_int16_t len)
91
{
92
	switch (nbr->state) {
93
	case NBR_STA_DOWN:
94
	case NBR_STA_ATTEMPT:
95
	case NBR_STA_INIT:
96
	case NBR_STA_2_WAY:
97
	case NBR_STA_XSTRT:
98
	case NBR_STA_SNAP:
99
		log_debug("recv_ls_req: packet ignored in state %s, "
100
		    "neighbor ID %s", nbr_state_name(nbr->state),
101
		    inet_ntoa(nbr->id));
102
		break;
103
	case NBR_STA_XCHNG:
104
	case NBR_STA_LOAD:
105
	case NBR_STA_FULL:
106
		imsg_compose_event(iev_rde, IMSG_LS_REQ, nbr->peerid,
107
		    0, -1, buf, len);
108
		break;
109
	default:
110
		fatalx("recv_ls_req: unknown neighbor state");
111
	}
112
}
113
114
/* link state request list */
115
void
116
ls_req_list_add(struct nbr *nbr, struct lsa_hdr *lsa)
117
{
118
	struct lsa_entry	*le;
119
120
	if (lsa == NULL)
121
		fatalx("ls_req_list_add: no LSA header");
122
123
	if ((le = calloc(1, sizeof(*le))) == NULL)
124
		fatal("ls_req_list_add");
125
126
	TAILQ_INSERT_TAIL(&nbr->ls_req_list, le, entry);
127
	le->le_lsa = lsa;
128
	nbr->ls_req_cnt++;
129
}
130
131
struct lsa_entry *
132
ls_req_list_get(struct nbr *nbr, struct lsa_hdr *lsa_hdr)
133
{
134
	struct lsa_entry	*le;
135
136
	TAILQ_FOREACH(le, &nbr->ls_req_list, entry) {
137
		if ((lsa_hdr->type == le->le_lsa->type) &&
138
		    (lsa_hdr->ls_id == le->le_lsa->ls_id) &&
139
		    (lsa_hdr->adv_rtr == le->le_lsa->adv_rtr))
140
			return (le);
141
	}
142
	return (NULL);
143
}
144
145
void
146
ls_req_list_free(struct nbr *nbr, struct lsa_entry *le)
147
{
148
	if (nbr->ls_req == le) {
149
		nbr->ls_req = TAILQ_NEXT(le, entry);
150
	}
151
152
	TAILQ_REMOVE(&nbr->ls_req_list, le, entry);
153
	free(le->le_lsa);
154
	free(le);
155
	nbr->ls_req_cnt--;
156
157
	/* received all requested LSA(s), send a new LS req */
158
	if (nbr->ls_req != NULL &&
159
	    nbr->ls_req == TAILQ_FIRST(&nbr->ls_req_list)) {
160
		start_ls_req_tx_timer(nbr);
161
	}
162
163
	/* we might not have received all DDs and are still in XCHNG */
164
	if (ls_req_list_empty(nbr) && nbr->dd_pending == 0 &&
165
	    nbr->state != NBR_STA_XCHNG)
166
		nbr_fsm(nbr, NBR_EVT_LOAD_DONE);
167
}
168
169
void
170
ls_req_list_clr(struct nbr *nbr)
171
{
172
	struct lsa_entry	*le;
173
174
	while ((le = TAILQ_FIRST(&nbr->ls_req_list)) != NULL) {
175
		TAILQ_REMOVE(&nbr->ls_req_list, le, entry);
176
		free(le->le_lsa);
177
		free(le);
178
	}
179
180
	nbr->ls_req_cnt = 0;
181
	nbr->ls_req = NULL;
182
}
183
184
int
185
ls_req_list_empty(struct nbr *nbr)
186
{
187
	return (TAILQ_EMPTY(&nbr->ls_req_list));
188
}
189
190
/* timers */
191
/* ARGSUSED */
192
void
193
ls_req_tx_timer(int fd, short event, void *arg)
194
{
195
	struct nbr	*nbr = arg;
196
	struct timeval	 tv;
197
198
	switch (nbr->state) {
199
	case NBR_STA_DOWN:
200
	case NBR_STA_ATTEMPT:
201
	case NBR_STA_INIT:
202
	case NBR_STA_2_WAY:
203
	case NBR_STA_SNAP:
204
	case NBR_STA_XSTRT:
205
	case NBR_STA_XCHNG:
206
		return;
207
	case NBR_STA_LOAD:
208
		send_ls_req(nbr);
209
		break;
210
	case NBR_STA_FULL:
211
		return;
212
	default:
213
		log_debug("ls_req_tx_timer: unknown neighbor state, "
214
		    "neighbor ID %s", inet_ntoa(nbr->id));
215
		break;
216
	}
217
218
	/* reschedule lsreq_tx_timer */
219
	if (nbr->state == NBR_STA_LOAD) {
220
		timerclear(&tv);
221
		tv.tv_sec = nbr->iface->rxmt_interval;
222
		if (evtimer_add(&nbr->lsreq_tx_timer, &tv) == -1)
223
			fatal("ls_req_tx_timer");
224
	}
225
}
226
227
void
228
start_ls_req_tx_timer(struct nbr *nbr)
229
{
230
	struct timeval tv;
231
232
	if (nbr == nbr->iface->self)
233
		return;
234
235
	timerclear(&tv);
236
	if (evtimer_add(&nbr->lsreq_tx_timer, &tv) == -1)
237
		fatal("start_ls_req_tx_timer");
238
}
239
240
void
241
stop_ls_req_tx_timer(struct nbr *nbr)
242
{
243
	if (nbr == nbr->iface->self)
244
		return;
245
246
	if (evtimer_del(&nbr->lsreq_tx_timer) == -1)
247
		fatal("stop_ls_req_tx_timer");
248
}