xref: /openbsd-src/usr.sbin/ospfd/database.c (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
1 /*	$OpenBSD: database.c,v 1.30 2013/01/17 08:58:53 markus Exp $ */
2 
3 /*
4  * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
5  * Copyright (c) 2004, 2005 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/in_systm.h>
24 #include <netinet/ip.h>
25 #include <arpa/inet.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 
30 #include "ospfd.h"
31 #include "ospf.h"
32 #include "log.h"
33 #include "ospfe.h"
34 
35 extern struct ospfd_conf	*oeconf;
36 
37 void	db_sum_list_next(struct nbr *);
38 
39 /* database description packet handling */
40 int
41 send_db_description(struct nbr *nbr)
42 {
43 	struct sockaddr_in	 dst;
44 	struct db_dscrp_hdr	 dd_hdr;
45 	struct lsa_entry	*le, *nle;
46 	struct ibuf		*buf;
47 	int			 ret = 0;
48 	u_int8_t		 bits = 0;
49 
50 	if ((buf = ibuf_open(nbr->iface->mtu - sizeof(struct ip))) == NULL)
51 		fatal("send_db_description");
52 
53 	/* OSPF header */
54 	if (gen_ospf_hdr(buf, nbr->iface, PACKET_TYPE_DD))
55 		goto fail;
56 
57 	/* reserve space for database description header */
58 	if (ibuf_reserve(buf, sizeof(dd_hdr)) == NULL)
59 		goto fail;
60 
61 	switch (nbr->state) {
62 	case NBR_STA_DOWN:
63 	case NBR_STA_ATTEMPT:
64 	case NBR_STA_INIT:
65 	case NBR_STA_2_WAY:
66 	case NBR_STA_SNAP:
67 		log_debug("send_db_description: cannot send packet in state %s,"
68 		    " neighbor ID %s", nbr_state_name(nbr->state),
69 		    inet_ntoa(nbr->id));
70 		ret = -1;
71 		goto done;
72 	case NBR_STA_XSTRT:
73 		bits |= OSPF_DBD_MS | OSPF_DBD_M | OSPF_DBD_I;
74 		nbr->dd_more = 1;
75 		break;
76 	case NBR_STA_XCHNG:
77 		if (nbr->dd_master)
78 			bits |= OSPF_DBD_MS;
79 		else
80 			bits &= ~OSPF_DBD_MS;
81 
82 		if (TAILQ_EMPTY(&nbr->db_sum_list)) {
83 			bits &= ~OSPF_DBD_M;
84 			nbr->dd_more = 0;
85 		} else {
86 			bits |= OSPF_DBD_M;
87 			nbr->dd_more = 1;
88 		}
89 
90 		bits &= ~OSPF_DBD_I;
91 
92 		/* build LSA list, keep space for a possible md5 sum */
93 		for (le = TAILQ_FIRST(&nbr->db_sum_list); le != NULL &&
94 		    ibuf_left(buf) >= MD5_DIGEST_LENGTH + sizeof(struct lsa_hdr);
95 		    le = nle) {
96 			nbr->dd_end = nle = TAILQ_NEXT(le, entry);
97 			if (ibuf_add(buf, le->le_lsa, sizeof(struct lsa_hdr)))
98 				goto fail;
99 		}
100 		break;
101 	case NBR_STA_LOAD:
102 	case NBR_STA_FULL:
103 		if (nbr->dd_master)
104 			bits |= OSPF_DBD_MS;
105 		else
106 			bits &= ~OSPF_DBD_MS;
107 		bits &= ~OSPF_DBD_M;
108 		bits &= ~OSPF_DBD_I;
109 
110 		nbr->dd_more = 0;
111 		break;
112 	default:
113 		fatalx("send_db_description: unknown neighbor state");
114 	}
115 
116 	/* set destination */
117 	dst.sin_family = AF_INET;
118 	dst.sin_len = sizeof(struct sockaddr_in);
119 
120 	switch (nbr->iface->type) {
121 	case IF_TYPE_POINTOPOINT:
122 		inet_aton(AllSPFRouters, &dst.sin_addr);
123 		dd_hdr.iface_mtu = htons(nbr->iface->mtu);
124 		break;
125 	case IF_TYPE_BROADCAST:
126 		dst.sin_addr = nbr->addr;
127 		dd_hdr.iface_mtu = htons(nbr->iface->mtu);
128 		break;
129 	case IF_TYPE_NBMA:
130 	case IF_TYPE_POINTOMULTIPOINT:
131 		/* XXX not supported */
132 		break;
133 	case IF_TYPE_VIRTUALLINK:
134 		dst.sin_addr = nbr->iface->dst;
135 		dd_hdr.iface_mtu = 0;
136 		break;
137 	default:
138 		fatalx("send_db_description: unknown interface type");
139 	}
140 
141 	/* XXX button or not for opaque LSA? */
142 	dd_hdr.opts = area_ospf_options(nbr->iface->area) | OSPF_OPTION_O;
143 	dd_hdr.bits = bits;
144 	dd_hdr.dd_seq_num = htonl(nbr->dd_seq_num);
145 
146 	memcpy(ibuf_seek(buf, sizeof(struct ospf_hdr), sizeof(dd_hdr)),
147 	    &dd_hdr, sizeof(dd_hdr));
148 
149 	/* update authentication and calculate checksum */
150 	if (auth_gen(buf, nbr->iface))
151 		goto fail;
152 
153 	/* transmit packet */
154 	ret = send_packet(nbr->iface, buf, &dst);
155 done:
156 	ibuf_free(buf);
157 	return (ret);
158 fail:
159 	log_warn("send_db_description");
160 	ibuf_free(buf);
161 	return (-1);
162 }
163 
164 void
165 recv_db_description(struct nbr *nbr, char *buf, u_int16_t len)
166 {
167 	struct db_dscrp_hdr	 dd_hdr;
168 	int			 dupe = 0;
169 
170 	if (len < sizeof(dd_hdr)) {
171 		log_warnx("recv_db_description: "
172 		    "bad packet size, neighbor ID %s", inet_ntoa(nbr->id));
173 		return;
174 	}
175 	memcpy(&dd_hdr, buf, sizeof(dd_hdr));
176 	buf += sizeof(dd_hdr);
177 	len -= sizeof(dd_hdr);
178 
179 	/* db description packet sanity checks */
180 	if (ntohs(dd_hdr.iface_mtu) > nbr->iface->mtu) {
181 		log_warnx("recv_db_description: invalid MTU %d sent by "
182 		    "neighbor ID %s, expected %d", ntohs(dd_hdr.iface_mtu),
183 		    inet_ntoa(nbr->id), nbr->iface->mtu);
184 		return;
185 	}
186 
187 	if (nbr->last_rx_options == dd_hdr.opts &&
188 	    nbr->last_rx_bits == dd_hdr.bits &&
189 	    ntohl(dd_hdr.dd_seq_num) == nbr->dd_seq_num - nbr->dd_master ?
190 	    1 : 0) {
191 		log_debug("recv_db_description: dupe from ID %s",
192 		    inet_ntoa(nbr->id));
193 		dupe = 1;
194 	}
195 
196 	switch (nbr->state) {
197 	case NBR_STA_DOWN:
198 	case NBR_STA_ATTEMPT:
199 	case NBR_STA_2_WAY:
200 	case NBR_STA_SNAP:
201 		log_debug("recv_db_description: packet ignored in state %s, "
202 		    "neighbor ID %s", nbr_state_name(nbr->state),
203 		    inet_ntoa(nbr->id));
204 		return;
205 	case NBR_STA_INIT:
206 		/* evaluate dr and bdr after issuing a 2-Way event */
207 		nbr_fsm(nbr, NBR_EVT_2_WAY_RCVD);
208 		if_fsm(nbr->iface, IF_EVT_NBR_CHNG);
209 		if (nbr->state != NBR_STA_XSTRT)
210 			return;
211 		/* FALLTHROUGH */
212 	case NBR_STA_XSTRT:
213 		if (dupe)
214 			return;
215 		nbr->capa_options = dd_hdr.opts;
216 		if ((nbr->capa_options & nbr->options) != nbr->options) {
217 			log_warnx("recv_db_description: neighbor ID %s "
218 			    "sent inconsistent options %x vs. %x",
219 			    inet_ntoa(nbr->id), nbr->capa_options,
220 			    nbr->options);
221 		}
222 		/*
223 		 * check bits: either I,M,MS or only M
224 		 */
225 		if (dd_hdr.bits == (OSPF_DBD_I | OSPF_DBD_M | OSPF_DBD_MS)) {
226 			/* if nbr Router ID is larger than own -> slave */
227 			if ((ntohl(nbr->id.s_addr)) >
228 			    ntohl(ospfe_router_id())) {
229 				/* slave */
230 				nbr->dd_master = 0;
231 				nbr->dd_seq_num = ntohl(dd_hdr.dd_seq_num);
232 
233 				/* event negotiation done */
234 				nbr_fsm(nbr, NBR_EVT_NEG_DONE);
235 			}
236 		} else if (!(dd_hdr.bits & (OSPF_DBD_I | OSPF_DBD_MS))) {
237 			/* M only case: we are master */
238 			if (ntohl(dd_hdr.dd_seq_num) != nbr->dd_seq_num) {
239 				log_warnx("recv_db_description: invalid "
240 				    "seq num, mine %x his %x",
241 				    nbr->dd_seq_num, ntohl(dd_hdr.dd_seq_num));
242 				return;
243 			}
244 			nbr->dd_seq_num++;
245 
246 			/* event negotiation done */
247 			nbr_fsm(nbr, NBR_EVT_NEG_DONE);
248 
249 			/* this packet may already have data so pass it on */
250 			if (len > 0) {
251 				nbr->dd_pending++;
252 				ospfe_imsg_compose_rde(IMSG_DD, nbr->peerid,
253 				    0, buf, len);
254 			}
255 		} else {
256 			/* ignore packet */
257 			log_debug("recv_db_description: packet ignored in "
258 			    "state %s (bad flags), neighbor ID %s",
259 			    nbr_state_name(nbr->state), inet_ntoa(nbr->id));
260 		}
261 		break;
262 	case NBR_STA_XCHNG:
263 	case NBR_STA_LOAD:
264 	case NBR_STA_FULL:
265 		if (dd_hdr.bits & OSPF_DBD_I ||
266 		    !(dd_hdr.bits & OSPF_DBD_MS) == !nbr->dd_master) {
267 			log_warnx("recv_db_description: seq num mismatch, "
268 			    "bad flags");
269 			nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS);
270 			return;
271 		}
272 
273 		if (nbr->last_rx_options != dd_hdr.opts) {
274 			log_warnx("recv_db_description: seq num mismatch, "
275 			    "bad options");
276 			nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS);
277 			return;
278 		}
279 
280 		if (dupe) {
281 			if (!nbr->dd_master)
282 				/* retransmit */
283 				start_db_tx_timer(nbr);
284 			return;
285 		}
286 
287 		if (nbr->state != NBR_STA_XCHNG) {
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 
295 		/* sanity check dd seq number */
296 		if (nbr->dd_master) {
297 			/* master */
298 			if (ntohl(dd_hdr.dd_seq_num) != nbr->dd_seq_num) {
299 				log_warnx("recv_db_description: invalid "
300 				    "seq num, mine %x his %x",
301 				    nbr->dd_seq_num, ntohl(dd_hdr.dd_seq_num));
302 				nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS);
303 				return;
304 			}
305 			nbr->dd_seq_num++;
306 		} else {
307 			/* slave */
308 			if (ntohl(dd_hdr.dd_seq_num) != nbr->dd_seq_num + 1) {
309 				log_warnx("recv_db_description: invalid "
310 				    "seq num, mine %x his %x",
311 				    nbr->dd_seq_num, ntohl(dd_hdr.dd_seq_num));
312 				nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS);
313 				return;
314 			}
315 			nbr->dd_seq_num = ntohl(dd_hdr.dd_seq_num);
316 		}
317 
318 		/* forward to RDE and let it decide which LSAs to request */
319 		if (len > 0) {
320 			nbr->dd_pending++;
321 			ospfe_imsg_compose_rde(IMSG_DD, nbr->peerid, 0,
322 			    buf, len);
323 		}
324 
325 		/* next packet */
326 		db_sum_list_next(nbr);
327 		start_db_tx_timer(nbr);
328 
329 		if (!(dd_hdr.bits & OSPF_DBD_M) &&
330 		    TAILQ_EMPTY(&nbr->db_sum_list))
331 			if (!nbr->dd_master || !nbr->dd_more)
332 				nbr_fsm(nbr, NBR_EVT_XCHNG_DONE);
333 		break;
334 	default:
335 		fatalx("recv_db_description: unknown neighbor state");
336 	}
337 
338 	nbr->last_rx_options = dd_hdr.opts;
339 	nbr->last_rx_bits = dd_hdr.bits;
340 }
341 
342 void
343 db_sum_list_add(struct nbr *nbr, struct lsa_hdr *lsa)
344 {
345 	struct lsa_entry	*le;
346 
347 	if ((le = calloc(1, sizeof(*le))) == NULL)
348 		fatal("db_sum_list_add");
349 
350 	TAILQ_INSERT_TAIL(&nbr->db_sum_list, le, entry);
351 	le->le_lsa = lsa;
352 }
353 
354 void
355 db_sum_list_next(struct nbr *nbr)
356 {
357 	struct lsa_entry	*le;
358 
359 	while ((le = TAILQ_FIRST(&nbr->db_sum_list)) != nbr->dd_end) {
360 		TAILQ_REMOVE(&nbr->db_sum_list, le, entry);
361 		free(le->le_lsa);
362 		free(le);
363 	}
364 }
365 
366 void
367 db_sum_list_clr(struct nbr *nbr)
368 {
369 	nbr->dd_end = NULL;
370 	db_sum_list_next(nbr);
371 }
372 
373 /* timers */
374 /* ARGSUSED */
375 void
376 db_tx_timer(int fd, short event, void *arg)
377 {
378 	struct nbr *nbr = arg;
379 	struct timeval tv;
380 
381 	switch (nbr->state) {
382 	case NBR_STA_DOWN:
383 	case NBR_STA_ATTEMPT:
384 	case NBR_STA_INIT:
385 	case NBR_STA_2_WAY:
386 	case NBR_STA_SNAP:
387 		return ;
388 	case NBR_STA_XSTRT:
389 	case NBR_STA_XCHNG:
390 	case NBR_STA_LOAD:
391 	case NBR_STA_FULL:
392 		send_db_description(nbr);
393 		break;
394 	default:
395 		log_debug("db_tx_timer: unknown neighbor state, "
396 		    "neighbor ID %s", inet_ntoa(nbr->id));
397 		break;
398 	}
399 
400 	/* reschedule db_tx_timer but only in master mode */
401 	if (nbr->dd_master) {
402 		timerclear(&tv);
403 		tv.tv_sec = nbr->iface->rxmt_interval;
404 		if (evtimer_add(&nbr->db_tx_timer, &tv) == -1)
405 			fatal("db_tx_timer");
406 	}
407 }
408 
409 void
410 start_db_tx_timer(struct nbr *nbr)
411 {
412 	struct timeval	tv;
413 
414 	if (nbr == nbr->iface->self)
415 		return;
416 
417 	timerclear(&tv);
418 	if (evtimer_add(&nbr->db_tx_timer, &tv) == -1)
419 		fatal("start_db_tx_timer");
420 }
421 
422 void
423 stop_db_tx_timer(struct nbr *nbr)
424 {
425 	if (nbr == nbr->iface->self)
426 		return;
427 
428 	if (evtimer_del(&nbr->db_tx_timer) == -1)
429 		fatal("stop_db_tx_timer");
430 }
431