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