xref: /openbsd/usr.sbin/bgpd/rtr_proto.c (revision fba72c10)
1 /*	$OpenBSD: rtr_proto.c,v 1.23 2024/01/05 11:02:57 claudio Exp $ */
2 
3 /*
4  * Copyright (c) 2020 Claudio Jeker <claudio@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 #include <sys/tree.h>
19 #include <errno.h>
20 #include <stdint.h>
21 #include <poll.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 
27 #include "bgpd.h"
28 #include "session.h"
29 #include "log.h"
30 
31 struct rtr_header {
32 	uint8_t		version;
33 	uint8_t		type;
34 	uint16_t	session_id; /* or error code */
35 	uint32_t	length;
36 };
37 
38 #define RTR_MAX_VERSION		2
39 #define RTR_MAX_LEN		2048
40 #define RTR_DEFAULT_REFRESH	3600
41 #define RTR_DEFAULT_RETRY	600
42 #define RTR_DEFAULT_EXPIRE	7200
43 #define RTR_DEFAULT_ACTIVE	60
44 
45 enum rtr_pdu_type {
46 	SERIAL_NOTIFY = 0,
47 	SERIAL_QUERY,
48 	RESET_QUERY,
49 	CACHE_RESPONSE,
50 	IPV4_PREFIX,
51 	IPV6_PREFIX = 6,
52 	END_OF_DATA = 7,
53 	CACHE_RESET = 8,
54 	ROUTER_KEY = 9,
55 	ERROR_REPORT = 10,
56 	ASPA = 11,
57 };
58 
59 #define FLAG_ANNOUNCE	0x1
60 #define FLAG_MASK	FLAG_ANNOUNCE
61 struct rtr_ipv4 {
62 	uint8_t		flags;
63 	uint8_t		prefixlen;
64 	uint8_t		maxlen;
65 	uint8_t		zero;
66 	uint32_t	prefix;
67 	uint32_t	asnum;
68 };
69 
70 struct rtr_ipv6 {
71 	uint8_t		flags;
72 	uint8_t		prefixlen;
73 	uint8_t		maxlen;
74 	uint8_t		zero;
75 	uint32_t	prefix[4];
76 	uint32_t	asnum;
77 };
78 
79 #define FLAG_AFI_V6	0x1
80 #define FLAG_AFI_MASK	FLAG_AFI_V6
81 struct rtr_aspa {
82 	uint8_t		flags;
83 	uint8_t		afi_flags;
84 	uint16_t	cnt;
85 	uint32_t	cas;
86 	/* array of spas with cnt elements follows */
87 };
88 
89 struct rtr_endofdata {
90 	uint32_t	serial;
91 	uint32_t	refresh;
92 	uint32_t	retry;
93 	uint32_t	expire;
94 };
95 
96 enum rtr_event {
97 	RTR_EVNT_START,
98 	RTR_EVNT_CON_OPEN,
99 	RTR_EVNT_CON_CLOSE,
100 	RTR_EVNT_TIMER_REFRESH,
101 	RTR_EVNT_TIMER_RETRY,
102 	RTR_EVNT_TIMER_EXPIRE,
103 	RTR_EVNT_TIMER_ACTIVE,
104 	RTR_EVNT_SEND_ERROR,
105 	RTR_EVNT_SERIAL_NOTIFY,
106 	RTR_EVNT_CACHE_RESPONSE,
107 	RTR_EVNT_END_OF_DATA,
108 	RTR_EVNT_CACHE_RESET,
109 	RTR_EVNT_NO_DATA,
110 	RTR_EVNT_RESET_AND_CLOSE,
111 	RTR_EVNT_UNSUPP_PROTO_VERSION,
112 };
113 
114 static const char *rtr_eventnames[] = {
115 	"start",
116 	"connection open",
117 	"connection closed",
118 	"refresh timer expired",
119 	"retry timer expired",
120 	"expire timer expired",
121 	"activity timer expired",
122 	"sent error",
123 	"serial notify received",
124 	"cache response received",
125 	"end of data received",
126 	"cache reset received",
127 	"no data",
128 	"connection closed with reset",
129 	"unsupported protocol version",
130 };
131 
132 enum rtr_state {
133 	RTR_STATE_CLOSED,
134 	RTR_STATE_ERROR,
135 	/* sessions with a state below this line will poll for incoming data */
136 	RTR_STATE_ESTABLISHED,
137 	RTR_STATE_EXCHANGE,
138 	RTR_STATE_NEGOTIATION,
139 };
140 
141 static const char *rtr_statenames[] = {
142 	"closed",
143 	"error",
144 	"established",
145 	"exchange",
146 	"negotiation",
147 };
148 
149 struct rtr_session {
150 	TAILQ_ENTRY(rtr_session)	entry;
151 	char				descr[PEER_DESCR_LEN];
152 	struct roa_tree			roa_set;
153 	struct aspa_tree		aspa;
154 	struct aspa_tree		aspa_oldv6;
155 	struct ibuf_read		r;
156 	struct msgbuf			w;
157 	struct timer_head		timers;
158 	uint32_t			id;		/* rtr_config id */
159 	uint32_t			serial;
160 	uint32_t			refresh;
161 	uint32_t			retry;
162 	uint32_t			expire;
163 	uint32_t			active;
164 	int				session_id;
165 	int				fd;
166 	int				active_lock;
167 	enum rtr_state			state;
168 	enum reconf_action		reconf_action;
169 	enum rtr_error			last_sent_error;
170 	enum rtr_error			last_recv_error;
171 	char				last_sent_msg[REASON_LEN];
172 	char				last_recv_msg[REASON_LEN];
173 	uint8_t				version;
174 };
175 
176 TAILQ_HEAD(, rtr_session) rtrs = TAILQ_HEAD_INITIALIZER(rtrs);
177 
178 static void	rtr_fsm(struct rtr_session *, enum rtr_event);
179 
180 static const char *
181 log_rtr(struct rtr_session *rs)
182 {
183 	return rs->descr;
184 }
185 
186 static const char *
187 log_rtr_type(enum rtr_pdu_type type)
188 {
189 	static char buf[20];
190 
191 	switch (type) {
192 	case SERIAL_NOTIFY:
193 		return "serial notify";
194 	case SERIAL_QUERY:
195 		return "serial query";
196 	case RESET_QUERY:
197 		return "reset query";
198 	case CACHE_RESPONSE:
199 		return "cache response";
200 	case IPV4_PREFIX:
201 		return "IPv4 prefix";
202 	case IPV6_PREFIX:
203 		return "IPv6 prefix";
204 	case END_OF_DATA:
205 		return "end of data";
206 	case CACHE_RESET:
207 		return "cache reset";
208 	case ROUTER_KEY:
209 		return "router key";
210 	case ERROR_REPORT:
211 		return "error report";
212 	case ASPA:
213 		return "aspa pdu";
214 	default:
215 		snprintf(buf, sizeof(buf), "unknown %u", type);
216 		return buf;
217 	}
218 };
219 
220 static void
221 rtr_reset_cache(struct rtr_session *rs)
222 {
223 	/* reset session */
224 	rs->session_id = -1;
225 	timer_stop(&rs->timers, Timer_Rtr_Expire);
226 	free_roatree(&rs->roa_set);
227 	free_aspatree(&rs->aspa);
228 	free_aspatree(&rs->aspa_oldv6);
229 }
230 
231 static struct ibuf *
232 rtr_newmsg(struct rtr_session *rs, enum rtr_pdu_type type, uint32_t len,
233     uint16_t session_id)
234 {
235 	struct ibuf *buf;
236 	int saved_errno;
237 
238 	if (len > RTR_MAX_LEN) {
239 		errno = ERANGE;
240 		return NULL;
241 	}
242 	len += sizeof(struct rtr_header);
243 	if ((buf = ibuf_open(len)) == NULL)
244 		goto fail;
245 	if (ibuf_add_n8(buf, rs->version) == -1)
246 		goto fail;
247 	if (ibuf_add_n8(buf, type) == -1)
248 		goto fail;
249 	if (ibuf_add_n16(buf, session_id) == -1)
250 		goto fail;
251 	if (ibuf_add_n32(buf, len) == -1)
252 		goto fail;
253 
254 	return buf;
255 
256  fail:
257 	saved_errno = errno;
258 	ibuf_free(buf);
259 	errno = saved_errno;
260 	return NULL;
261 }
262 
263 /*
264  * Try to send an error PDU to cache, put connection into error
265  * state.
266  */
267 static void
268 rtr_send_error(struct rtr_session *rs, enum rtr_error err, char *msg,
269     struct ibuf *pdu)
270 {
271 	struct ibuf *buf;
272 	size_t len = 0, mlen = 0;
273 
274 	rs->last_sent_error = err;
275 	if (msg != NULL) {
276 		mlen = strlen(msg);
277 		strlcpy(rs->last_sent_msg, msg, sizeof(rs->last_sent_msg));
278 	} else
279 		memset(rs->last_sent_msg, 0, sizeof(rs->last_sent_msg));
280 
281 	if (pdu != NULL) {
282 		ibuf_rewind(pdu);
283 		len = ibuf_size(pdu);
284 	}
285 
286 	buf = rtr_newmsg(rs, ERROR_REPORT, 2 * sizeof(uint32_t) + len + mlen,
287 	    err);
288 	if (buf == NULL)
289 		goto fail;
290 	if (ibuf_add_n32(buf, len) == -1)
291 		goto fail;
292 	if (pdu != NULL) {
293 		if (ibuf_add_ibuf(buf, pdu) == -1)
294 			goto fail;
295 	}
296 	if (ibuf_add_n32(buf, mlen) == -1)
297 		goto fail;
298 	if (ibuf_add(buf, msg, mlen) == -1)
299 		goto fail;
300 	ibuf_close(&rs->w, buf);
301 
302 	log_warnx("rtr %s: sending error: %s%s%s", log_rtr(rs),
303 	    log_rtr_error(err), msg ? ": " : "", msg ? msg : "");
304 
305 	rtr_fsm(rs, RTR_EVNT_SEND_ERROR);
306 	return;
307 
308  fail:
309 	log_warn("rtr %s: send error report", log_rtr(rs));
310 	ibuf_free(buf);
311 }
312 
313 static void
314 rtr_send_reset_query(struct rtr_session *rs)
315 {
316 	struct ibuf *buf;
317 
318 	buf = rtr_newmsg(rs, RESET_QUERY, 0, 0);
319 	if (buf == NULL) {
320 		log_warn("rtr %s: send reset query", log_rtr(rs));
321 		rtr_send_error(rs, INTERNAL_ERROR, "out of memory", NULL);
322 		return;
323 	}
324 	ibuf_close(&rs->w, buf);
325 }
326 
327 static void
328 rtr_send_serial_query(struct rtr_session *rs)
329 {
330 	struct ibuf *buf;
331 
332 	buf = rtr_newmsg(rs, SERIAL_QUERY, sizeof(uint32_t), rs->session_id);
333 	if (buf == NULL)
334 		goto fail;
335 	if (ibuf_add_n32(buf, rs->serial) == -1)
336 		goto fail;
337 	ibuf_close(&rs->w, buf);
338 	return;
339 
340  fail:
341 	log_warn("rtr %s: send serial query", log_rtr(rs));
342 	ibuf_free(buf);
343 	rtr_send_error(rs, INTERNAL_ERROR, "out of memory", NULL);
344 }
345 
346 /*
347  * Validate the common rtr header (first 8 bytes) including the
348  * included length field.
349  * Returns -1 on failure. On success msgtype and msglen are set
350  * and the function return 0.
351  */
352 static int
353 rtr_parse_header(struct rtr_session *rs, struct ibuf *hdr,
354     size_t *msglen, enum rtr_pdu_type *msgtype)
355 {
356 	struct rtr_header rh;
357 	uint32_t len = 16;	/* default for ERROR_REPORT */
358 	int session_id;
359 
360 	if (ibuf_get(hdr, &rh, sizeof(rh)) == -1)
361 		fatal("%s: ibuf_get", __func__);
362 
363 	if (rh.version != rs->version && rh.type != ERROR_REPORT) {
364  badversion:
365 		log_warnx("rtr %s: received %s message: unexpected version %d",
366 		    log_rtr(rs), log_rtr_type(rh.type), rh.version);
367 		rtr_send_error(rs, UNEXP_PROTOCOL_VERS, NULL, hdr);
368 		return -1;
369 	}
370 
371 	*msgtype = rh.type;
372 	*msglen = ntohl(rh.length);
373 
374 	switch (rh.type) {
375 	case SERIAL_NOTIFY:
376 		session_id = rs->session_id;
377 		len = 12;
378 		break;
379 	case CACHE_RESPONSE:
380 		/* set session_id if not yet happened */
381 		if (rs->session_id == -1)
382 			rs->session_id = ntohs(rh.session_id);
383 		session_id = rs->session_id;
384 		len = 8;
385 		break;
386 	case IPV4_PREFIX:
387 		session_id = 0;
388 		len = 20;
389 		break;
390 	case IPV6_PREFIX:
391 		session_id = 0;
392 		len = 32;
393 		break;
394 	case END_OF_DATA:
395 		session_id = rs->session_id;
396 		len = 24;
397 		break;
398 	case CACHE_RESET:
399 		session_id = 0;
400 		len = 8;
401 		break;
402 	case ROUTER_KEY:
403 		if (rs->version < 1)
404 			goto badversion;
405 		len = 36;	/* XXX probably too small, but we ignore it */
406 		/* FALLTHROUGH */
407 	case ERROR_REPORT:
408 		if (*msglen > RTR_MAX_LEN) {
409  toobig:
410 			log_warnx("rtr %s: received %s: msg too big: %zu byte",
411 			    log_rtr(rs), log_rtr_type(rh.type), *msglen);
412 			rtr_send_error(rs, CORRUPT_DATA, "too big", hdr);
413 			return -1;
414 		}
415 		if (*msglen < len) {
416  toosmall:
417 			log_warnx("rtr %s: received %s: msg too small: "
418 			    "%zu byte", log_rtr(rs), log_rtr_type(rh.type),
419 			    *msglen);
420 			rtr_send_error(rs, CORRUPT_DATA, "too small", hdr);
421 			return -1;
422 		}
423 		/*
424 		 * session_id check omitted since ROUTER_KEY and ERROR_REPORT
425 		 * use the field for different things.
426 		 */
427 		return 0;
428 	case ASPA:
429 		if (rs->version < 2)
430 			goto badversion;
431 		session_id = 0;
432 		/* unlike all other messages ASPA is variable sized */
433 		if (*msglen > RTR_MAX_LEN)
434 			goto toobig;
435 		if (*msglen < sizeof(struct rtr_aspa))
436 			goto toosmall;
437 		/* len must be a multiple of 4 */
438 		len = *msglen & ~0x3;
439 		break;
440 	default:
441 		log_warnx("rtr %s: received unknown message: type %s",
442 		    log_rtr(rs), log_rtr_type(rh.type));
443 		rtr_send_error(rs, UNSUPP_PDU_TYPE, NULL, hdr);
444 		return -1;
445 	}
446 
447 	if (len != *msglen) {
448 		log_warnx("rtr %s: received %s: illegal len: %zu byte not %u",
449 		    log_rtr(rs), log_rtr_type(rh.type), *msglen, len);
450 		rtr_send_error(rs, CORRUPT_DATA, "bad length", hdr);
451 		return -1;
452 	}
453 
454 	if (session_id != ntohs(rh.session_id)) {
455 		/* ignore SERIAL_NOTIFY during startup */
456 		if (rs->session_id == -1 && rh.type == SERIAL_NOTIFY)
457 			return 0;
458 
459 		log_warnx("rtr %s: received %s: bad session_id: %d != %d",
460 		    log_rtr(rs), log_rtr_type(rh.type), ntohs(rh.session_id),
461 		    session_id);
462 		rtr_send_error(rs, CORRUPT_DATA, "bad session_id", hdr);
463 		return -1;
464 	}
465 
466 	return 0;
467 }
468 
469 static int
470 rtr_parse_notify(struct rtr_session *rs, struct ibuf *pdu)
471 {
472 	if (rs->state == RTR_STATE_EXCHANGE ||
473 	    rs->state == RTR_STATE_NEGOTIATION) {
474 		log_warnx("rtr %s: received %s: while in state %s (ignored)",
475 		    log_rtr(rs), log_rtr_type(SERIAL_NOTIFY),
476 		    rtr_statenames[rs->state]);
477 		return 0;
478 	}
479 
480 	rtr_fsm(rs, RTR_EVNT_SERIAL_NOTIFY);
481 	return 0;
482 }
483 
484 static int
485 rtr_parse_cache_response(struct rtr_session *rs, struct ibuf *pdu)
486 {
487 	if (rs->state != RTR_STATE_ESTABLISHED &&
488 	    rs->state != RTR_STATE_NEGOTIATION) {
489 		log_warnx("rtr %s: received %s: out of context",
490 		    log_rtr(rs), log_rtr_type(CACHE_RESPONSE));
491 		return -1;
492 	}
493 
494 	rtr_fsm(rs, RTR_EVNT_CACHE_RESPONSE);
495 	return 0;
496 }
497 
498 static int
499 rtr_parse_ipv4_prefix(struct rtr_session *rs, struct ibuf *pdu)
500 {
501 	struct rtr_ipv4 ip4;
502 	struct roa *roa;
503 
504 	if (ibuf_skip(pdu, sizeof(struct rtr_header)) == -1 ||
505 	    ibuf_get(pdu, &ip4, sizeof(ip4)) == -1) {
506 		log_warnx("rtr %s: received %s: bad pdu len",
507 		    log_rtr(rs), log_rtr_type(IPV4_PREFIX));
508 		rtr_send_error(rs, CORRUPT_DATA, "bad len", pdu);
509 		return -1;
510 	}
511 
512 	if (rs->state != RTR_STATE_EXCHANGE) {
513 		log_warnx("rtr %s: received %s: out of context",
514 		    log_rtr(rs), log_rtr_type(IPV4_PREFIX));
515 		rtr_send_error(rs, CORRUPT_DATA, NULL, pdu);
516 		return -1;
517 	}
518 
519 	if (ip4.prefixlen > 32 || ip4.maxlen > 32 ||
520 	    ip4.prefixlen > ip4.maxlen) {
521 		log_warnx("rtr: %s: received %s: bad prefixlen / maxlen",
522 		    log_rtr(rs), log_rtr_type(IPV4_PREFIX));
523 		rtr_send_error(rs, CORRUPT_DATA, "bad prefixlen / maxlen", pdu);
524 		return -1;
525 	}
526 
527 	if ((roa = calloc(1, sizeof(*roa))) == NULL) {
528 		log_warn("rtr %s: received %s",
529 		    log_rtr(rs), log_rtr_type(IPV4_PREFIX));
530 		rtr_send_error(rs, INTERNAL_ERROR, "out of memory", NULL);
531 		return -1;
532 	}
533 	roa->aid = AID_INET;
534 	roa->prefixlen = ip4.prefixlen;
535 	roa->maxlen = ip4.maxlen;
536 	roa->asnum = ntohl(ip4.asnum);
537 	roa->prefix.inet.s_addr = ip4.prefix;
538 
539 	if (ip4.flags & FLAG_ANNOUNCE) {
540 		if (RB_INSERT(roa_tree, &rs->roa_set, roa) != NULL) {
541 			log_warnx("rtr %s: received %s: duplicate announcement",
542 			    log_rtr(rs), log_rtr_type(IPV4_PREFIX));
543 			rtr_send_error(rs, DUP_REC_RECV, NULL, pdu);
544 			free(roa);
545 			return -1;
546 		}
547 	} else {
548 		struct roa *r;
549 
550 		r = RB_FIND(roa_tree, &rs->roa_set, roa);
551 		if (r == NULL) {
552 			log_warnx("rtr %s: received %s: unknown withdrawal",
553 			    log_rtr(rs), log_rtr_type(IPV4_PREFIX));
554 			rtr_send_error(rs, UNK_REC_WDRAWL, NULL, pdu);
555 			free(roa);
556 			return -1;
557 		}
558 		RB_REMOVE(roa_tree, &rs->roa_set, r);
559 		free(r);
560 		free(roa);
561 	}
562 
563 	return 0;
564 }
565 
566 static int
567 rtr_parse_ipv6_prefix(struct rtr_session *rs, struct ibuf *pdu)
568 {
569 	struct rtr_ipv6 ip6;
570 	struct roa *roa;
571 
572 	if (ibuf_skip(pdu, sizeof(struct rtr_header)) == -1 ||
573 	    ibuf_get(pdu, &ip6, sizeof(ip6)) == -1) {
574 		log_warnx("rtr %s: received %s: bad pdu len",
575 		    log_rtr(rs), log_rtr_type(IPV6_PREFIX));
576 		rtr_send_error(rs, CORRUPT_DATA, "bad len", pdu);
577 		return -1;
578 	}
579 
580 	if (rs->state != RTR_STATE_EXCHANGE) {
581 		log_warnx("rtr %s: received %s: out of context",
582 		    log_rtr(rs), log_rtr_type(IPV6_PREFIX));
583 		rtr_send_error(rs, CORRUPT_DATA, NULL, pdu);
584 		return -1;
585 	}
586 
587 	if (ip6.prefixlen > 128 || ip6.maxlen > 128 ||
588 	    ip6.prefixlen > ip6.maxlen) {
589 		log_warnx("rtr: %s: received %s: bad prefixlen / maxlen",
590 		    log_rtr(rs), log_rtr_type(IPV6_PREFIX));
591 		rtr_send_error(rs, CORRUPT_DATA, "bad prefixlen / maxlen", pdu);
592 		return -1;
593 	}
594 
595 	if ((roa = calloc(1, sizeof(*roa))) == NULL) {
596 		log_warn("rtr %s: received %s",
597 		    log_rtr(rs), log_rtr_type(IPV6_PREFIX));
598 		rtr_send_error(rs, INTERNAL_ERROR, "out of memory", NULL);
599 		return -1;
600 	}
601 	roa->aid = AID_INET6;
602 	roa->prefixlen = ip6.prefixlen;
603 	roa->maxlen = ip6.maxlen;
604 	roa->asnum = ntohl(ip6.asnum);
605 	memcpy(&roa->prefix.inet6, ip6.prefix, sizeof(roa->prefix.inet6));
606 
607 	if (ip6.flags & FLAG_ANNOUNCE) {
608 		if (RB_INSERT(roa_tree, &rs->roa_set, roa) != NULL) {
609 			log_warnx("rtr %s: received %s: duplicate announcement",
610 			    log_rtr(rs), log_rtr_type(IPV6_PREFIX));
611 			rtr_send_error(rs, DUP_REC_RECV, NULL, pdu);
612 			free(roa);
613 			return -1;
614 		}
615 	} else {
616 		struct roa *r;
617 
618 		r = RB_FIND(roa_tree, &rs->roa_set, roa);
619 		if (r == NULL) {
620 			log_warnx("rtr %s: received %s: unknown withdrawal",
621 			    log_rtr(rs), log_rtr_type(IPV6_PREFIX));
622 			rtr_send_error(rs, UNK_REC_WDRAWL, NULL, pdu);
623 			free(roa);
624 			return -1;
625 		}
626 		RB_REMOVE(roa_tree, &rs->roa_set, r);
627 		free(r);
628 		free(roa);
629 	}
630 	return 0;
631 }
632 
633 static int
634 rtr_parse_aspa(struct rtr_session *rs, struct ibuf *pdu)
635 {
636 	struct rtr_aspa rtr_aspa;
637 	struct aspa_tree *aspatree;
638 	struct aspa_set *aspa, *a;
639 	uint16_t cnt, i;
640 
641 	if (ibuf_skip(pdu, sizeof(struct rtr_header)) == -1 ||
642 	    ibuf_get(pdu, &rtr_aspa, sizeof(rtr_aspa)) == -1) {
643 		log_warnx("rtr %s: received %s: bad pdu len",
644 		    log_rtr(rs), log_rtr_type(ASPA));
645 		rtr_send_error(rs, CORRUPT_DATA, "bad len", pdu);
646 		return -1;
647 	}
648 	cnt = ntohs(rtr_aspa.cnt);
649 	if (ibuf_size(pdu) != cnt * sizeof(uint32_t)) {
650 		log_warnx("rtr %s: received %s: bad pdu len",
651 		    log_rtr(rs), log_rtr_type(ASPA));
652 		rtr_send_error(rs, CORRUPT_DATA, "bad len", pdu);
653 		return -1;
654 	}
655 
656 	if (rs->state != RTR_STATE_EXCHANGE) {
657 		log_warnx("rtr %s: received %s: out of context",
658 		    log_rtr(rs), log_rtr_type(ASPA));
659 		rtr_send_error(rs, CORRUPT_DATA, NULL, pdu);
660 		return -1;
661 	}
662 
663 	if (rtr_aspa.afi_flags & FLAG_AFI_V6) {
664 		aspatree = &rs->aspa_oldv6;
665 	} else {
666 		aspatree = &rs->aspa;
667 	}
668 
669 	/* create aspa_set entry from the rtr aspa pdu */
670 	if ((aspa = calloc(1, sizeof(*aspa))) == NULL) {
671 		log_warn("rtr %s: received %s",
672 		    log_rtr(rs), log_rtr_type(ASPA));
673 		rtr_send_error(rs, INTERNAL_ERROR, "out of memory", NULL);
674 		return -1;
675 	}
676 	aspa->as = ntohl(rtr_aspa.cas);
677 	aspa->num = cnt;
678 	if (cnt > 0) {
679 		if ((aspa->tas = calloc(cnt, sizeof(uint32_t))) == NULL) {
680 			free_aspa(aspa);
681 			log_warn("rtr %s: received %s",
682 			    log_rtr(rs), log_rtr_type(ASPA));
683 			rtr_send_error(rs, INTERNAL_ERROR, "out of memory",
684 			    NULL);
685 			return -1;
686 		}
687 		for (i = 0; i < cnt; i++) {
688 			if (ibuf_get_n32(pdu, &aspa->tas[i]) == -1) {
689 				log_warnx("rtr %s: received %s: bad pdu len",
690 				    log_rtr(rs), log_rtr_type(ASPA));
691 				rtr_send_error(rs, CORRUPT_DATA, "bad len",
692 				    pdu);
693 				return -1;
694 			}
695 		}
696 	}
697 
698 	if (rtr_aspa.flags & FLAG_ANNOUNCE) {
699 		a = RB_INSERT(aspa_tree, aspatree, aspa);
700 		if (a != NULL) {
701 			RB_REMOVE(aspa_tree, aspatree, a);
702 			free_aspa(a);
703 
704 			if (RB_INSERT(aspa_tree, aspatree, aspa) != NULL) {
705 				log_warnx("rtr %s: received %s: corrupt tree",
706 				    log_rtr(rs), log_rtr_type(ASPA));
707 				rtr_send_error(rs, INTERNAL_ERROR,
708 				    "corrupt aspa tree", NULL);
709 				free_aspa(aspa);
710 				return -1;
711 			}
712 		}
713 	} else {
714 		a = RB_FIND(aspa_tree, aspatree, aspa);
715 		if (a == NULL) {
716 			log_warnx("rtr %s: received %s: unknown withdrawal",
717 			    log_rtr(rs), log_rtr_type(ASPA));
718 			rtr_send_error(rs, UNK_REC_WDRAWL, NULL, pdu);
719 			free_aspa(aspa);
720 			return -1;
721 		}
722 		RB_REMOVE(aspa_tree, aspatree, a);
723 		free_aspa(a);
724 		free_aspa(aspa);
725 	}
726 
727 	return 0;
728 }
729 
730 static int
731 rtr_parse_end_of_data(struct rtr_session *rs, struct ibuf *pdu)
732 {
733 	struct rtr_endofdata eod;
734 	uint32_t t;
735 
736 	if (ibuf_skip(pdu, sizeof(struct rtr_header)) == -1 ||
737 	    ibuf_get(pdu, &eod, sizeof(eod)) == -1) {
738 		log_warnx("rtr %s: received %s: bad pdu len",
739 		    log_rtr(rs), log_rtr_type(END_OF_DATA));
740 		return -1;
741 	}
742 
743 	if (rs->state != RTR_STATE_EXCHANGE) {
744 		log_warnx("rtr %s: received %s: out of context",
745 		    log_rtr(rs), log_rtr_type(END_OF_DATA));
746 		return -1;
747 	}
748 
749 	rs->serial = ntohl(eod.serial);
750 	/* validate timer values to be in the right range */
751 	t = ntohl(eod.refresh);
752 	if (t < 1 || t > 86400)
753 		goto bad;
754 	rs->refresh = t;
755 	t = ntohl(eod.retry);
756 	if (t < 1 || t > 7200)
757 		goto bad;
758 	rs->retry = t;
759 	t = ntohl(eod.expire);
760 	if (t < 600 || t > 172800)
761 		goto bad;
762 	if (t <= rs->retry || t <= rs->refresh)
763 		goto bad;
764 	rs->expire = t;
765 
766 	rtr_fsm(rs, RTR_EVNT_END_OF_DATA);
767 	return 0;
768 
769 bad:
770 	log_warnx("rtr %s: received %s: bad timeout values",
771 	    log_rtr(rs), log_rtr_type(END_OF_DATA));
772 	return -1;
773 }
774 
775 static int
776 rtr_parse_cache_reset(struct rtr_session *rs, struct ibuf *pdu)
777 {
778 	if (rs->state != RTR_STATE_ESTABLISHED) {
779 		log_warnx("rtr %s: received %s: out of context",
780 		    log_rtr(rs), log_rtr_type(CACHE_RESET));
781 		return -1;
782 	}
783 
784 	rtr_fsm(rs, RTR_EVNT_CACHE_RESET);
785 	return 0;
786 }
787 
788 static char *
789 ibuf_get_string(struct ibuf *buf, size_t len)
790 {
791 	char *str;
792 
793 	if (ibuf_size(buf) < len) {
794 		errno = EBADMSG;
795 		return (NULL);
796 	}
797 	str = strndup(ibuf_data(buf), len);
798 	if (str == NULL)
799 		return (NULL);
800 	ibuf_skip(buf, len);
801 	return (str);
802 }
803 
804 /*
805  * Parse an Error Response message. This function behaves a bit different
806  * from other parse functions since on error the connection needs to be
807  * dropped without sending an error response back.
808  */
809 static int
810 rtr_parse_error(struct rtr_session *rs, struct ibuf *pdu)
811 {
812 	struct rtr_header rh;
813 	struct ibuf err_pdu;
814 	uint32_t pdu_len, msg_len;
815 	char *str = NULL;
816 	uint16_t errcode;
817 	int rv = -1;
818 
819 	if (ibuf_get(pdu, &rh, sizeof(rh)) == -1)
820 		goto fail;
821 	errcode = ntohs(rh.session_id);
822 
823 	if (ibuf_get_n32(pdu, &pdu_len) == -1)
824 		goto fail;
825 
826 	/* for now just ignore the embedded pdu */
827 	if (ibuf_get_ibuf(pdu, pdu_len, &err_pdu) == -1)
828 		goto fail;
829 
830 	if (ibuf_get_n32(pdu, &msg_len) == -1)
831 		goto fail;
832 
833 	/* optional error msg */
834 	if (msg_len != 0)
835 		if ((str = ibuf_get_string(pdu, msg_len)) == NULL)
836 			goto fail;
837 
838 	log_warnx("rtr %s: received error: %s%s%s", log_rtr(rs),
839 	    log_rtr_error(errcode), str ? ": " : "", str ? str : "");
840 
841 	if (errcode == NO_DATA_AVAILABLE) {
842 		rtr_fsm(rs, RTR_EVNT_NO_DATA);
843 		rv = 0;
844 	} else if (errcode == UNSUPP_PROTOCOL_VERS)
845 		rtr_fsm(rs, RTR_EVNT_UNSUPP_PROTO_VERSION);
846 	else
847 		rtr_fsm(rs, RTR_EVNT_RESET_AND_CLOSE);
848 
849 	rs->last_recv_error = errcode;
850 	if (str)
851 		strlcpy(rs->last_recv_msg, str, sizeof(rs->last_recv_msg));
852 	else
853 		memset(rs->last_recv_msg, 0, sizeof(rs->last_recv_msg));
854 
855 	free(str);
856 	return rv;
857 
858  fail:
859 	log_warnx("rtr %s: received %s: bad encoding", log_rtr(rs),
860 	    log_rtr_type(ERROR_REPORT));
861 	rtr_fsm(rs, RTR_EVNT_RESET_AND_CLOSE);
862 	return -1;
863 }
864 
865 /*
866  * Try to process received rtr message, it is possible that not a full
867  * message is in the buffer. In that case stop, once new data is available
868  * a retry will be done.
869  */
870 static void
871 rtr_process_msg(struct rtr_session *rs)
872 {
873 	struct ibuf rbuf, hdr, msg;
874 	size_t msglen;
875 	enum rtr_pdu_type msgtype;
876 
877 	ibuf_from_buffer(&rbuf, rs->r.buf, rs->r.wpos);
878 
879 	for (;;) {
880 		if (ibuf_size(&rbuf) < sizeof(struct rtr_header))
881 			break;
882 
883 		/* parse header */
884 		ibuf_from_buffer(&hdr, ibuf_data(&rbuf),
885 		    sizeof(struct rtr_header));
886 		if (rtr_parse_header(rs, &hdr, &msglen, &msgtype) == -1)
887 			return;
888 
889 		/* extract message */
890 		if (ibuf_get_ibuf(&rbuf, msglen, &msg) == -1)
891 			break;
892 
893 		switch (msgtype) {
894 		case SERIAL_NOTIFY:
895 			if (rtr_parse_notify(rs, &msg) == -1) {
896 				rtr_send_error(rs, CORRUPT_DATA, NULL, &msg);
897 				return;
898 			}
899 			break;
900 		case CACHE_RESPONSE:
901 			if (rtr_parse_cache_response(rs, &msg) == -1) {
902 				rtr_send_error(rs, CORRUPT_DATA, NULL, &msg);
903 				return;
904 			}
905 			break;
906 		case IPV4_PREFIX:
907 			if (rtr_parse_ipv4_prefix(rs, &msg) == -1) {
908 				return;
909 			}
910 			break;
911 		case IPV6_PREFIX:
912 			if (rtr_parse_ipv6_prefix(rs, &msg) == -1) {
913 				return;
914 			}
915 			break;
916 		case END_OF_DATA:
917 			if (rtr_parse_end_of_data(rs, &msg) == -1) {
918 				rtr_send_error(rs, CORRUPT_DATA, NULL, &msg);
919 				return;
920 			}
921 			break;
922 		case CACHE_RESET:
923 			if (rtr_parse_cache_reset(rs, &msg) == -1) {
924 				rtr_send_error(rs, CORRUPT_DATA, NULL, &msg);
925 				return;
926 			}
927 			break;
928 		case ROUTER_KEY:
929 			/* silently ignore router key */
930 			break;
931 		case ERROR_REPORT:
932 			if (rtr_parse_error(rs, &msg) == -1) {
933 				/* no need to send back an error */
934 				return;
935 			}
936 			break;
937 		case ASPA:
938 			if (rtr_parse_aspa(rs, &msg) == -1) {
939 				return;
940 			}
941 			break;
942 		default:
943 			log_warnx("rtr %s: received %s: unexpected pdu type",
944 			    log_rtr(rs), log_rtr_type(msgtype));
945 			rtr_send_error(rs, INVALID_REQUEST, NULL, &msg);
946 			return;
947 		}
948 	}
949 
950 	memmove(&rs->r.buf, ibuf_data(&rbuf), ibuf_size(&rbuf));
951 	rs->r.wpos = ibuf_size(&rbuf);
952 }
953 
954 /*
955  * Simple FSM for RTR sessions
956  */
957 static void
958 rtr_fsm(struct rtr_session *rs, enum rtr_event event)
959 {
960 	enum rtr_state prev_state = rs->state;
961 
962 	switch (event) {
963 	case RTR_EVNT_UNSUPP_PROTO_VERSION:
964 		if (rs->state == RTR_STATE_NEGOTIATION) {
965 			if (rs->version > 0)
966 				rs->version--;
967 			else {
968 				/*
969 				 * can't downgrade anymore, fail connection
970 				 * RFC requires to send the error with our
971 				 * highest version number.
972 				 */
973 				rs->version = RTR_MAX_VERSION;
974 				log_warnx("rtr %s: version negotiation failed",
975 				    log_rtr(rs));
976 				rtr_send_error(rs, UNSUPP_PROTOCOL_VERS,
977 				    NULL, NULL);
978 				return;
979 			}
980 
981 			if (rs->fd != -1) {
982 				/* flush buffers */
983 				msgbuf_clear(&rs->w);
984 				rs->r.wpos = 0;
985 				close(rs->fd);
986 				rs->fd = -1;
987 			}
988 
989 			/* retry connection with lower version */
990 			timer_set(&rs->timers, Timer_Rtr_Retry, rs->retry);
991 			rtr_imsg_compose(IMSG_SOCKET_CONN, rs->id, 0, NULL, 0);
992 			break;
993 		}
994 		/* FALLTHROUGH */
995 	case RTR_EVNT_RESET_AND_CLOSE:
996 		rtr_reset_cache(rs);
997 		rtr_recalc();
998 		/* FALLTHROUGH */
999 	case RTR_EVNT_CON_CLOSE:
1000 		if (rs->state == RTR_STATE_NEGOTIATION) {
1001 			/* consider any close event as a version failure. */
1002 			rtr_fsm(rs, RTR_EVNT_UNSUPP_PROTO_VERSION);
1003 			break;
1004 		}
1005 		if (rs->fd != -1) {
1006 			/* flush buffers */
1007 			msgbuf_clear(&rs->w);
1008 			rs->r.wpos = 0;
1009 			close(rs->fd);
1010 			rs->fd = -1;
1011 		}
1012 		rs->state = RTR_STATE_CLOSED;
1013 		/* try to reopen session */
1014 		timer_set(&rs->timers, Timer_Rtr_Retry,
1015 		    arc4random_uniform(10));
1016 		break;
1017 	case RTR_EVNT_START:
1018 	case RTR_EVNT_TIMER_RETRY:
1019 		switch (rs->state) {
1020 		case RTR_STATE_ERROR:
1021 			rtr_fsm(rs, RTR_EVNT_CON_CLOSE);
1022 			return;
1023 		case RTR_STATE_CLOSED:
1024 			timer_set(&rs->timers, Timer_Rtr_Retry, rs->retry);
1025 			rtr_imsg_compose(IMSG_SOCKET_CONN, rs->id, 0, NULL, 0);
1026 			return;
1027 		default:
1028 			break;
1029 		}
1030 		/* FALLTHROUGH */
1031 	case RTR_EVNT_CON_OPEN:
1032 		timer_stop(&rs->timers, Timer_Rtr_Retry);
1033 		if (rs->session_id == -1)
1034 			rtr_send_reset_query(rs);
1035 		else
1036 			rtr_send_serial_query(rs);
1037 		break;
1038 	case RTR_EVNT_SERIAL_NOTIFY:
1039 		/* schedule a refresh after a quick wait */
1040 		timer_set(&rs->timers, Timer_Rtr_Refresh,
1041 		    arc4random_uniform(10));
1042 		break;
1043 	case RTR_EVNT_TIMER_REFRESH:
1044 		/* send serial query */
1045 		rtr_send_serial_query(rs);
1046 		break;
1047 	case RTR_EVNT_TIMER_EXPIRE:
1048 		rtr_reset_cache(rs);
1049 		rtr_recalc();
1050 		break;
1051 	case RTR_EVNT_TIMER_ACTIVE:
1052 		log_warnx("rtr %s: activity timer fired", log_rtr(rs));
1053 		rtr_sem_release(rs->active_lock);
1054 		rtr_recalc();
1055 		rs->active_lock = 0;
1056 		break;
1057 	case RTR_EVNT_CACHE_RESPONSE:
1058 		rs->state = RTR_STATE_EXCHANGE;
1059 		timer_stop(&rs->timers, Timer_Rtr_Refresh);
1060 		timer_stop(&rs->timers, Timer_Rtr_Retry);
1061 		timer_set(&rs->timers, Timer_Rtr_Active, rs->active);
1062 		/* prevent rtr_recalc from running while active */
1063 		rs->active_lock = 1;
1064 		rtr_sem_acquire(rs->active_lock);
1065 		break;
1066 	case RTR_EVNT_END_OF_DATA:
1067 		/* start refresh and expire timers */
1068 		timer_set(&rs->timers, Timer_Rtr_Refresh, rs->refresh);
1069 		timer_set(&rs->timers, Timer_Rtr_Expire, rs->expire);
1070 		timer_stop(&rs->timers, Timer_Rtr_Active);
1071 		rs->state = RTR_STATE_ESTABLISHED;
1072 		rtr_sem_release(rs->active_lock);
1073 		rtr_recalc();
1074 		rs->active_lock = 0;
1075 		break;
1076 	case RTR_EVNT_CACHE_RESET:
1077 		rtr_reset_cache(rs);
1078 		rtr_recalc();
1079 		/* retry after a quick wait */
1080 		timer_set(&rs->timers, Timer_Rtr_Retry,
1081 		    arc4random_uniform(10));
1082 		break;
1083 	case RTR_EVNT_NO_DATA:
1084 		/* start retry timer */
1085 		timer_set(&rs->timers, Timer_Rtr_Retry, rs->retry);
1086 		/* stop refresh timer just to be sure */
1087 		timer_stop(&rs->timers, Timer_Rtr_Refresh);
1088 		rs->state = RTR_STATE_ESTABLISHED;
1089 		break;
1090 	case RTR_EVNT_SEND_ERROR:
1091 		rtr_reset_cache(rs);
1092 		rtr_recalc();
1093 		rs->state = RTR_STATE_ERROR;
1094 		/* flush receive buffer */
1095 		rs->r.wpos = 0;
1096 		break;
1097 	}
1098 
1099 	log_debug("rtr %s: state change %s -> %s, reason: %s",
1100 	    log_rtr(rs), rtr_statenames[prev_state], rtr_statenames[rs->state],
1101 	    rtr_eventnames[event]);
1102 }
1103 
1104 /*
1105  * IO handler for RTR sessions
1106  */
1107 static void
1108 rtr_dispatch_msg(struct pollfd *pfd, struct rtr_session *rs)
1109 {
1110 	ssize_t n;
1111 	int error;
1112 
1113 	if (pfd->revents & POLLHUP) {
1114 		log_warnx("rtr %s: Connection closed, hangup", log_rtr(rs));
1115 		rtr_fsm(rs, RTR_EVNT_CON_CLOSE);
1116 		return;
1117 	}
1118 	if (pfd->revents & (POLLERR|POLLNVAL)) {
1119 		log_warnx("rtr %s: Connection closed, error", log_rtr(rs));
1120 		rtr_fsm(rs, RTR_EVNT_CON_CLOSE);
1121 		return;
1122 	}
1123 	if (pfd->revents & POLLOUT && rs->w.queued) {
1124 		if ((error = ibuf_write(&rs->w)) == -1) {
1125 			if (errno != EAGAIN) {
1126 				log_warn("rtr %s: write error", log_rtr(rs));
1127 				rtr_fsm(rs, RTR_EVNT_CON_CLOSE);
1128 			}
1129 		}
1130 		if (error == 0)
1131 			rtr_fsm(rs, RTR_EVNT_CON_CLOSE);
1132 		if (rs->w.queued == 0 && rs->state == RTR_STATE_ERROR)
1133 			rtr_fsm(rs, RTR_EVNT_CON_CLOSE);
1134 	}
1135 	if (pfd->revents & POLLIN) {
1136 		if ((n = read(rs->fd, rs->r.buf + rs->r.wpos,
1137 		    sizeof(rs->r.buf) - rs->r.wpos)) == -1) {
1138 			if (errno != EINTR && errno != EAGAIN) {
1139 				log_warn("rtr %s: read error", log_rtr(rs));
1140 				rtr_fsm(rs, RTR_EVNT_CON_CLOSE);
1141 			}
1142 			return;
1143 		}
1144 		if (n == 0) {
1145 			rtr_fsm(rs, RTR_EVNT_CON_CLOSE);
1146 			return;
1147 		}
1148 		rs->r.wpos += n;
1149 
1150 		/* new data arrived, try to process it */
1151 		rtr_process_msg(rs);
1152 	}
1153 
1154 }
1155 
1156 void
1157 rtr_check_events(struct pollfd *pfds, size_t npfds)
1158 {
1159 	struct rtr_session *rs;
1160 	struct timer *t;
1161 	time_t now;
1162 	size_t i = 0;
1163 
1164 	for (i = 0; i < npfds; i++) {
1165 		if (pfds[i].revents == 0)
1166 			continue;
1167 		TAILQ_FOREACH(rs, &rtrs, entry)
1168 			if (rs->fd == pfds[i].fd) {
1169 				rtr_dispatch_msg(&pfds[i], rs);
1170 				break;
1171 			}
1172 		if (rs == NULL)
1173 			log_warnx("%s: unknown fd in pollfds", __func__);
1174 	}
1175 
1176 	/* run all timers */
1177 	now = getmonotime();
1178 	TAILQ_FOREACH(rs, &rtrs, entry)
1179 		if ((t = timer_nextisdue(&rs->timers, now)) != NULL) {
1180 			log_debug("rtr %s: %s triggered", log_rtr(rs),
1181 			    timernames[t->type]);
1182 			/* stop timer so it does not trigger again */
1183 			timer_stop(&rs->timers, t->type);
1184 			switch (t->type) {
1185 			case Timer_Rtr_Refresh:
1186 				rtr_fsm(rs, RTR_EVNT_TIMER_REFRESH);
1187 				break;
1188 			case Timer_Rtr_Retry:
1189 				rtr_fsm(rs, RTR_EVNT_TIMER_RETRY);
1190 				break;
1191 			case Timer_Rtr_Expire:
1192 				rtr_fsm(rs, RTR_EVNT_TIMER_EXPIRE);
1193 				break;
1194 			case Timer_Rtr_Active:
1195 				rtr_fsm(rs, RTR_EVNT_TIMER_ACTIVE);
1196 				break;
1197 			default:
1198 				fatalx("King Bula lost in time");
1199 			}
1200 		}
1201 }
1202 
1203 size_t
1204 rtr_count(void)
1205 {
1206 	struct rtr_session *rs;
1207 	size_t count = 0;
1208 
1209 	TAILQ_FOREACH(rs, &rtrs, entry)
1210 		count++;
1211 	return count;
1212 }
1213 
1214 size_t
1215 rtr_poll_events(struct pollfd *pfds, size_t npfds, time_t *timeout)
1216 {
1217 	struct rtr_session *rs;
1218 	time_t now = getmonotime();
1219 	size_t i = 0;
1220 
1221 	TAILQ_FOREACH(rs, &rtrs, entry) {
1222 		time_t nextaction;
1223 		struct pollfd *pfd = pfds + i++;
1224 
1225 		if (i > npfds)
1226 			fatalx("%s: too many sessions for pollfd", __func__);
1227 
1228 		if ((nextaction = timer_nextduein(&rs->timers, now)) != -1 &&
1229 		    nextaction < *timeout)
1230 			*timeout = nextaction;
1231 
1232 		if (rs->state == RTR_STATE_CLOSED) {
1233 			pfd->fd = -1;
1234 			continue;
1235 		}
1236 
1237 		pfd->fd = rs->fd;
1238 		pfd->events = 0;
1239 
1240 		if (rs->w.queued)
1241 			pfd->events |= POLLOUT;
1242 		if (rs->state >= RTR_STATE_ESTABLISHED)
1243 			pfd->events |= POLLIN;
1244 	}
1245 
1246 	return i;
1247 }
1248 
1249 struct rtr_session *
1250 rtr_new(uint32_t id, char *descr)
1251 {
1252 	struct rtr_session *rs;
1253 
1254 	if ((rs = calloc(1, sizeof(*rs))) == NULL)
1255 		fatal("RTR session %s", descr);
1256 
1257 	RB_INIT(&rs->roa_set);
1258 	RB_INIT(&rs->aspa);
1259 	RB_INIT(&rs->aspa_oldv6);
1260 	TAILQ_INIT(&rs->timers);
1261 	msgbuf_init(&rs->w);
1262 
1263 	strlcpy(rs->descr, descr, sizeof(rs->descr));
1264 	rs->id = id;
1265 	rs->session_id = -1;
1266 	rs->version = RTR_MAX_VERSION;
1267 	rs->refresh = RTR_DEFAULT_REFRESH;
1268 	rs->retry = RTR_DEFAULT_RETRY;
1269 	rs->expire = RTR_DEFAULT_EXPIRE;
1270 	rs->active = RTR_DEFAULT_ACTIVE;
1271 	rs->state = RTR_STATE_CLOSED;
1272 	rs->reconf_action = RECONF_REINIT;
1273 	rs->last_recv_error = NO_ERROR;
1274 	rs->last_sent_error = NO_ERROR;
1275 
1276 	/* make sure that some timer is running to abort bad sessions */
1277 	timer_set(&rs->timers, Timer_Rtr_Expire, rs->expire);
1278 
1279 	log_debug("rtr %s: new session, start", log_rtr(rs));
1280 	TAILQ_INSERT_TAIL(&rtrs, rs, entry);
1281 	rtr_fsm(rs, RTR_EVNT_START);
1282 
1283 	return rs;
1284 }
1285 
1286 struct rtr_session *
1287 rtr_get(uint32_t id)
1288 {
1289 	struct rtr_session *rs;
1290 
1291 	TAILQ_FOREACH(rs, &rtrs, entry)
1292 		if (rs->id == id)
1293 			return rs;
1294 	return NULL;
1295 }
1296 
1297 void
1298 rtr_free(struct rtr_session *rs)
1299 {
1300 	if (rs == NULL)
1301 		return;
1302 
1303 	rtr_reset_cache(rs);
1304 	rtr_fsm(rs, RTR_EVNT_CON_CLOSE);
1305 	timer_remove_all(&rs->timers);
1306 	free(rs);
1307 }
1308 
1309 void
1310 rtr_open(struct rtr_session *rs, int fd)
1311 {
1312 	if (rs->state != RTR_STATE_CLOSED &&
1313 	    rs->state != RTR_STATE_NEGOTIATION) {
1314 		log_warnx("rtr %s: bad session state", log_rtr(rs));
1315 		rtr_fsm(rs, RTR_EVNT_CON_CLOSE);
1316 	}
1317 
1318 	if (rs->state == RTR_STATE_CLOSED)
1319 		rs->version = RTR_MAX_VERSION;
1320 
1321 	rs->fd = rs->w.fd = fd;
1322 	rs->state = RTR_STATE_NEGOTIATION;
1323 	rtr_fsm(rs, RTR_EVNT_CON_OPEN);
1324 }
1325 
1326 void
1327 rtr_config_prep(void)
1328 {
1329 	struct rtr_session *rs;
1330 
1331 	TAILQ_FOREACH(rs, &rtrs, entry)
1332 		rs->reconf_action = RECONF_DELETE;
1333 }
1334 
1335 void
1336 rtr_config_merge(void)
1337 {
1338 	struct rtr_session *rs, *nrs;
1339 
1340 	TAILQ_FOREACH_SAFE(rs, &rtrs, entry, nrs)
1341 		if (rs->reconf_action == RECONF_DELETE) {
1342 			TAILQ_REMOVE(&rtrs, rs, entry);
1343 			rtr_free(rs);
1344 		}
1345 }
1346 
1347 void
1348 rtr_config_keep(struct rtr_session *rs)
1349 {
1350 	rs->reconf_action = RECONF_KEEP;
1351 }
1352 
1353 void
1354 rtr_roa_merge(struct roa_tree *rt)
1355 {
1356 	struct rtr_session *rs;
1357 	struct roa *roa;
1358 
1359 	TAILQ_FOREACH(rs, &rtrs, entry) {
1360 		RB_FOREACH(roa, roa_tree, &rs->roa_set)
1361 			rtr_roa_insert(rt, roa);
1362 	}
1363 }
1364 
1365 void
1366 rtr_aspa_merge(struct aspa_tree *at)
1367 {
1368 	struct rtr_session *rs;
1369 	struct aspa_set *aspa;
1370 
1371 	TAILQ_FOREACH(rs, &rtrs, entry) {
1372 		RB_FOREACH(aspa, aspa_tree, &rs->aspa)
1373 			rtr_aspa_insert(at, aspa);
1374 		RB_FOREACH(aspa, aspa_tree, &rs->aspa_oldv6)
1375 			rtr_aspa_insert(at, aspa);
1376 	}
1377 }
1378 
1379 void
1380 rtr_shutdown(void)
1381 {
1382 	struct rtr_session *rs, *nrs;
1383 
1384 	TAILQ_FOREACH_SAFE(rs, &rtrs, entry, nrs)
1385 		rtr_free(rs);
1386 }
1387 
1388 void
1389 rtr_show(struct rtr_session *rs, pid_t pid)
1390 {
1391 	struct ctl_show_rtr msg;
1392 	struct ctl_timer ct;
1393 	u_int i;
1394 	time_t d;
1395 
1396 	memset(&msg, 0, sizeof(msg));
1397 
1398 	/* descr, remote_addr, local_addr and remote_port set by parent */
1399 	msg.version = rs->version;
1400 	msg.serial = rs->serial;
1401 	msg.refresh = rs->refresh;
1402 	msg.retry = rs->retry;
1403 	msg.expire = rs->expire;
1404 	msg.session_id = rs->session_id;
1405 	msg.last_sent_error = rs->last_sent_error;
1406 	msg.last_recv_error = rs->last_recv_error;
1407 	strlcpy(msg.last_sent_msg, rs->last_sent_msg,
1408 	    sizeof(msg.last_sent_msg));
1409 	strlcpy(msg.last_recv_msg, rs->last_recv_msg,
1410 	    sizeof(msg.last_recv_msg));
1411 
1412 	/* send back imsg */
1413 	rtr_imsg_compose(IMSG_CTL_SHOW_RTR, rs->id, pid, &msg, sizeof(msg));
1414 
1415 	/* send back timer imsgs */
1416 	for (i = 1; i < Timer_Max; i++) {
1417 		if (!timer_running(&rs->timers, i, &d))
1418 			continue;
1419 		ct.type = i;
1420 		ct.val = d;
1421 		rtr_imsg_compose(IMSG_CTL_SHOW_TIMER, rs->id, pid,
1422 		    &ct, sizeof(ct));
1423 	}
1424 }
1425