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