1 /* $OpenBSD: rde.c,v 1.25 2023/03/08 04:43:14 guenther Exp $ */ 2 3 /* 4 * Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it> 5 * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org> 6 * Copyright (c) 2004 Esben Norby <norby@openbsd.org> 7 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 #include <sys/socket.h> 23 #include <sys/queue.h> 24 #include <netinet/in.h> 25 #include <arpa/inet.h> 26 #include <err.h> 27 #include <errno.h> 28 #include <stdlib.h> 29 #include <signal.h> 30 #include <string.h> 31 #include <pwd.h> 32 #include <unistd.h> 33 #include <event.h> 34 35 #include "ripd.h" 36 #include "rip.h" 37 #include "ripe.h" 38 #include "log.h" 39 #include "rde.h" 40 41 #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) 42 43 struct ripd_conf *rdeconf = NULL; 44 static struct imsgev *iev_ripe; 45 static struct imsgev *iev_main; 46 47 void rde_sig_handler(int, short, void *); 48 __dead void rde_shutdown(void); 49 void rde_dispatch_imsg(int, short, void *); 50 void rde_dispatch_parent(int, short, void *); 51 int rde_imsg_compose_ripe(int, u_int32_t, pid_t, void *, u_int16_t); 52 int rde_check_route(struct rip_route *); 53 void triggered_update(struct rt_node *); 54 55 void 56 rde_sig_handler(int sig, short event, void *arg) 57 { 58 /* 59 * signal handler rules don't apply, libevent decouples for us 60 */ 61 62 switch (sig) { 63 case SIGINT: 64 case SIGTERM: 65 rde_shutdown(); 66 /* NOTREACHED */ 67 default: 68 fatalx("unexpected signal"); 69 } 70 } 71 72 /* route decision engine */ 73 pid_t 74 rde(struct ripd_conf *xconf, int pipe_parent2rde[2], int pipe_ripe2rde[2], 75 int pipe_parent2ripe[2]) 76 { 77 struct event ev_sigint, ev_sigterm; 78 struct passwd *pw; 79 struct redistribute *r; 80 pid_t pid; 81 82 switch (pid = fork()) { 83 case -1: 84 fatal("cannot fork"); 85 /* NOTREACHED */ 86 case 0: 87 break; 88 default: 89 return (pid); 90 } 91 92 rdeconf = xconf; 93 94 if ((pw = getpwnam(RIPD_USER)) == NULL) 95 fatal("getpwnam"); 96 97 if (chroot(pw->pw_dir) == -1) 98 fatal("chroot"); 99 if (chdir("/") == -1) 100 fatal("chdir(\"/\")"); 101 102 setproctitle("route decision engine"); 103 log_procname = "rde"; 104 105 if (setgroups(1, &pw->pw_gid) || 106 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 107 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 108 fatal("can't drop privileges"); 109 110 if (pledge("stdio", NULL) == -1) 111 fatal("pledge"); 112 113 event_init(); 114 115 /* setup signal handler */ 116 signal_set(&ev_sigint, SIGINT, rde_sig_handler, NULL); 117 signal_set(&ev_sigterm, SIGTERM, rde_sig_handler, NULL); 118 signal_add(&ev_sigint, NULL); 119 signal_add(&ev_sigterm, NULL); 120 signal(SIGPIPE, SIG_IGN); 121 signal(SIGHUP, SIG_IGN); 122 123 /* setup pipes */ 124 close(pipe_ripe2rde[0]); 125 close(pipe_parent2rde[0]); 126 close(pipe_parent2ripe[0]); 127 close(pipe_parent2ripe[1]); 128 129 if ((iev_ripe = malloc(sizeof(struct imsgev))) == NULL || 130 (iev_main = malloc(sizeof(struct imsgev))) == NULL) 131 fatal(NULL); 132 imsg_init(&iev_ripe->ibuf, pipe_ripe2rde[1]); 133 iev_ripe->handler = rde_dispatch_imsg; 134 imsg_init(&iev_main->ibuf, pipe_parent2rde[1]); 135 iev_main->handler = rde_dispatch_parent; 136 137 /* setup event handler */ 138 iev_ripe->events = EV_READ; 139 event_set(&iev_ripe->ev, iev_ripe->ibuf.fd, iev_ripe->events, 140 iev_ripe->handler, iev_ripe); 141 event_add(&iev_ripe->ev, NULL); 142 143 iev_main->events = EV_READ; 144 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events, 145 iev_main->handler, iev_main); 146 event_add(&iev_main->ev, NULL); 147 rt_init(); 148 149 /* remove unneeded config stuff */ 150 while ((r = SIMPLEQ_FIRST(&rdeconf->redist_list)) != NULL) { 151 SIMPLEQ_REMOVE_HEAD(&rdeconf->redist_list, entry); 152 free(r); 153 } 154 155 event_dispatch(); 156 157 rde_shutdown(); 158 /* NOTREACHED */ 159 160 return (0); 161 } 162 163 __dead void 164 rde_shutdown(void) 165 { 166 /* close pipes */ 167 msgbuf_clear(&iev_ripe->ibuf.w); 168 close(iev_ripe->ibuf.fd); 169 msgbuf_clear(&iev_main->ibuf.w); 170 close(iev_main->ibuf.fd); 171 172 rt_clear(); 173 free(iev_ripe); 174 free(iev_main); 175 free(rdeconf); 176 177 log_info("route decision engine exiting"); 178 _exit(0); 179 } 180 181 int 182 rde_imsg_compose_ripe(int type, u_int32_t peerid, pid_t pid, void *data, 183 u_int16_t datalen) 184 { 185 return (imsg_compose_event(iev_ripe, type, peerid, pid, -1, 186 data, datalen)); 187 } 188 189 void 190 rde_dispatch_imsg(int fd, short event, void *bula) 191 { 192 struct imsgev *iev = bula; 193 struct imsgbuf *ibuf = &iev->ibuf; 194 struct rip_route rr; 195 struct imsg imsg; 196 ssize_t n; 197 int shut = 0, verbose; 198 199 if (event & EV_READ) { 200 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 201 fatal("imsg_read error"); 202 if (n == 0) /* connection closed */ 203 shut = 1; 204 } 205 if (event & EV_WRITE) { 206 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 207 fatal("msgbuf_write"); 208 if (n == 0) /* connection closed */ 209 shut = 1; 210 } 211 212 for (;;) { 213 if ((n = imsg_get(ibuf, &imsg)) == -1) 214 fatal("rde_dispatch_imsg: imsg_get error"); 215 if (n == 0) 216 break; 217 218 switch (imsg.hdr.type) { 219 case IMSG_ROUTE_FEED: 220 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(rr)) 221 fatalx("invalid size of RDE request"); 222 223 memcpy(&rr, imsg.data, sizeof(rr)); 224 225 if (rde_check_route(&rr) == -1) 226 log_debug("rde_dispatch_imsg: " 227 "packet malformed\n"); 228 break; 229 case IMSG_FULL_REQUEST: 230 bzero(&rr, sizeof(rr)); 231 /* 232 * AFI == 0 && metric == INFINITY request the 233 * whole routing table 234 */ 235 rr.metric = INFINITY; 236 rde_imsg_compose_ripe(IMSG_REQUEST_ADD, 0, 237 0, &rr, sizeof(rr)); 238 rde_imsg_compose_ripe(IMSG_SEND_REQUEST, 0, 239 0, NULL, 0); 240 break; 241 case IMSG_FULL_RESPONSE: 242 rt_snap(imsg.hdr.peerid); 243 rde_imsg_compose_ripe(IMSG_SEND_RESPONSE, 244 imsg.hdr.peerid, 0, NULL, 0); 245 break; 246 case IMSG_ROUTE_REQUEST: 247 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(rr)) 248 fatalx("invalid size of RDE request"); 249 250 memcpy(&rr, imsg.data, sizeof(rr)); 251 252 rt_complete(&rr); 253 rde_imsg_compose_ripe(IMSG_RESPONSE_ADD, 254 imsg.hdr.peerid, 0, &rr, sizeof(rr)); 255 256 break; 257 case IMSG_ROUTE_REQUEST_END: 258 rde_imsg_compose_ripe(IMSG_SEND_RESPONSE, 259 imsg.hdr.peerid, 0, NULL, 0); 260 break; 261 case IMSG_CTL_SHOW_RIB: 262 rt_dump(imsg.hdr.pid); 263 264 imsg_compose_event(iev_ripe, IMSG_CTL_END, 0, 265 imsg.hdr.pid, -1, NULL, 0); 266 267 break; 268 case IMSG_CTL_LOG_VERBOSE: 269 /* already checked by ripe */ 270 memcpy(&verbose, imsg.data, sizeof(verbose)); 271 log_verbose(verbose); 272 break; 273 default: 274 log_debug("rde_dispatch_msg: unexpected imsg %d", 275 imsg.hdr.type); 276 break; 277 } 278 imsg_free(&imsg); 279 } 280 if (!shut) 281 imsg_event_add(iev); 282 else { 283 /* this pipe is dead, so remove the event handler */ 284 event_del(&iev->ev); 285 event_loopexit(NULL); 286 } 287 } 288 289 void 290 rde_dispatch_parent(int fd, short event, void *bula) 291 { 292 struct imsg imsg; 293 struct rt_node *rt; 294 struct kroute kr; 295 struct imsgev *iev = bula; 296 struct imsgbuf *ibuf = &iev->ibuf; 297 ssize_t n; 298 int shut = 0; 299 300 if (event & EV_READ) { 301 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 302 fatal("imsg_read error"); 303 if (n == 0) /* connection closed */ 304 shut = 1; 305 } 306 if (event & EV_WRITE) { 307 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 308 fatal("msgbuf_write"); 309 if (n == 0) /* connection closed */ 310 shut = 1; 311 } 312 313 for (;;) { 314 if ((n = imsg_get(ibuf, &imsg)) == -1) 315 fatal("rde_dispatch_parent: imsg_get error"); 316 if (n == 0) 317 break; 318 319 switch (imsg.hdr.type) { 320 case IMSG_NETWORK_ADD: 321 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(kr)) { 322 log_warnx("rde_dispatch: wrong imsg len"); 323 break; 324 } 325 326 memcpy(&kr, imsg.data, sizeof(kr)); 327 328 rt = rt_new_kr(&kr); 329 rt_insert(rt); 330 break; 331 case IMSG_NETWORK_DEL: 332 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(kr)) { 333 log_warnx("rde_dispatch: wrong imsg len"); 334 break; 335 } 336 memcpy(&kr, imsg.data, sizeof(kr)); 337 338 if ((rt = rt_find(kr.prefix.s_addr, 339 kr.netmask.s_addr)) != NULL) 340 rt_remove(rt); 341 break; 342 default: 343 log_debug("rde_dispatch_parent: unexpected imsg %d", 344 imsg.hdr.type); 345 break; 346 } 347 imsg_free(&imsg); 348 } 349 if (!shut) 350 imsg_event_add(iev); 351 else { 352 /* this pipe is dead, so remove the event handler */ 353 event_del(&iev->ev); 354 event_loopexit(NULL); 355 } 356 } 357 358 void 359 rde_send_change_kroute(struct rt_node *r) 360 { 361 struct kroute kr; 362 363 bzero(&kr, sizeof(kr)); 364 kr.prefix.s_addr = r->prefix.s_addr; 365 kr.nexthop.s_addr = r->nexthop.s_addr; 366 kr.netmask.s_addr = r->netmask.s_addr; 367 kr.metric = r->metric; 368 kr.flags = r->flags; 369 kr.ifindex = r->ifindex; 370 371 imsg_compose_event(iev_main, IMSG_KROUTE_CHANGE, 0, 0, -1, 372 &kr, sizeof(kr)); 373 } 374 375 void 376 rde_send_delete_kroute(struct rt_node *r) 377 { 378 struct kroute kr; 379 380 bzero(&kr, sizeof(kr)); 381 kr.prefix.s_addr = r->prefix.s_addr; 382 kr.nexthop.s_addr = r->nexthop.s_addr; 383 kr.netmask.s_addr = r->netmask.s_addr; 384 kr.metric = r->metric; 385 kr.flags = r->flags; 386 kr.ifindex = r->ifindex; 387 388 imsg_compose_event(iev_main, IMSG_KROUTE_DELETE, 0, 0, -1, 389 &kr, sizeof(kr)); 390 } 391 392 int 393 rde_check_route(struct rip_route *e) 394 { 395 struct timeval tv, now; 396 struct rt_node *rn; 397 struct iface *iface; 398 u_int8_t metric; 399 400 if ((e->nexthop.s_addr & htonl(IN_CLASSA_NET)) == 401 htonl(INADDR_LOOPBACK & IN_CLASSA_NET) || 402 e->nexthop.s_addr == INADDR_ANY) 403 return (-1); 404 405 if ((iface = if_find_index(e->ifindex)) == NULL) 406 return (-1); 407 408 metric = MINIMUM(INFINITY, e->metric + iface->cost); 409 410 if ((rn = rt_find(e->address.s_addr, e->mask.s_addr)) == NULL) { 411 if (metric >= INFINITY) 412 return (0); 413 rn = rt_new_rr(e, metric); 414 rt_insert(rn); 415 rde_send_change_kroute(rn); 416 route_start_timeout(rn); 417 triggered_update(rn); 418 } else { 419 /* 420 * XXX don't we have to track all incoming routes? 421 * what happens if the kernel route is removed later. 422 */ 423 if (rn->flags & F_KERNEL) 424 return (0); 425 426 if (metric < rn->metric) { 427 rn->metric = metric; 428 rn->nexthop.s_addr = e->nexthop.s_addr; 429 rn->ifindex = e->ifindex; 430 rde_send_change_kroute(rn); 431 triggered_update(rn); 432 } else if (e->nexthop.s_addr == rn->nexthop.s_addr && 433 metric > rn->metric) { 434 rn->metric = metric; 435 rde_send_change_kroute(rn); 436 triggered_update(rn); 437 if (rn->metric == INFINITY) 438 route_start_garbage(rn); 439 } else if (e->nexthop.s_addr != rn->nexthop.s_addr && 440 metric == rn->metric) { 441 /* If the new metric is the same as the old one, 442 * examine the timeout for the existing route. If it 443 * is at least halfway to the expiration point, switch 444 * to the new route. 445 */ 446 timerclear(&tv); 447 gettimeofday(&now, NULL); 448 evtimer_pending(&rn->timeout_timer, &tv); 449 if (tv.tv_sec - now.tv_sec < ROUTE_TIMEOUT / 2) { 450 rn->nexthop.s_addr = e->nexthop.s_addr; 451 rn->ifindex = e->ifindex; 452 rde_send_change_kroute(rn); 453 } 454 } 455 456 if (e->nexthop.s_addr == rn->nexthop.s_addr && 457 rn->metric < INFINITY) 458 route_reset_timers(rn); 459 } 460 461 return (0); 462 } 463 464 void 465 triggered_update(struct rt_node *rn) 466 { 467 struct rip_route rr; 468 469 rr.address.s_addr = rn->prefix.s_addr; 470 rr.mask.s_addr = rn->netmask.s_addr; 471 rr.nexthop.s_addr = rn->nexthop.s_addr; 472 rr.metric = rn->metric; 473 rr.ifindex = rn->ifindex; 474 475 rde_imsg_compose_ripe(IMSG_SEND_TRIGGERED_UPDATE, 0, 0, &rr, 476 sizeof(struct rip_route)); 477 } 478