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