xref: /openbsd-src/usr.sbin/bgpd/rtr_proto.c (revision f1dd7b858388b4a23f4f67a4957ec5ff656ebbe8)
1 /*	$OpenBSD: rtr_proto.c,v 1.1 2021/02/16 08:29:16 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 	roa->aid = AID_INET;
453 	roa->prefixlen = ip4.prefixlen;
454 	roa->maxlen = ip4.maxlen;
455 	roa->asnum = ntohl(ip4.asnum);
456 	roa->prefix.inet.s_addr = ip4.prefix;
457 
458 	if (ip4.flags & FLAG_ANNOUNCE) {
459 		if (RB_INSERT(roa_tree, &rs->roa_set, roa) != NULL) {
460 			log_warnx("rtr %s: received %s: duplicate announcement",
461 			    log_rtr(rs), log_rtr_type(IPV4_PREFIX));
462 			rtr_send_error(rs, DUP_REC_RECV, NULL, buf, len);
463 			free(roa);
464 			return -1;
465 		}
466 	} else {
467 		struct roa *r;
468 
469 		r = RB_FIND(roa_tree, &rs->roa_set, roa);
470 		if (r == NULL) {
471 			log_warnx("rtr %s: received %s: unknown withdrawl",
472 			    log_rtr(rs), log_rtr_type(IPV4_PREFIX));
473 			rtr_send_error(rs, UNK_REC_WDRAWL, NULL, buf, len);
474 			free(roa);
475 			return -1;
476 		}
477 		RB_REMOVE(roa_tree, &rs->roa_set, r);
478 		free(r);
479 		free(roa);
480 	}
481 
482 	return 0;
483 }
484 
485 static int
486 rtr_parse_ipv6_prefix(struct rtr_session *rs, uint8_t *buf, size_t len)
487 {
488 	struct rtr_ipv6 ip6;
489 	struct roa *roa;
490 
491 	if (len != sizeof(struct rtr_header) + sizeof(ip6)) {
492 		log_warnx("rtr %s: received %s: bad pdu len",
493 		    log_rtr(rs), log_rtr_type(IPV6_PREFIX));
494 		rtr_send_error(rs, CORRUPT_DATA, "bad len", buf, len);
495 		return -1;
496 	}
497 
498 	if (rs->state != RTR_STATE_ACTIVE) {
499 		log_warnx("rtr %s: received %s: out of context",
500 		    log_rtr(rs), log_rtr_type(IPV6_PREFIX));
501 		rtr_send_error(rs, CORRUPT_DATA, NULL, buf, len);
502 		return -1;
503 	}
504 
505 	memcpy(&ip6, buf + sizeof(struct rtr_header), sizeof(ip6));
506 
507 	if ((roa = calloc(1, sizeof(*roa))) == NULL) {
508 		log_warn("rtr %s: received %s",
509 		    log_rtr(rs), log_rtr_type(IPV6_PREFIX));
510 		rtr_send_error(rs, INTERNAL_ERROR, "out of memory", NULL, 0);
511 		return -1;
512 	}
513 	roa->aid = AID_INET6;
514 	roa->prefixlen = ip6.prefixlen;
515 	roa->maxlen = ip6.maxlen;
516 	roa->asnum = ntohl(ip6.asnum);
517 	memcpy(&roa->prefix.inet6, ip6.prefix, sizeof(roa->prefix.inet6));
518 
519 	if (ip6.flags & FLAG_ANNOUNCE) {
520 		if (RB_INSERT(roa_tree, &rs->roa_set, roa) != NULL) {
521 			log_warnx("rtr %s: received %s: duplicate announcement",
522 			    log_rtr(rs), log_rtr_type(IPV6_PREFIX));
523 			rtr_send_error(rs, DUP_REC_RECV, NULL, buf, len);
524 			free(roa);
525 			return -1;
526 		}
527 	} else {
528 		struct roa *r;
529 
530 		r = RB_FIND(roa_tree, &rs->roa_set, roa);
531 		if (r == NULL) {
532 			log_warnx("rtr %s: received %s: unknown withdrawl",
533 			    log_rtr(rs), log_rtr_type(IPV6_PREFIX));
534 			rtr_send_error(rs, UNK_REC_WDRAWL, NULL, buf, len);
535 			free(roa);
536 			return -1;
537 		}
538 		RB_REMOVE(roa_tree, &rs->roa_set, r);
539 		free(r);
540 		free(roa);
541 	}
542 	return 0;
543 }
544 
545 static int
546 rtr_parse_end_of_data(struct rtr_session *rs, uint8_t *buf, size_t len)
547 {
548 	struct rtr_endofdata eod;
549 	uint32_t t;
550 
551 	buf += sizeof(struct rtr_header);
552 	len -= sizeof(struct rtr_header);
553 
554 	if (len != sizeof(eod)) {
555 		log_warnx("rtr %s: received %s: bad pdu len",
556 		    log_rtr(rs), log_rtr_type(END_OF_DATA));
557 		return -1;
558 	}
559 
560 	memcpy(&eod, buf, sizeof(eod));
561 
562 	if (rs->state != RTR_STATE_ACTIVE) {
563 		log_warnx("rtr %s: received %s: out of context",
564 		    log_rtr(rs), log_rtr_type(END_OF_DATA));
565 		return -1;
566 	}
567 
568 	rs->serial = ntohl(eod.serial);
569 	/* validate timer values to be in the right range */
570 	t = ntohl(eod.refresh);
571 	if (t < 1 || t > 86400)
572 		goto bad;
573 	rs->refresh = t;
574 	t = ntohl(eod.retry);
575 	if (t < 1 || t > 7200)
576 		goto bad;
577 	rs->retry = t;
578 	t = ntohl(eod.expire);
579 	if (t < 600 || t > 172800)
580 		goto bad;
581 	if (t <= rs->retry || t <= rs->refresh)
582 		goto bad;
583 	rs->expire = t;
584 
585 	rtr_fsm(rs, RTR_EVNT_END_OF_DATA);
586 	return 0;
587 
588 bad:
589 	log_warnx("rtr %s: received %s: bad timeout values",
590 	    log_rtr(rs), log_rtr_type(END_OF_DATA));
591 	return -1;
592 }
593 
594 static int
595 rtr_parse_cache_reset(struct rtr_session *rs, uint8_t *buf, size_t len)
596 {
597 	if (rs->state != RTR_STATE_IDLE) {
598 		log_warnx("rtr %s: received %s: out of context",
599 		    log_rtr(rs), log_rtr_type(CACHE_RESET));
600 		return -1;
601 	}
602 
603 	rtr_fsm(rs, RTR_EVNT_CACHE_RESET);
604 	return 0;
605 }
606 
607 /*
608  * Parse an Error Response message. This function behaves a bit different
609  * from other parse functions since on error the connection needs to be
610  * dropped without sending an error response back.
611  */
612 static int
613 rtr_parse_error(struct rtr_session *rs, uint8_t *buf, size_t len)
614 {
615 	struct rtr_header rh;
616 	uint32_t pdu_len, msg_len;
617 	uint8_t *msg;
618 	char *str = NULL;
619 	uint16_t errcode;
620 
621 	memcpy(&rh, buf, sizeof(rh));
622 	buf += sizeof(struct rtr_header);
623 	len -= sizeof(struct rtr_header);
624 	errcode = ntohs(rh.session_id);
625 
626 	memcpy(&pdu_len, buf, sizeof(pdu_len));
627 	pdu_len = ntohs(pdu_len);
628 
629 	if (len < pdu_len + sizeof(pdu_len)) {
630 		log_warnx("rtr %s: received %s: bad pdu len: %u byte",
631 		    log_rtr(rs), log_rtr_type(ERROR_REPORT), pdu_len);
632 		rtr_fsm(rs, RTR_EVNT_CON_CLOSED);
633 		return -1;
634 	}
635 
636 	/* for now just ignore the embedded pdu */
637 	buf += pdu_len + sizeof(pdu_len);
638 	len -= pdu_len + sizeof(pdu_len);
639 
640 	memcpy(&msg_len, buf, sizeof(msg_len));
641 	msg_len = ntohs(msg_len);
642 
643 	if (len < msg_len + sizeof(msg_len)) {
644 		log_warnx("rtr %s: received %s: bad msg len: %u byte",
645 		    log_rtr(rs), log_rtr_type(ERROR_REPORT), msg_len);
646 		rtr_fsm(rs, RTR_EVNT_CON_CLOSED);
647 		return -1;
648 	}
649 
650 	msg = buf + sizeof(msg_len);
651 	if (msg_len != 0)
652 		/* optional error msg, no need to check for failure */
653 		str = strndup(msg, msg_len);
654 
655 	log_warnx("rtr %s: received error: %s%s%s", log_rtr(rs),
656 	    log_rtr_error(errcode), str ? ": " : "", str ? str : "");
657 
658 	if (errcode == NO_DATA_AVAILABLE) {
659 		rtr_fsm(rs, RTR_EVNT_NO_DATA);
660 	} else {
661 		rtr_fsm(rs, RTR_EVNT_CON_CLOSED);
662 		rs->last_recv_error = errcode;
663 		if (str)
664 			strlcpy(rs->last_recv_msg, str,
665 			    sizeof(rs->last_recv_msg));
666 		else
667 			memset(rs->last_recv_msg, 0,
668 			    sizeof(rs->last_recv_msg));
669 
670 		free(str);
671 		return -1;
672 	}
673 	free(str);
674 
675 	return 0;
676 }
677 
678 /*
679  * Try to process received rtr message, it is possible that not a full
680  * message is in the buffer. In that case stop, once new data is available
681  * a retry will be done.
682  */
683 static void
684 rtr_process_msg(struct rtr_session *rs)
685 {
686 	size_t rpos, av, left;
687 	void *rptr;
688 	size_t msglen;
689 	enum rtr_pdu_type msgtype;
690 
691 	rpos = 0;
692 	av = rs->r.wpos;
693 
694 	for (;;) {
695 		if (rpos + sizeof(struct rtr_header) > av)
696 			break;
697 		rptr = rs->r.buf + rpos;
698 		if (rtr_parse_header(rs, rptr, &msglen, &msgtype) == -1)
699 			return;
700 
701 		/* missing data */
702 		if (rpos + msglen > av)
703 			break;
704 
705 		switch (msgtype) {
706 		case SERIAL_NOTIFY:
707 			if (rtr_parse_notify(rs, rptr, msglen) == -1) {
708 				rtr_send_error(rs, CORRUPT_DATA, NULL,
709 				    rptr, msglen);
710 				return;
711 			}
712 			break;
713 		case CACHE_RESPONSE:
714 			if (rtr_parse_cache_response(rs, rptr, msglen) == -1) {
715 				rtr_send_error(rs, CORRUPT_DATA, NULL,
716 				    rptr, msglen);
717 				return;
718 			}
719 			break;
720 		case IPV4_PREFIX:
721 			if (rtr_parse_ipv4_prefix(rs, rptr, msglen) == -1) {
722 				return;
723 			}
724 			break;
725 		case IPV6_PREFIX:
726 			if (rtr_parse_ipv6_prefix(rs, rptr, msglen) == -1) {
727 				return;
728 			}
729 			break;
730 		case END_OF_DATA:
731 			if (rtr_parse_end_of_data(rs, rptr, msglen) == -1) {
732 				rtr_send_error(rs, CORRUPT_DATA, NULL,
733 				    rptr, msglen);
734 				return;
735 			}
736 			break;
737 		case CACHE_RESET:
738 			if (rtr_parse_cache_reset(rs, rptr, msglen) == -1) {
739 				rtr_send_error(rs, CORRUPT_DATA, NULL,
740 				    rptr, msglen);
741 				return;
742 			}
743 			break;
744 		case ROUTER_KEY:
745 			/* silently ignore router key */
746 			break;
747 		case ERROR_REPORT:
748 			if (rtr_parse_error(rs, rptr, msglen) == -1)
749 				/* no need to send back an error */
750 				return;
751 			break;
752 		default:
753 			log_warnx("rtr %s: received %s: unexpected pdu type",
754 		    	    log_rtr(rs), log_rtr_type(msgtype));
755 			rtr_send_error(rs, INVALID_REQUEST, NULL, rptr, msglen);
756 			return;
757 		}
758 		rpos += msglen;
759 	}
760 
761 	left = av - rpos;
762 	memmove(&rs->r.buf, rs->r.buf + rpos, left);
763 	rs->r.wpos = left;
764 }
765 
766 /*
767  * Simple FSM for RTR sessions
768  */
769 static void
770 rtr_fsm(struct rtr_session *rs, enum rtr_event event)
771 {
772 	enum rtr_state prev_state = rs->state;
773 
774 	switch (event) {
775 	case RTR_EVNT_CON_CLOSED:
776 		if (rs->state != RTR_STATE_CLOSED) {
777 			/* flush buffers */
778 			msgbuf_clear(&rs->w);
779 			rs->r.wpos = 0;
780 			close(rs->fd);
781 			rs->fd = -1;
782 		}
783 		rs->state = RTR_STATE_CLOSED;
784 		/* try to reopen session */
785 		timer_set(&rs->timers, Timer_Rtr_Retry,
786 		    arc4random_uniform(10));
787 		break;
788 	case RTR_EVNT_START:
789 	case RTR_EVNT_TIMER_RETRY:
790 		switch (rs->state) {
791 		case RTR_STATE_ERROR:
792 			rtr_fsm(rs, RTR_EVNT_CON_CLOSED);
793 			return;
794 		case RTR_STATE_CLOSED:
795 			timer_set(&rs->timers, Timer_Rtr_Retry, rs->retry);
796 			rtr_imsg_compose(IMSG_SOCKET_CONN, rs->id, 0, NULL, 0);
797 			return;
798 		default:
799 			break;
800 		}
801 		/* FALLTHROUGH */
802 	case RTR_EVNT_CON_OPEN:
803 		timer_stop(&rs->timers, Timer_Rtr_Retry);
804 		if (rs->session_id == -1)
805 			rtr_reset_query(rs);
806 		else
807 			rtr_serial_query(rs);
808 		break;
809 	case RTR_EVNT_SERIAL_NOTIFY:
810 		/* schedule a refresh after a quick wait */
811 		timer_set(&rs->timers, Timer_Rtr_Refresh,
812 		    arc4random_uniform(10));
813 		break;
814 	case RTR_EVNT_TIMER_REFRESH:
815 		/* send serial query */
816 		rtr_serial_query(rs);
817 		break;
818 	case RTR_EVNT_TIMER_EXPIRE:
819 		free_roatree(&rs->roa_set);
820 		rtr_recalc();
821 		break;
822 	case RTR_EVNT_CACHE_RESPONSE:
823 		rs->state = RTR_STATE_ACTIVE;
824 		timer_stop(&rs->timers, Timer_Rtr_Refresh);
825 		timer_stop(&rs->timers, Timer_Rtr_Retry);
826 		break;
827 	case RTR_EVNT_END_OF_DATA:
828 		/* start refresh and expire timers */
829 		timer_set(&rs->timers, Timer_Rtr_Refresh, rs->refresh);
830 		timer_set(&rs->timers, Timer_Rtr_Expire, rs->expire);
831 		rs->state = RTR_STATE_IDLE;
832 		rtr_recalc();
833 		break;
834 	case RTR_EVNT_CACHE_RESET:
835 		/* reset session and retry after a quick wait */
836 		rs->session_id = -1;
837 		free_roatree(&rs->roa_set);
838 		timer_set(&rs->timers, Timer_Rtr_Retry,
839 		    arc4random_uniform(10));
840 		break;
841 	case RTR_EVNT_NO_DATA:
842 		/* start retry timer */
843 		timer_set(&rs->timers, Timer_Rtr_Retry, rs->retry);
844 		/* stop refresh timer just to be sure */
845 		timer_stop(&rs->timers, Timer_Rtr_Refresh);
846 		break;
847 	case RTR_EVNT_SEND_ERROR:
848 		rs->state = RTR_STATE_ERROR;
849 		/* flush receive buffer */
850 		rs->r.wpos = 0;
851 		break;
852 	}
853 
854 	log_info("rtr %s: state change %s -> %s, reason: %s",
855 	    log_rtr(rs), rtr_statenames[prev_state], rtr_statenames[rs->state],
856 	    rtr_eventnames[event]);
857 }
858 
859 /*
860  * IO handler for RTR sessions
861  */
862 static void
863 rtr_dispatch_msg(struct pollfd *pfd, struct rtr_session *rs)
864 {
865 	ssize_t n;
866 	int error;
867 
868 	if (pfd->revents & POLLHUP) {
869 		log_warnx("rtr %s: Connection closed, hangup", log_rtr(rs));
870 		rtr_fsm(rs, RTR_EVNT_CON_CLOSED);
871 		return;
872 	}
873 	if (pfd->revents & (POLLERR|POLLNVAL)) {
874 		log_warnx("rtr %s: Connection closed, error", log_rtr(rs));
875 		rtr_fsm(rs, RTR_EVNT_CON_CLOSED);
876 		return;
877 	}
878 	if (pfd->revents & POLLOUT && rs->w.queued) {
879 		if ((error = ibuf_write(&rs->w)) <= 0 && errno != EAGAIN) {
880 			if (error == 0)
881 				log_warnx("rtr %s: Connection closed",
882 				    log_rtr(rs));
883 			else if (error == -1)
884 				log_warn("rtr %s: write error", log_rtr(rs));
885 			rtr_fsm(rs, RTR_EVNT_CON_CLOSED);
886 			return;
887 		}
888 		if (rs->w.queued == 0 && rs->state == RTR_STATE_ERROR)
889 			rtr_fsm(rs, RTR_EVNT_CON_CLOSED);
890 	}
891 	if (pfd->revents & POLLIN) {
892 		if ((n = read(rs->fd, rs->r.buf + rs->r.wpos,
893 		    sizeof(rs->r.buf) - rs->r.wpos)) == -1) {
894 			if (errno != EINTR && errno != EAGAIN) {
895 				log_warn("rtr %s: read error", log_rtr(rs));
896 				rtr_fsm(rs, RTR_EVNT_CON_CLOSED);
897 			}
898 			return;
899 		}
900 		if (n == 0) {
901 			log_warnx("rtr %s: Connection closed", log_rtr(rs));
902 			rtr_fsm(rs, RTR_EVNT_CON_CLOSED);
903 			return;
904 		}
905 		rs->r.wpos += n;
906 
907 		/* new data arrived, try to process it */
908 		rtr_process_msg(rs);
909 	}
910 
911 }
912 
913 void
914 rtr_check_events(struct pollfd *pfds, size_t npfds)
915 {
916 	struct rtr_session *rs;
917 	struct timer *t;
918 	time_t now;
919 	size_t i = 0;
920 
921 	for (i = 0; i < npfds; i++) {
922 		if (pfds[i].revents == 0)
923 			continue;
924 		TAILQ_FOREACH(rs, &rtrs, entry)
925 			if (rs->fd == pfds[i].fd) {
926 				rtr_dispatch_msg(&pfds[i], rs);
927 				break;
928 			}
929 		if (rs == NULL)
930 			log_warnx("%s: unknown fd in pollfds", __func__);
931 	}
932 
933 	/* run all timers */
934 	now = getmonotime();
935 	TAILQ_FOREACH(rs, &rtrs, entry)
936 		if ((t = timer_nextisdue(&rs->timers, now)) != NULL) {
937 			log_debug("rtr %s: %s triggered", log_rtr(rs),
938 			    timernames[t->type]);
939 			/* stop timer so it does not trigger again */
940 			timer_stop(&rs->timers, t->type);
941 			switch (t->type) {
942 			case Timer_Rtr_Refresh:
943 				rtr_fsm(rs, RTR_EVNT_TIMER_REFRESH);
944 				break;
945 			case Timer_Rtr_Retry:
946 				rtr_fsm(rs, RTR_EVNT_TIMER_RETRY);
947 				break;
948 			case Timer_Rtr_Expire:
949 				rtr_fsm(rs, RTR_EVNT_TIMER_EXPIRE);
950 				break;
951 			default:
952 				fatalx("King Bula lost in time");
953 			}
954 		}
955 }
956 
957 size_t
958 rtr_count(void)
959 {
960 	struct rtr_session *rs;
961 	size_t count = 0;
962 
963 	TAILQ_FOREACH(rs, &rtrs, entry)
964 		count++;
965 	return count;
966 }
967 
968 size_t
969 rtr_poll_events(struct pollfd *pfds, size_t npfds, time_t *timeout)
970 {
971 	struct rtr_session *rs;
972 	time_t now = getmonotime();
973 	size_t i = 0;
974 
975 	TAILQ_FOREACH(rs, &rtrs, entry) {
976 		time_t nextaction;
977 		struct pollfd *pfd = pfds + i++;
978 
979 		if (i > npfds)
980 			fatalx("%s: too many sessions for pollfd", __func__);
981 
982 		if ((nextaction = timer_nextduein(&rs->timers, now)) != -1 &&
983 		    nextaction < *timeout)
984 			*timeout = nextaction;
985 
986 		if (rs->state == RTR_STATE_CLOSED) {
987 			pfd->fd = -1;
988 			continue;
989 		}
990 
991 		pfd->fd = rs->fd;
992 		pfd->events = 0;
993 
994 		if (rs->w.queued)
995 			pfd->events |= POLLOUT;
996 		if (rs->state >= RTR_STATE_IDLE)
997 			pfd->events |= POLLIN;
998 	}
999 
1000 	return i;
1001 }
1002 
1003 struct rtr_session *
1004 rtr_new(uint32_t id, char *descr)
1005 {
1006 	struct rtr_session *rs;
1007 
1008 	if ((rs = calloc(1, sizeof(*rs))) == NULL)
1009 		fatal("RTR session %s", descr);
1010 
1011 	RB_INIT(&rs->roa_set);
1012 	TAILQ_INIT(&rs->timers);
1013 	msgbuf_init(&rs->w);
1014 
1015 	strlcpy(rs->descr, descr, sizeof(rs->descr));
1016 	rs->id = id;
1017 	rs->session_id = -1;
1018 	rs->refresh = RTR_DEFAULT_REFRESH;
1019 	rs->retry = RTR_DEFAULT_RETRY;
1020 	rs->expire = RTR_DEFAULT_EXPIRE;
1021 	rs->state = RTR_STATE_CLOSED;
1022 	rs->reconf_action = RECONF_REINIT;
1023 	rs->last_recv_error = NO_ERROR;
1024 	rs->last_sent_error = NO_ERROR;
1025 
1026 	/* make sure that some timer is running to abort bad sessions */
1027 	timer_set(&rs->timers, Timer_Rtr_Expire, rs->expire);
1028 
1029 	log_debug("rtr %s: new session, start", log_rtr(rs));
1030 	TAILQ_INSERT_TAIL(&rtrs, rs, entry);
1031 	rtr_fsm(rs, RTR_EVNT_START);
1032 
1033 	return rs;
1034 }
1035 
1036 struct rtr_session *
1037 rtr_get(uint32_t id)
1038 {
1039 	struct rtr_session *rs;
1040 
1041 	TAILQ_FOREACH(rs, &rtrs, entry)
1042 		if (rs->id == id)
1043 			return rs;
1044 	return NULL;
1045 }
1046 
1047 void
1048 rtr_free(struct rtr_session *rs)
1049 {
1050 	if (rs == NULL)
1051 		return;
1052 
1053 	rtr_fsm(rs, RTR_EVNT_CON_CLOSED);
1054 	timer_remove_all(&rs->timers);
1055 	free_roatree(&rs->roa_set);
1056 	free(rs);
1057 }
1058 
1059 void
1060 rtr_open(struct rtr_session *rs, int fd)
1061 {
1062 	if (rs->state != RTR_STATE_CLOSED) {
1063 		log_warnx("rtr %s: bad session state", log_rtr(rs));
1064 		rtr_fsm(rs, RTR_EVNT_CON_CLOSED);
1065 	}
1066 
1067 	log_debug("rtr %s: connection opened", log_rtr(rs));
1068 
1069 	rs->fd = rs->w.fd = fd;
1070 	rs->state = RTR_STATE_IDLE;
1071 	rtr_fsm(rs, RTR_EVNT_CON_OPEN);
1072 }
1073 
1074 void
1075 rtr_config_prep(void)
1076 {
1077 	struct rtr_session *rs;
1078 
1079 	TAILQ_FOREACH(rs, &rtrs, entry)
1080 		rs->reconf_action = RECONF_DELETE;
1081 }
1082 
1083 void
1084 rtr_config_merge(void)
1085 {
1086 	struct rtr_session *rs, *nrs;
1087 
1088 	TAILQ_FOREACH_SAFE(rs, &rtrs, entry, nrs)
1089 		if (rs->reconf_action == RECONF_DELETE) {
1090 			TAILQ_REMOVE(&rtrs, rs, entry);
1091 			rtr_free(rs);
1092 		}
1093 }
1094 
1095 void
1096 rtr_config_keep(struct rtr_session *rs)
1097 {
1098 	rs->reconf_action = RECONF_KEEP;
1099 }
1100 
1101 void
1102 rtr_roa_merge(struct roa_tree *rt)
1103 {
1104 	struct rtr_session *rs;
1105 	struct roa *roa;
1106 
1107 	TAILQ_FOREACH(rs, &rtrs, entry) {
1108 		RB_FOREACH(roa, roa_tree, &rs->roa_set)
1109 			roa_insert(rt, roa);
1110 	}
1111 }
1112 
1113 void
1114 rtr_shutdown(void)
1115 {
1116 	struct rtr_session *rs, *nrs;
1117 
1118 	TAILQ_FOREACH_SAFE(rs, &rtrs, entry, nrs)
1119 		rtr_free(rs);
1120 }
1121 
1122 void
1123 rtr_show(struct rtr_session *rs, pid_t pid)
1124 {
1125 	struct ctl_show_rtr msg;
1126 	struct ctl_timer ct;
1127 	u_int i;
1128 	time_t d;
1129 
1130 	memset(&msg, 0, sizeof(msg));
1131 
1132 	/* descr, remote_addr, local_addr and remote_port set by parent */
1133 	msg.serial = rs->serial;
1134 	msg.refresh = rs->refresh;
1135 	msg.retry = rs->retry;
1136 	msg.expire = rs->expire;
1137 	msg.session_id = rs->session_id;
1138 	msg.last_sent_error = rs->last_sent_error;
1139 	msg.last_recv_error = rs->last_recv_error;
1140 	strlcpy(msg.last_sent_msg, rs->last_sent_msg,
1141 	    sizeof(msg.last_sent_msg));
1142 	strlcpy(msg.last_recv_msg, rs->last_recv_msg,
1143 	    sizeof(msg.last_recv_msg));
1144 
1145 	/* send back imsg */
1146 	rtr_imsg_compose(IMSG_CTL_SHOW_RTR, rs->id, pid, &msg, sizeof(msg));
1147 
1148 	/* send back timer imsgs */
1149 	for (i = 1; i < Timer_Max; i++) {
1150 		if (!timer_running(&rs->timers, i, &d))
1151 			continue;
1152 		ct.type = i;
1153 		ct.val = d;
1154 		rtr_imsg_compose(IMSG_CTL_SHOW_TIMER, rs->id, pid,
1155 		    &ct, sizeof(ct));
1156 	}
1157 }
1158