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