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

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