1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1983, 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include "defs.h" 33 #include "pathnames.h" 34 #include <signal.h> 35 #include <fcntl.h> 36 #include <sys/file.h> 37 38 __COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993 " 39 "The Regents of the University of California." 40 " All rights reserved."); 41 pid_t mypid; 42 43 naddr myaddr; /* system address */ 44 static char myname[MAXHOSTNAMELEN+1]; 45 46 static int verbose; 47 48 int supplier; /* supply or broadcast updates */ 49 int supplier_set; 50 static int ipforwarding = 1; /* kernel forwarding on */ 51 52 static int default_gateway; /* 1=advertise default */ 53 static int background = 1; 54 int ridhosts; /* 1=reduce host routes */ 55 int mhome; /* 1=want multi-homed host route */ 56 int advertise_mhome; /* 1=must continue advertising it */ 57 int auth_ok = 1; /* 1=ignore auth if we do not care */ 58 int insecure; /* Reply to special queries or not */ 59 60 struct timeval epoch; /* when started */ 61 struct timeval clk; 62 static struct timeval prev_clk; 63 static int usec_fudge; 64 struct timeval now; /* current idea of time */ 65 time_t now_stale; 66 time_t now_expire; 67 time_t now_garbage; 68 69 static struct timeval next_bcast; /* next general broadcast */ 70 struct timeval no_flash = { /* inhibit flash update */ 71 EPOCH+SUPPLY_INTERVAL, 0 72 }; 73 74 static struct timeval flush_kern_timer; 75 76 static fd_set fdbits; 77 static int sock_max; 78 int rip_sock = -1; /* RIP socket */ 79 const struct interface *rip_sock_mcast; /* current multicast interface */ 80 int rt_sock; /* routing socket */ 81 int rt_sock_seqno; 82 83 84 static int get_rip_sock(naddr, int); 85 static void timevalsub(struct timeval *, struct timeval *, struct timeval *); 86 static void sigalrm(int s UNUSED); 87 static void sigterm(int sig); 88 89 int 90 main(int argc, 91 char *argv[]) 92 { 93 int n, mib[4], off; 94 size_t len; 95 char *p, *q; 96 const char *cp; 97 struct timeval wtime, t2; 98 time_t dt; 99 fd_set ibits; 100 naddr p_net, p_mask; 101 struct interface *ifp; 102 struct parm parm; 103 char *tracename = 0; 104 105 106 /* Some shells are badly broken and send SIGHUP to backgrounded 107 * processes. 108 */ 109 signal(SIGHUP, SIG_IGN); 110 111 openlog("routed", LOG_PID, LOG_DAEMON); 112 ftrace = stdout; 113 114 gettimeofday(&clk, 0); 115 prev_clk = clk; 116 epoch = clk; 117 epoch.tv_sec -= EPOCH; 118 now.tv_sec = EPOCH; 119 now_stale = EPOCH - STALE_TIME; 120 now_expire = EPOCH - EXPIRE_TIME; 121 now_garbage = EPOCH - GARBAGE_TIME; 122 wtime.tv_sec = 0; 123 124 (void)gethostname(myname, sizeof(myname)-1); 125 (void)gethost(myname, &myaddr); 126 127 while ((n = getopt(argc, argv, "isqdghmAtvT:F:P:")) != -1) { 128 switch (n) { 129 case 'i': 130 insecure++; 131 break; 132 case 's': 133 supplier = 1; 134 supplier_set = 1; 135 break; 136 137 case 'q': 138 supplier = 0; 139 supplier_set = 1; 140 break; 141 142 case 'd': 143 background = 0; 144 break; 145 146 case 'g': 147 memset(&parm, 0, sizeof(parm)); 148 parm.parm_d_metric = 1; 149 cp = check_parms(&parm); 150 if (cp != 0) 151 msglog("bad -g: %s", cp); 152 else 153 default_gateway = 1; 154 break; 155 156 case 'h': /* suppress extra host routes */ 157 ridhosts = 1; 158 break; 159 160 case 'm': /* advertise host route */ 161 mhome = 1; /* on multi-homed hosts */ 162 break; 163 164 case 'A': 165 /* Ignore authentication if we do not care. 166 * Crazy as it is, that is what RFC 1723 requires. 167 */ 168 auth_ok = 0; 169 break; 170 171 case 't': 172 new_tracelevel++; 173 break; 174 175 case 'T': 176 tracename = optarg; 177 break; 178 179 case 'F': /* minimal routes for SLIP */ 180 n = FAKE_METRIC; 181 p = strchr(optarg,','); 182 if (p && *p != '\0') { 183 n = (int)strtoul(p+1, &q, 0); 184 if (*q == '\0' 185 && n <= HOPCNT_INFINITY-1 186 && n >= 1) 187 *p = '\0'; 188 } 189 if (!getnet(optarg, &p_net, &p_mask)) { 190 msglog("bad network; \"-F %s\"", 191 optarg); 192 break; 193 } 194 memset(&parm, 0, sizeof(parm)); 195 parm.parm_net = p_net; 196 parm.parm_mask = p_mask; 197 parm.parm_d_metric = n; 198 cp = check_parms(&parm); 199 if (cp != 0) 200 msglog("bad -F: %s", cp); 201 break; 202 203 case 'P': 204 /* handle arbitrary parameters. 205 */ 206 q = strdup(optarg); 207 cp = parse_parms(q, 0); 208 if (cp != 0) 209 msglog("%s in \"-P %s\"", cp, optarg); 210 free(q); 211 break; 212 213 case 'v': 214 /* display version */ 215 verbose++; 216 msglog("version 2.31"); 217 break; 218 219 default: 220 goto usage; 221 } 222 } 223 argc -= optind; 224 argv += optind; 225 226 if (tracename == 0 && argc >= 1) { 227 tracename = *argv++; 228 argc--; 229 } 230 if (tracename != 0 && tracename[0] == '\0') 231 goto usage; 232 if (argc != 0) { 233 usage: 234 logbad(0, "usage: routed [-sqdghmAtv] [-T tracefile]" 235 " [-F net[,metric]] [-P parms]"); 236 } 237 if (geteuid() != 0) { 238 if (verbose) 239 exit(0); 240 logbad(0, "requires UID 0"); 241 } 242 243 mib[0] = CTL_NET; 244 mib[1] = PF_INET; 245 mib[2] = IPPROTO_IP; 246 mib[3] = IPCTL_FORWARDING; 247 len = sizeof(ipforwarding); 248 if (sysctl(mib, 4, &ipforwarding, &len, 0, 0) < 0) 249 LOGERR("sysctl(IPCTL_FORWARDING)"); 250 251 if (!ipforwarding) { 252 if (supplier) 253 msglog("-s incompatible with ipforwarding=0"); 254 if (default_gateway) { 255 msglog("-g incompatible with ipforwarding=0"); 256 default_gateway = 0; 257 } 258 supplier = 0; 259 supplier_set = 1; 260 } 261 if (default_gateway) { 262 if (supplier_set && !supplier) { 263 msglog("-g and -q incompatible"); 264 } else { 265 supplier = 1; 266 supplier_set = 1; 267 } 268 } 269 270 271 signal(SIGALRM, sigalrm); 272 if (!background) 273 signal(SIGHUP, sigterm); /* SIGHUP fatal during debugging */ 274 signal(SIGTERM, sigterm); 275 signal(SIGINT, sigterm); 276 signal(SIGUSR1, sigtrace_on); 277 signal(SIGUSR2, sigtrace_off); 278 279 /* get into the background */ 280 if (background && daemon(0, 1) < 0) 281 BADERR(0,"daemon()"); 282 283 mypid = getpid(); 284 285 /* prepare socket connected to the kernel. 286 */ 287 rt_sock = socket(AF_ROUTE, SOCK_RAW, 0); 288 if (rt_sock < 0) 289 BADERR(1,"rt_sock = socket()"); 290 if (fcntl(rt_sock, F_SETFL, O_NONBLOCK) == -1) 291 logbad(1, "fcntl(rt_sock) O_NONBLOCK: %s", strerror(errno)); 292 off = 0; 293 if (setsockopt(rt_sock, SOL_SOCKET,SO_USELOOPBACK, 294 &off,sizeof(off)) < 0) 295 LOGERR("setsockopt(SO_USELOOPBACK,0)"); 296 297 fix_select(); 298 299 300 if (tracename != 0) { 301 strncpy(inittracename, tracename, sizeof(inittracename)-1); 302 set_tracefile(inittracename, "%s", -1); 303 } else { 304 tracelevel_msg("%s", -1); /* turn on tracing to stdio */ 305 } 306 307 bufinit(); 308 309 /* initialize radix tree */ 310 rtinit(); 311 312 /* Pick a random part of the second for our output to minimize 313 * collisions. 314 * 315 * Start broadcasting after hearing from other routers, and 316 * at a random time so a bunch of systems do not get synchronized 317 * after a power failure. 318 */ 319 intvl_random(&next_bcast, EPOCH+MIN_WAITTIME, EPOCH+SUPPLY_INTERVAL); 320 age_timer.tv_usec = next_bcast.tv_usec; 321 age_timer.tv_sec = EPOCH+MIN_WAITTIME; 322 rdisc_timer = next_bcast; 323 ifinit_timer.tv_usec = next_bcast.tv_usec; 324 325 /* Collect an initial view of the world by checking the interface 326 * configuration and the kludge file. 327 */ 328 gwkludge(); 329 ifinit(); 330 331 /* Ask for routes */ 332 rip_query(); 333 rdisc_sol(); 334 335 /* Now turn off stdio if not tracing */ 336 if (new_tracelevel == 0) 337 trace_close(background); 338 339 /* Loop forever, listening and broadcasting. 340 */ 341 for (;;) { 342 prev_clk = clk; 343 gettimeofday(&clk, 0); 344 if (prev_clk.tv_sec == clk.tv_sec 345 && prev_clk.tv_usec == clk.tv_usec+usec_fudge) { 346 /* Much of `routed` depends on time always advancing. 347 * On systems that do not guarantee that gettimeofday() 348 * produces unique timestamps even if called within 349 * a single tick, use trickery like that in classic 350 * BSD kernels. 351 */ 352 clk.tv_usec += ++usec_fudge; 353 354 } else { 355 usec_fudge = 0; 356 357 timevalsub(&t2, &clk, &prev_clk); 358 if (t2.tv_sec < 0 359 || t2.tv_sec > wtime.tv_sec + 5) { 360 /* Deal with time changes before other 361 * housekeeping to keep everything straight. 362 */ 363 dt = t2.tv_sec; 364 if (dt > 0) 365 dt -= wtime.tv_sec; 366 trace_act("time changed by %d sec", (int)dt); 367 epoch.tv_sec += dt; 368 } 369 } 370 timevalsub(&now, &clk, &epoch); 371 now_stale = now.tv_sec - STALE_TIME; 372 now_expire = now.tv_sec - EXPIRE_TIME; 373 now_garbage = now.tv_sec - GARBAGE_TIME; 374 375 /* deal with signals that should affect tracing */ 376 set_tracelevel(); 377 378 if (stopint != 0) { 379 rip_bcast(0); 380 rdisc_adv(); 381 trace_off("exiting with signal %d", stopint); 382 exit(stopint | 128); 383 } 384 385 /* look for new or dead interfaces */ 386 timevalsub(&wtime, &ifinit_timer, &now); 387 if (wtime.tv_sec <= 0) { 388 wtime.tv_sec = 0; 389 ifinit(); 390 rip_query(); 391 continue; 392 } 393 394 /* Check the kernel table occasionally for mysteriously 395 * evaporated routes 396 */ 397 timevalsub(&t2, &flush_kern_timer, &now); 398 if (t2.tv_sec <= 0) { 399 flush_kern(); 400 flush_kern_timer.tv_sec = (now.tv_sec 401 + CHECK_QUIET_INTERVAL); 402 continue; 403 } 404 if (timercmp(&t2, &wtime, <)) 405 wtime = t2; 406 407 /* If it is time, then broadcast our routes. 408 */ 409 if (supplier || advertise_mhome) { 410 timevalsub(&t2, &next_bcast, &now); 411 if (t2.tv_sec <= 0) { 412 /* Synchronize the aging and broadcast 413 * timers to minimize awakenings 414 */ 415 age(0); 416 417 rip_bcast(0); 418 419 /* It is desirable to send routing updates 420 * regularly. So schedule the next update 421 * 30 seconds after the previous one was 422 * scheduled, instead of 30 seconds after 423 * the previous update was finished. 424 * Even if we just started after discovering 425 * a 2nd interface or were otherwise delayed, 426 * pick a 30-second anniversary of the 427 * original broadcast time. 428 */ 429 n = 1 + (0-t2.tv_sec)/SUPPLY_INTERVAL; 430 next_bcast.tv_sec += n*SUPPLY_INTERVAL; 431 432 continue; 433 } 434 435 if (timercmp(&t2, &wtime, <)) 436 wtime = t2; 437 } 438 439 /* If we need a flash update, either do it now or 440 * set the delay to end when it is time. 441 * 442 * If we are within MIN_WAITTIME seconds of a full update, 443 * do not bother. 444 */ 445 if (need_flash 446 && supplier 447 && no_flash.tv_sec+MIN_WAITTIME < next_bcast.tv_sec) { 448 /* accurate to the millisecond */ 449 if (!timercmp(&no_flash, &now, >)) 450 rip_bcast(1); 451 timevalsub(&t2, &no_flash, &now); 452 if (timercmp(&t2, &wtime, <)) 453 wtime = t2; 454 } 455 456 /* trigger the main aging timer. 457 */ 458 timevalsub(&t2, &age_timer, &now); 459 if (t2.tv_sec <= 0) { 460 age(0); 461 continue; 462 } 463 if (timercmp(&t2, &wtime, <)) 464 wtime = t2; 465 466 /* update the kernel routing table 467 */ 468 timevalsub(&t2, &need_kern, &now); 469 if (t2.tv_sec <= 0) { 470 age(0); 471 continue; 472 } 473 if (timercmp(&t2, &wtime, <)) 474 wtime = t2; 475 476 /* take care of router discovery, 477 * but do it in the correct the millisecond 478 */ 479 if (!timercmp(&rdisc_timer, &now, >)) { 480 rdisc_age(0); 481 continue; 482 } 483 timevalsub(&t2, &rdisc_timer, &now); 484 if (timercmp(&t2, &wtime, <)) 485 wtime = t2; 486 487 488 /* wait for input or a timer to expire. 489 */ 490 trace_flush(); 491 ibits = fdbits; 492 n = select(sock_max, &ibits, 0, 0, &wtime); 493 if (n <= 0) { 494 if (n < 0 && errno != EINTR && errno != EAGAIN) 495 BADERR(1,"select"); 496 continue; 497 } 498 499 if (FD_ISSET(rt_sock, &ibits)) { 500 read_rt(); 501 n--; 502 } 503 if (rdisc_sock >= 0 && FD_ISSET(rdisc_sock, &ibits)) { 504 read_d(); 505 n--; 506 } 507 if (rip_sock >= 0 && FD_ISSET(rip_sock, &ibits)) { 508 read_rip(rip_sock, 0); 509 n--; 510 } 511 512 LIST_FOREACH(ifp, &ifnet, int_list) { 513 if (n <= 0) 514 break; 515 if (ifp->int_rip_sock >= 0 516 && FD_ISSET(ifp->int_rip_sock, &ibits)) { 517 read_rip(ifp->int_rip_sock, ifp); 518 n--; 519 } 520 } 521 } 522 } 523 524 525 /* ARGSUSED */ 526 static void 527 sigalrm(int s UNUSED) 528 { 529 /* Historically, SIGALRM would cause the daemon to check for 530 * new and broken interfaces. 531 */ 532 ifinit_timer.tv_sec = now.tv_sec; 533 trace_act("SIGALRM"); 534 } 535 536 537 /* watch for fatal signals */ 538 static void 539 sigterm(int sig) 540 { 541 stopint = sig; 542 (void)signal(sig, SIG_DFL); /* catch it only once */ 543 } 544 545 546 void 547 fix_select(void) 548 { 549 struct interface *ifp; 550 551 552 FD_ZERO(&fdbits); 553 sock_max = 0; 554 555 FD_SET(rt_sock, &fdbits); 556 if (sock_max <= rt_sock) 557 sock_max = rt_sock+1; 558 if (rip_sock >= 0) { 559 FD_SET(rip_sock, &fdbits); 560 if (sock_max <= rip_sock) 561 sock_max = rip_sock+1; 562 } 563 LIST_FOREACH(ifp, &ifnet, int_list) { 564 if (ifp->int_rip_sock >= 0) { 565 FD_SET(ifp->int_rip_sock, &fdbits); 566 if (sock_max <= ifp->int_rip_sock) 567 sock_max = ifp->int_rip_sock+1; 568 } 569 } 570 if (rdisc_sock >= 0) { 571 FD_SET(rdisc_sock, &fdbits); 572 if (sock_max <= rdisc_sock) 573 sock_max = rdisc_sock+1; 574 } 575 } 576 577 578 void 579 fix_sock(int sock, 580 const char *name) 581 { 582 int on; 583 #define MIN_SOCKBUF (4*1024) 584 static int rbuf; 585 586 if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) 587 logbad(1, "fcntl(%s) O_NONBLOCK: %s", 588 name, strerror(errno)); 589 on = 1; 590 if (setsockopt(sock, SOL_SOCKET,SO_BROADCAST, &on,sizeof(on)) < 0) 591 msglog("setsockopt(%s,SO_BROADCAST): %s", 592 name, strerror(errno)); 593 #ifdef USE_PASSIFNAME 594 on = 1; 595 if (setsockopt(sock, SOL_SOCKET, SO_PASSIFNAME, &on,sizeof(on)) < 0) 596 msglog("setsockopt(%s,SO_PASSIFNAME): %s", 597 name, strerror(errno)); 598 #endif 599 600 if (rbuf >= MIN_SOCKBUF) { 601 if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, 602 &rbuf, sizeof(rbuf)) < 0) 603 msglog("setsockopt(%s,SO_RCVBUF=%d): %s", 604 name, rbuf, strerror(errno)); 605 } else { 606 for (rbuf = 60*1024; ; rbuf -= 4096) { 607 if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, 608 &rbuf, sizeof(rbuf)) == 0) { 609 trace_act("RCVBUF=%d", rbuf); 610 break; 611 } 612 if (rbuf < MIN_SOCKBUF) { 613 msglog("setsockopt(%s,SO_RCVBUF = %d): %s", 614 name, rbuf, strerror(errno)); 615 break; 616 } 617 } 618 } 619 } 620 621 622 /* get a rip socket 623 */ 624 static int /* <0 or file descriptor */ 625 get_rip_sock(naddr addr, 626 int serious) /* 1=failure to bind is serious */ 627 { 628 struct sockaddr_in rsin; 629 unsigned char ttl; 630 int s; 631 632 633 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 634 BADERR(1,"rip_sock = socket()"); 635 636 memset(&rsin, 0, sizeof(rsin)); 637 #ifdef _HAVE_SIN_LEN 638 rsin.sin_len = sizeof(rsin); 639 #endif 640 rsin.sin_family = AF_INET; 641 rsin.sin_port = htons(RIP_PORT); 642 rsin.sin_addr.s_addr = addr; 643 if (bind(s, (struct sockaddr *)&rsin, sizeof(rsin)) < 0) { 644 if (serious) 645 BADERR(errno != EADDRINUSE, "bind(rip_sock)"); 646 close(s); 647 return -1; 648 } 649 fix_sock(s,"rip_sock"); 650 651 ttl = 1; 652 if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, 653 &ttl, sizeof(ttl)) < 0) 654 DBGERR(1,"rip_sock setsockopt(IP_MULTICAST_TTL)"); 655 656 return s; 657 } 658 659 660 /* turn off main RIP socket */ 661 void 662 rip_off(void) 663 { 664 struct interface *ifp; 665 naddr addr; 666 667 668 if (rip_sock >= 0 && !mhome) { 669 trace_act("turn off RIP"); 670 671 (void)close(rip_sock); 672 rip_sock = -1; 673 674 /* get non-broadcast sockets to listen to queries. 675 */ 676 LIST_FOREACH(ifp, &ifnet, int_list) { 677 if (ifp->int_state & IS_REMOTE) 678 continue; 679 if (ifp->int_rip_sock < 0) { 680 addr = ((ifp->int_if_flags & IFF_POINTOPOINT) 681 ? ifp->int_dstaddr 682 : ifp->int_addr); 683 ifp->int_rip_sock = get_rip_sock(addr, 0); 684 } 685 } 686 687 fix_select(); 688 689 age(0); 690 } 691 } 692 693 694 /* turn on RIP multicast input via an interface 695 */ 696 static void 697 rip_mcast_on(struct interface *ifp) 698 { 699 struct group_req gr; 700 struct sockaddr_in *sin; 701 702 if (!IS_RIP_IN_OFF(ifp->int_state) 703 && (ifp->int_if_flags & IFF_MULTICAST) 704 && !(ifp->int_state & IS_ALIAS)) { 705 memset(&gr, 0, sizeof(gr)); 706 gr.gr_interface = ifp->int_index; 707 sin = (struct sockaddr_in *)&gr.gr_group; 708 sin->sin_family = AF_INET; 709 #ifdef _HAVE_SIN_LEN 710 sin->sin_len = sizeof(struct sockaddr_in); 711 #endif 712 sin->sin_addr.s_addr = htonl(INADDR_RIP_GROUP); 713 if (setsockopt(rip_sock, IPPROTO_IP, MCAST_JOIN_GROUP, 714 &gr, sizeof(gr)) < 0) 715 LOGERR("setsockopt(MCAST_JOIN_GROUP RIP)"); 716 } 717 } 718 719 720 /* Prepare socket used for RIP. 721 */ 722 void 723 rip_on(struct interface *ifp) 724 { 725 /* If the main RIP socket is already alive, only start receiving 726 * multicasts for this interface. 727 */ 728 if (rip_sock >= 0) { 729 if (ifp != NULL) 730 rip_mcast_on(ifp); 731 return; 732 } 733 734 /* If the main RIP socket is off and it makes sense to turn it on, 735 * then turn it on for all of the interfaces. 736 * It makes sense if either router discovery is off, or if 737 * router discover is on and at most one interface is doing RIP. 738 */ 739 if (rip_interfaces > 0 && (!rdisc_ok || rip_interfaces > 1)) { 740 trace_act("turn on RIP"); 741 742 /* Close all of the query sockets so that we can open 743 * the main socket. SO_REUSEPORT is not a solution, 744 * since that would let two daemons bind to the broadcast 745 * socket. 746 */ 747 LIST_FOREACH(ifp, &ifnet, int_list) { 748 if (ifp->int_rip_sock >= 0) { 749 (void)close(ifp->int_rip_sock); 750 ifp->int_rip_sock = -1; 751 } 752 } 753 754 rip_sock = get_rip_sock(INADDR_ANY, 1); 755 rip_sock_mcast = NULL; 756 757 /* Do not advertise anything until we have heard something 758 */ 759 if (next_bcast.tv_sec < now.tv_sec+MIN_WAITTIME) 760 next_bcast.tv_sec = now.tv_sec+MIN_WAITTIME; 761 762 LIST_FOREACH(ifp, &ifnet, int_list) { 763 ifp->int_query_time = NEVER; 764 rip_mcast_on(ifp); 765 } 766 ifinit_timer.tv_sec = now.tv_sec; 767 768 } else if (ifp != NULL 769 && !(ifp->int_state & IS_REMOTE) 770 && ifp->int_rip_sock < 0) { 771 /* RIP is off, so ensure there are sockets on which 772 * to listen for queries. 773 */ 774 ifp->int_rip_sock = get_rip_sock(ifp->int_addr, 0); 775 } 776 777 fix_select(); 778 } 779 780 781 /* die if malloc(3) fails 782 */ 783 void * 784 rtmalloc(size_t size, 785 const char *msg) 786 { 787 void *p = malloc(size); 788 if (p == NULL) 789 logbad(1,"malloc(%lu) failed in %s", (u_long)size, msg); 790 return p; 791 } 792 793 794 /* get a random instant in an interval 795 */ 796 void 797 intvl_random(struct timeval *tp, /* put value here */ 798 u_long lo, /* value is after this second */ 799 u_long hi) /* and before this */ 800 { 801 tp->tv_sec = (time_t)(hi == lo 802 ? lo 803 : (lo + arc4random_uniform(1 + hi - lo))); 804 tp->tv_usec = arc4random_uniform(1000000); 805 } 806 807 808 void 809 timevaladd(struct timeval *t1, 810 struct timeval *t2) 811 { 812 813 t1->tv_sec += t2->tv_sec; 814 if ((t1->tv_usec += t2->tv_usec) >= 1000000) { 815 t1->tv_sec++; 816 t1->tv_usec -= 1000000; 817 } 818 } 819 820 821 /* t1 = t2 - t3 822 */ 823 static void 824 timevalsub(struct timeval *t1, 825 struct timeval *t2, 826 struct timeval *t3) 827 { 828 t1->tv_sec = t2->tv_sec - t3->tv_sec; 829 if ((t1->tv_usec = t2->tv_usec - t3->tv_usec) < 0) { 830 t1->tv_sec--; 831 t1->tv_usec += 1000000; 832 } 833 } 834 835 836 /* put a message into the system log 837 */ 838 void 839 msglog(const char *p, ...) 840 { 841 va_list args; 842 843 trace_flush(); 844 845 va_start(args, p); 846 vsyslog(LOG_ERR, p, args); 847 va_end(args); 848 if (ftrace != NULL) { 849 if (ftrace == stdout) 850 (void)fputs("routed: ", ftrace); 851 va_start(args, p); 852 (void)vfprintf(ftrace, p, args); 853 va_end(args); 854 (void)fputc('\n', ftrace); 855 } 856 } 857 858 859 /* Put a message about a bad system into the system log if 860 * we have not complained about it recently. 861 * 862 * It is desirable to complain about all bad systems, but not too often. 863 * In the worst case, it is not practical to keep track of all bad systems. 864 * For example, there can be many systems with the wrong password. 865 */ 866 void 867 msglim(struct msg_limit *lim, naddr addr, const char *p, ...) 868 { 869 va_list args; 870 int i; 871 struct msg_sub *ms1, *ms; 872 const char *p1; 873 874 /* look for the oldest slot in the table 875 * or the slot for the bad router. 876 */ 877 ms = ms1 = lim->subs; 878 for (i = MSG_SUBJECT_N; ; i--, ms1++) { 879 if (i == 0) { 880 /* Reuse a slot at most once every 10 minutes. 881 */ 882 if (lim->reuse > now.tv_sec) { 883 ms = NULL; 884 } else { 885 ms = ms1; 886 lim->reuse = now.tv_sec + 10*60; 887 } 888 break; 889 } 890 if (ms->addr == addr) { 891 /* Repeat a complaint about a given system at 892 * most once an hour. 893 */ 894 if (ms->until > now.tv_sec) 895 ms = NULL; 896 break; 897 } 898 if (ms->until < ms1->until) 899 ms = ms1; 900 } 901 if (ms != NULL) { 902 ms->addr = addr; 903 ms->until = now.tv_sec + 60*60; /* 60 minutes */ 904 905 trace_flush(); 906 for (p1 = p; *p1 == ' '; p1++) 907 continue; 908 va_start(args, p); 909 vsyslog(LOG_ERR, p1, args); 910 va_end(args); 911 } 912 913 /* always display the message if tracing */ 914 if (ftrace != NULL) { 915 va_start(args, p); 916 (void)vfprintf(ftrace, p, args); 917 va_end(args); 918 (void)fputc('\n', ftrace); 919 } 920 } 921 922 923 void 924 logbad(int dump, const char *p, ...) 925 { 926 va_list args; 927 928 trace_flush(); 929 930 va_start(args, p); 931 vsyslog(LOG_ERR, p, args); 932 va_end(args); 933 (void)fputs("routed: ", stderr); 934 va_start(args, p); 935 (void)vfprintf(stderr, p, args); 936 va_end(args); 937 (void)fputs("; giving up\n",stderr); 938 (void)fflush(stderr); 939 940 if (dump) 941 abort(); 942 exit(1); 943 } 944