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