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