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