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