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