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, ¬ify, 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, ¬ify.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