xref: /openbsd-src/usr.sbin/ospfd/lsupdate.c (revision de8cc8edbc71bd3e3bc7fbffa27ba0e564c37d8b)
1 /*	$OpenBSD: lsupdate.c,v 1.49 2021/01/19 09:25:53 claudio 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 <arpa/inet.h>
24 
25 #include <stdlib.h>
26 #include <string.h>
27 #include <siphash.h>
28 
29 #include "ospf.h"
30 #include "ospfd.h"
31 #include "log.h"
32 #include "ospfe.h"
33 #include "rde.h"
34 
35 struct ibuf *prepare_ls_update(struct iface *);
36 int	add_ls_update(struct ibuf *, struct iface *, void *, u_int16_t,
37 	    u_int16_t);
38 int	send_ls_update(struct ibuf *, struct iface *, struct in_addr, u_int32_t);
39 
40 void	ls_retrans_list_insert(struct nbr *, struct lsa_entry *);
41 void	ls_retrans_list_remove(struct nbr *, struct lsa_entry *);
42 
43 /* link state update packet handling */
44 int
45 lsa_flood(struct iface *iface, struct nbr *originator, struct lsa_hdr *lsa_hdr,
46     void *data)
47 {
48 	struct nbr		*nbr;
49 	struct lsa_entry	*le = NULL;
50 	int			 queued = 0, dont_ack = 0;
51 	int			 r;
52 
53 	LIST_FOREACH(nbr, &iface->nbr_list, entry) {
54 		if (nbr == iface->self)
55 			continue;
56 		if (!(nbr->state & NBR_STA_FLOOD))
57 			continue;
58 
59 		if (iface->state & IF_STA_DROTHER && !queued)
60 			while ((le = ls_retrans_list_get(iface->self, lsa_hdr)))
61 			    ls_retrans_list_free(iface->self, le);
62 
63 		while ((le = ls_retrans_list_get(nbr, lsa_hdr)))
64 			ls_retrans_list_free(nbr, le);
65 
66 		if (!(nbr->state & NBR_STA_FULL) &&
67 		    (le = ls_req_list_get(nbr, lsa_hdr)) != NULL) {
68 			r = lsa_newer(lsa_hdr, le->le_lsa);
69 			if (r > 0) {
70 				/* to flood LSA is newer than requested */
71 				ls_req_list_free(nbr, le);
72 				/* new needs to be flooded */
73 			} else if (r < 0) {
74 				/* to flood LSA is older than requested */
75 				continue;
76 			} else {
77 				/* LSA are equal */
78 				ls_req_list_free(nbr, le);
79 				continue;
80 			}
81 		}
82 
83 		if (nbr == originator) {
84 			dont_ack++;
85 			continue;
86 		}
87 
88 		/* non DR or BDR router keep all lsa in one retrans list */
89 		if (iface->state & IF_STA_DROTHER) {
90 			if (!queued)
91 				ls_retrans_list_add(iface->self, data,
92 				    iface->rxmt_interval, 0);
93 			queued = 1;
94 		} else {
95 			ls_retrans_list_add(nbr, data, iface->rxmt_interval, 0);
96 			queued = 1;
97 		}
98 	}
99 
100 	if (!queued)
101 		return (0);
102 
103 	if (iface == originator->iface && iface->self != originator) {
104 		if (iface->dr == originator || iface->bdr == originator)
105 			return (0);
106 		if (iface->state & IF_STA_BACKUP)
107 			return (0);
108 		dont_ack++;
109 	}
110 
111 	/*
112 	 * initial flood needs to be queued separately, timeout is zero
113 	 * and oneshot has to be set because the retransimssion queues
114 	 * are already loaded.
115 	 */
116 	switch (iface->type) {
117 	case IF_TYPE_POINTOPOINT:
118 	case IF_TYPE_BROADCAST:
119 		ls_retrans_list_add(iface->self, data, 0, 1);
120 		break;
121 	case IF_TYPE_NBMA:
122 	case IF_TYPE_POINTOMULTIPOINT:
123 	case IF_TYPE_VIRTUALLINK:
124 		LIST_FOREACH(nbr, &iface->nbr_list, entry) {
125 			if (nbr == iface->self)
126 				continue;
127 			if (!(nbr->state & NBR_STA_FLOOD))
128 				continue;
129 			if (!TAILQ_EMPTY(&nbr->ls_retrans_list)) {
130 				le = TAILQ_LAST(&nbr->ls_retrans_list,
131 				    lsa_head);
132 				if (lsa_hdr->type != le->le_lsa->type ||
133 				    lsa_hdr->ls_id != le->le_lsa->ls_id ||
134 				    lsa_hdr->adv_rtr != le->le_lsa->adv_rtr)
135 					continue;
136 			}
137 			ls_retrans_list_add(nbr, data, 0, 1);
138 		}
139 		break;
140 	default:
141 		fatalx("lsa_flood: unknown interface type");
142 	}
143 
144 	return (dont_ack == 2);
145 }
146 
147 struct ibuf *
148 prepare_ls_update(struct iface *iface)
149 {
150 	struct ibuf		*buf;
151 
152 	if ((buf = ibuf_dynamic(iface->mtu - sizeof(struct ip),
153 	    IP_MAXPACKET - sizeof(struct ip))) == NULL)
154 		fatal("prepare_ls_update");
155 
156 	/* OSPF header */
157 	if (gen_ospf_hdr(buf, iface, PACKET_TYPE_LS_UPDATE))
158 		goto fail;
159 
160 	/* reserve space for number of lsa field */
161 	if (ibuf_reserve(buf, sizeof(u_int32_t)) == NULL)
162 		goto fail;
163 
164 	return (buf);
165 fail:
166 	log_warn("prepare_ls_update");
167 	ibuf_free(buf);
168 	return (NULL);
169 }
170 
171 int
172 add_ls_update(struct ibuf *buf, struct iface *iface, void *data, u_int16_t len,
173     u_int16_t older)
174 {
175 	size_t		ageoff;
176 	u_int16_t	age;
177 
178 	if ((size_t)iface->mtu < sizeof(struct ip) + sizeof(struct ospf_hdr) +
179 	    sizeof(u_int32_t) + ibuf_size(buf) + len + MD5_DIGEST_LENGTH) {
180 		/* start new packet unless this is the first LSA to pack */
181 		if (ibuf_size(buf) > sizeof(struct ospf_hdr) +
182 		    sizeof(u_int32_t))
183 			return (0);
184 	}
185 
186 	ageoff = ibuf_size(buf);
187 	if (ibuf_add(buf, data, len)) {
188 		log_warn("add_ls_update");
189 		return (0);
190 	}
191 
192 	/* age LSA before sending it out */
193 	memcpy(&age, data, sizeof(age));
194 	age = ntohs(age);
195 	if ((age += older + iface->transmit_delay) >= MAX_AGE)
196 		age = MAX_AGE;
197 	age = htons(age);
198 	memcpy(ibuf_seek(buf, ageoff, sizeof(age)), &age, sizeof(age));
199 
200 	return (1);
201 }
202 
203 
204 
205 int
206 send_ls_update(struct ibuf *buf, struct iface *iface, struct in_addr addr,
207     u_int32_t nlsa)
208 {
209 	struct sockaddr_in	 dst;
210 
211 	nlsa = htonl(nlsa);
212 	memcpy(ibuf_seek(buf, sizeof(struct ospf_hdr), sizeof(nlsa)),
213 	    &nlsa, sizeof(nlsa));
214 	/* update authentication and calculate checksum */
215 	if (auth_gen(buf, iface))
216 		goto fail;
217 
218 	/* set destination */
219 	dst.sin_family = AF_INET;
220 	dst.sin_len = sizeof(struct sockaddr_in);
221 	dst.sin_addr.s_addr = addr.s_addr;
222 
223 	if (send_packet(iface, buf, &dst) == -1)
224 		goto fail;
225 
226 	ibuf_free(buf);
227 	return (0);
228 fail:
229 	log_warn("%s", __func__);
230 	ibuf_free(buf);
231 	return (-1);
232 }
233 
234 void
235 recv_ls_update(struct nbr *nbr, char *buf, u_int16_t len)
236 {
237 	struct lsa_hdr		 lsa;
238 	u_int32_t		 nlsa;
239 
240 	if (len < sizeof(nlsa)) {
241 		log_warnx("recv_ls_update: bad packet size, neighbor ID %s",
242 		    inet_ntoa(nbr->id));
243 		return;
244 	}
245 	memcpy(&nlsa, buf, sizeof(nlsa));
246 	nlsa = ntohl(nlsa);
247 	buf += sizeof(nlsa);
248 	len -= sizeof(nlsa);
249 
250 	switch (nbr->state) {
251 	case NBR_STA_DOWN:
252 	case NBR_STA_ATTEMPT:
253 	case NBR_STA_INIT:
254 	case NBR_STA_2_WAY:
255 	case NBR_STA_XSTRT:
256 	case NBR_STA_SNAP:
257 		log_debug("recv_ls_update: packet ignored in state %s, "
258 		    "neighbor ID %s", nbr_state_name(nbr->state),
259 		    inet_ntoa(nbr->id));
260 		break;
261 	case NBR_STA_XCHNG:
262 	case NBR_STA_LOAD:
263 	case NBR_STA_FULL:
264 		for (; nlsa > 0 && len > 0; nlsa--) {
265 			if (len < sizeof(lsa)) {
266 				log_warnx("recv_ls_update: bad packet size, "
267 				    "neighbor ID %s", inet_ntoa(nbr->id));
268 				return;
269 			}
270 			memcpy(&lsa, buf, sizeof(lsa));
271 			if (len < ntohs(lsa.len)) {
272 				log_warnx("recv_ls_update: bad packet size, "
273 				    "neighbor ID %s", inet_ntoa(nbr->id));
274 				return;
275 			}
276 			ospfe_imsg_compose_rde(IMSG_LS_UPD, nbr->peerid, 0,
277 			    buf, ntohs(lsa.len));
278 			buf += ntohs(lsa.len);
279 			len -= ntohs(lsa.len);
280 		}
281 		if (nlsa > 0 || len > 0) {
282 			log_warnx("recv_ls_update: bad packet size, "
283 			    "neighbor ID %s", inet_ntoa(nbr->id));
284 			return;
285 		}
286 		break;
287 	default:
288 		fatalx("recv_ls_update: unknown neighbor state");
289 	}
290 }
291 
292 /* link state retransmit list */
293 void
294 ls_retrans_list_add(struct nbr *nbr, struct lsa_hdr *lsa,
295     unsigned short timeout, unsigned short oneshot)
296 {
297 	struct timeval		 tv;
298 	struct lsa_entry	*le;
299 	struct lsa_ref		*ref;
300 
301 	if ((ref = lsa_cache_get(lsa)) == NULL)
302 		fatalx("King Bula sez: somebody forgot to lsa_cache_add");
303 
304 	if ((le = calloc(1, sizeof(*le))) == NULL)
305 		fatal("ls_retrans_list_add");
306 
307 	le->le_ref = ref;
308 	le->le_when = timeout;
309 	le->le_oneshot = oneshot;
310 
311 	ls_retrans_list_insert(nbr, le);
312 
313 	if (!evtimer_pending(&nbr->ls_retrans_timer, NULL)) {
314 		timerclear(&tv);
315 		tv.tv_sec = TAILQ_FIRST(&nbr->ls_retrans_list)->le_when;
316 
317 		if (evtimer_add(&nbr->ls_retrans_timer, &tv) == -1)
318 			fatal("ls_retrans_list_add");
319 	}
320 }
321 
322 int
323 ls_retrans_list_del(struct nbr *nbr, struct lsa_hdr *lsa_hdr)
324 {
325 	struct lsa_entry	*le;
326 
327 	if ((le = ls_retrans_list_get(nbr, lsa_hdr)) == NULL)
328 		return (-1);
329 	/*
330 	 * Compare LSA with the Ack by comparing not only the seq_num and
331 	 * checksum but also the age field.  Since we only care about MAX_AGE
332 	 * vs. non-MAX_AGE LSA, a simple >= comparison is good enough.  This
333 	 * ensures that a LSA withdrawal is not acked by a previous update.
334 	 */
335 	if (lsa_hdr->seq_num == le->le_ref->hdr.seq_num &&
336 	    lsa_hdr->ls_chksum == le->le_ref->hdr.ls_chksum &&
337 	    ntohs(lsa_hdr->age) >= ntohs(le->le_ref->hdr.age)) {
338 		ls_retrans_list_free(nbr, le);
339 		return (0);
340 	}
341 
342 	return (-1);
343 }
344 
345 struct lsa_entry *
346 ls_retrans_list_get(struct nbr *nbr, struct lsa_hdr *lsa_hdr)
347 {
348 	struct lsa_entry	*le;
349 
350 	TAILQ_FOREACH(le, &nbr->ls_retrans_list, entry) {
351 		if ((lsa_hdr->type == le->le_ref->hdr.type) &&
352 		    (lsa_hdr->ls_id == le->le_ref->hdr.ls_id) &&
353 		    (lsa_hdr->adv_rtr == le->le_ref->hdr.adv_rtr))
354 			return (le);
355 	}
356 	return (NULL);
357 }
358 
359 void
360 ls_retrans_list_insert(struct nbr *nbr, struct lsa_entry *new)
361 {
362 	struct lsa_entry	*le;
363 	unsigned short		 when = new->le_when;
364 
365 	TAILQ_FOREACH(le, &nbr->ls_retrans_list, entry) {
366 		if (when < le->le_when) {
367 			new->le_when = when;
368 			TAILQ_INSERT_BEFORE(le, new, entry);
369 			nbr->ls_ret_cnt++;
370 			return;
371 		}
372 		when -= le->le_when;
373 	}
374 	new->le_when = when;
375 	TAILQ_INSERT_TAIL(&nbr->ls_retrans_list, new, entry);
376 	nbr->ls_ret_cnt++;
377 }
378 
379 void
380 ls_retrans_list_remove(struct nbr *nbr, struct lsa_entry *le)
381 {
382 	struct timeval		 tv;
383 	struct lsa_entry	*next = TAILQ_NEXT(le, entry);
384 	int			 reset = 0;
385 
386 	/* adjust timeout of next entry */
387 	if (next)
388 		next->le_when += le->le_when;
389 
390 	if (TAILQ_FIRST(&nbr->ls_retrans_list) == le &&
391 	    evtimer_pending(&nbr->ls_retrans_timer, NULL))
392 		reset = 1;
393 
394 	TAILQ_REMOVE(&nbr->ls_retrans_list, le, entry);
395 	nbr->ls_ret_cnt--;
396 
397 	if (reset && TAILQ_FIRST(&nbr->ls_retrans_list)) {
398 		if (evtimer_del(&nbr->ls_retrans_timer) == -1)
399 			fatal("ls_retrans_list_remove");
400 
401 		timerclear(&tv);
402 		tv.tv_sec = TAILQ_FIRST(&nbr->ls_retrans_list)->le_when;
403 
404 		if (evtimer_add(&nbr->ls_retrans_timer, &tv) == -1)
405 			fatal("ls_retrans_list_remove");
406 	}
407 }
408 
409 void
410 ls_retrans_list_free(struct nbr *nbr, struct lsa_entry *le)
411 {
412 	ls_retrans_list_remove(nbr, le);
413 
414 	lsa_cache_put(le->le_ref, nbr);
415 	free(le);
416 }
417 
418 void
419 ls_retrans_list_clr(struct nbr *nbr)
420 {
421 	struct lsa_entry	*le;
422 
423 	while ((le = TAILQ_FIRST(&nbr->ls_retrans_list)) != NULL)
424 		ls_retrans_list_free(nbr, le);
425 
426 	nbr->ls_ret_cnt = 0;
427 }
428 
429 /* ARGSUSED */
430 void
431 ls_retrans_timer(int fd, short event, void *bula)
432 {
433 	struct timeval		 tv;
434 	struct timespec		 tp;
435 	struct in_addr		 addr;
436 	struct nbr		*nbr = bula;
437 	struct lsa_entry	*le;
438 	struct ibuf		*buf;
439 	time_t			 now;
440 	int			 d;
441 	u_int32_t		 nlsa = 0;
442 
443 	if ((le = TAILQ_FIRST(&nbr->ls_retrans_list)) != NULL)
444 		le->le_when = 0;	/* timer fired */
445 	else
446 		return;			/* queue empty, nothing to do */
447 
448 	clock_gettime(CLOCK_MONOTONIC, &tp);
449 	now = tp.tv_sec;
450 
451 	if (nbr->iface->self == nbr) {
452 		/*
453 		 * oneshot needs to be set for lsa queued for flooding,
454 		 * if oneshot is not set then the lsa needs to be converted
455 		 * because the router switched lately to DR or BDR
456 		 */
457 		if (le->le_oneshot && nbr->iface->state & IF_STA_DRORBDR)
458 			inet_aton(AllSPFRouters, &addr);
459 		else if (nbr->iface->state & IF_STA_DRORBDR) {
460 			/*
461 			 * old retransmission needs to be converted into
462 			 * flood by rerunning the lsa_flood.
463 			 */
464 			lsa_flood(nbr->iface, nbr, &le->le_ref->hdr,
465 			    le->le_ref->data);
466 			ls_retrans_list_free(nbr, le);
467 			/* ls_retrans_list_free retriggers the timer */
468 			return;
469 		} else if (nbr->iface->type == IF_TYPE_POINTOPOINT)
470 			memcpy(&addr, &nbr->addr, sizeof(addr));
471 		else
472 			inet_aton(AllDRouters, &addr);
473 	} else
474 		memcpy(&addr, &nbr->addr, sizeof(addr));
475 
476 	if ((buf = prepare_ls_update(nbr->iface)) == NULL) {
477 		le->le_when = 1;
478 		goto done;
479 	}
480 
481 	while ((le = TAILQ_FIRST(&nbr->ls_retrans_list)) != NULL &&
482 	    le->le_when == 0) {
483 		d = now - le->le_ref->stamp;
484 		if (d < 0)
485 			d = 0;
486 		else if (d > MAX_AGE)
487 			d = MAX_AGE;
488 
489 		if (add_ls_update(buf, nbr->iface, le->le_ref->data,
490 		    le->le_ref->len, d) == 0) {
491 			if (nlsa == 0) {
492 				/* something bad happened retry later */
493 				log_warnx("ls_retrans_timer: sending LS update "
494 				    "to neighbor ID %s failed",
495 				    inet_ntoa(nbr->id));
496 				TAILQ_REMOVE(&nbr->ls_retrans_list, le, entry);
497 				nbr->ls_ret_cnt--;
498 				le->le_when = nbr->iface->rxmt_interval;
499 				ls_retrans_list_insert(nbr, le);
500 			}
501 			break;
502 		}
503 		nlsa++;
504 		if (le->le_oneshot)
505 			ls_retrans_list_free(nbr, le);
506 		else {
507 			TAILQ_REMOVE(&nbr->ls_retrans_list, le, entry);
508 			nbr->ls_ret_cnt--;
509 			le->le_when = nbr->iface->rxmt_interval;
510 			ls_retrans_list_insert(nbr, le);
511 		}
512 	}
513 	if (nlsa)
514 		send_ls_update(buf, nbr->iface, addr, nlsa);
515 	else
516 		ibuf_free(buf);
517 
518 done:
519 	if ((le = TAILQ_FIRST(&nbr->ls_retrans_list)) != NULL) {
520 		timerclear(&tv);
521 		tv.tv_sec = le->le_when;
522 
523 		if (evtimer_add(&nbr->ls_retrans_timer, &tv) == -1)
524 			fatal("ls_retrans_timer");
525 	}
526 }
527 
528 LIST_HEAD(lsa_cache_head, lsa_ref);
529 
530 struct lsa_cache {
531 	struct lsa_cache_head	*hashtbl;
532 	u_int32_t		 hashmask;
533 } lsacache;
534 
535 SIPHASH_KEY lsacachekey;
536 
537 struct lsa_ref		*lsa_cache_look(struct lsa_hdr *);
538 
539 void
540 lsa_cache_init(u_int32_t hashsize)
541 {
542 	u_int32_t        hs, i;
543 
544 	for (hs = 1; hs < hashsize; hs <<= 1)
545 		;
546 	lsacache.hashtbl = calloc(hs, sizeof(struct lsa_cache_head));
547 	if (lsacache.hashtbl == NULL)
548 		fatal("lsa_cache_init");
549 
550 	for (i = 0; i < hs; i++)
551 		LIST_INIT(&lsacache.hashtbl[i]);
552 	arc4random_buf(&lsacachekey, sizeof(lsacachekey));
553 
554 	lsacache.hashmask = hs - 1;
555 }
556 
557 static uint32_t
558 lsa_hash_hdr(const struct lsa_hdr *hdr)
559 {
560 	return SipHash24(&lsacachekey, hdr, sizeof(*hdr));
561 }
562 
563 struct lsa_ref *
564 lsa_cache_add(void *data, u_int16_t len)
565 {
566 	struct lsa_cache_head	*head;
567 	struct lsa_ref		*ref, *old;
568 	struct timespec		 tp;
569 
570 	if ((ref = calloc(1, sizeof(*ref))) == NULL)
571 		fatal("lsa_cache_add");
572 	memcpy(&ref->hdr, data, sizeof(ref->hdr));
573 
574 	if ((old = lsa_cache_look(&ref->hdr))) {
575 		free(ref);
576 		old->refcnt++;
577 		return (old);
578 	}
579 
580 	if ((ref->data = malloc(len)) == NULL)
581 		fatal("lsa_cache_add");
582 	memcpy(ref->data, data, len);
583 
584 	clock_gettime(CLOCK_MONOTONIC, &tp);
585 	ref->stamp = tp.tv_sec;
586 	ref->len = len;
587 	ref->refcnt = 1;
588 
589 	head = &lsacache.hashtbl[lsa_hash_hdr(&ref->hdr) & lsacache.hashmask];
590 	LIST_INSERT_HEAD(head, ref, entry);
591 	return (ref);
592 }
593 
594 struct lsa_ref *
595 lsa_cache_get(struct lsa_hdr *lsa_hdr)
596 {
597 	struct lsa_ref		*ref;
598 
599 	ref = lsa_cache_look(lsa_hdr);
600 	if (ref)
601 		ref->refcnt++;
602 
603 	return (ref);
604 }
605 
606 void
607 lsa_cache_put(struct lsa_ref *ref, struct nbr *nbr)
608 {
609 	if (--ref->refcnt > 0)
610 		return;
611 
612 	if (ntohs(ref->hdr.age) >= MAX_AGE)
613 		ospfe_imsg_compose_rde(IMSG_LS_MAXAGE, nbr->peerid, 0,
614 		    ref->data, sizeof(struct lsa_hdr));
615 
616 	free(ref->data);
617 	LIST_REMOVE(ref, entry);
618 	free(ref);
619 }
620 
621 struct lsa_ref *
622 lsa_cache_look(struct lsa_hdr *lsa_hdr)
623 {
624 	struct lsa_cache_head	*head;
625 	struct lsa_ref		*ref;
626 
627 	head = &lsacache.hashtbl[lsa_hash_hdr(lsa_hdr) & lsacache.hashmask];
628 
629 	LIST_FOREACH(ref, head, entry) {
630 		if (memcmp(&ref->hdr, lsa_hdr, sizeof(*lsa_hdr)) == 0)
631 			/* found match */
632 			return (ref);
633 	}
634 
635 	return (NULL);
636 }
637