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