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