]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/routed/main.c
MFC r338522, r338523, r338533:
[FreeBSD/FreeBSD.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
307         /* prepare socket connected to the kernel.
308          */
309         rt_sock = socket(AF_ROUTE, SOCK_RAW, 0);
310         if (rt_sock < 0)
311                 BADERR(1,"rt_sock = socket()");
312         if (fcntl(rt_sock, F_SETFL, O_NONBLOCK) == -1)
313                 logbad(1, "fcntl(rt_sock) O_NONBLOCK: %s", strerror(errno));
314         off = 0;
315         if (setsockopt(rt_sock, SOL_SOCKET,SO_USELOOPBACK,
316                        &off,sizeof(off)) < 0)
317                 LOGERR("setsockopt(SO_USELOOPBACK,0)");
318
319         fix_select();
320
321
322         if (tracename != 0) {
323                 strncpy(inittracename, tracename, sizeof(inittracename)-1);
324                 set_tracefile(inittracename, "%s", -1);
325         } else {
326                 tracelevel_msg("%s", -1);   /* turn on tracing to stdio */
327         }
328
329         bufinit();
330
331         /* initialize radix tree */
332         rtinit();
333
334         /* Pick a random part of the second for our output to minimize
335          * collisions.
336          *
337          * Start broadcasting after hearing from other routers, and
338          * at a random time so a bunch of systems do not get synchronized
339          * after a power failure.
340          */
341         intvl_random(&next_bcast, EPOCH+MIN_WAITTIME, EPOCH+SUPPLY_INTERVAL);
342         age_timer.tv_usec = next_bcast.tv_usec;
343         age_timer.tv_sec = EPOCH+MIN_WAITTIME;
344         rdisc_timer = next_bcast;
345         ifinit_timer.tv_usec = next_bcast.tv_usec;
346
347         /* Collect an initial view of the world by checking the interface
348          * configuration and the kludge file.
349          */
350         gwkludge();
351         ifinit();
352
353         /* Ask for routes */
354         rip_query();
355         rdisc_sol();
356
357         /* Now turn off stdio if not tracing */
358         if (new_tracelevel == 0)
359                 trace_close(background);
360
361         /* Loop forever, listening and broadcasting.
362          */
363         for (;;) {
364                 prev_clk = clk;
365                 gettimeofday(&clk, 0);
366                 if (prev_clk.tv_sec == clk.tv_sec
367                     && prev_clk.tv_usec == clk.tv_usec+usec_fudge) {
368                         /* Much of `routed` depends on time always advancing.
369                          * On systems that do not guarantee that gettimeofday()
370                          * produces unique timestamps even if called within
371                          * a single tick, use trickery like that in classic
372                          * BSD kernels.
373                          */
374                         clk.tv_usec += ++usec_fudge;
375
376                 } else {
377                         usec_fudge = 0;
378
379                         timevalsub(&t2, &clk, &prev_clk);
380                         if (t2.tv_sec < 0
381                             || t2.tv_sec > wtime.tv_sec + 5) {
382                                 /* Deal with time changes before other
383                                  * housekeeping to keep everything straight.
384                                  */
385                                 dt = t2.tv_sec;
386                                 if (dt > 0)
387                                         dt -= wtime.tv_sec;
388                                 trace_act("time changed by %d sec", (int)dt);
389                                 epoch.tv_sec += dt;
390                         }
391                 }
392                 timevalsub(&now, &clk, &epoch);
393                 now_stale = now.tv_sec - STALE_TIME;
394                 now_expire = now.tv_sec - EXPIRE_TIME;
395                 now_garbage = now.tv_sec - GARBAGE_TIME;
396
397                 /* deal with signals that should affect tracing */
398                 set_tracelevel();
399
400                 if (stopint != 0) {
401                         rip_bcast(0);
402                         rdisc_adv();
403                         trace_off("exiting with signal %d", stopint);
404                         exit(stopint | 128);
405                 }
406
407                 /* look for new or dead interfaces */
408                 timevalsub(&wtime, &ifinit_timer, &now);
409                 if (wtime.tv_sec <= 0) {
410                         wtime.tv_sec = 0;
411                         ifinit();
412                         rip_query();
413                         continue;
414                 }
415
416                 /* Check the kernel table occasionally for mysteriously
417                  * evaporated routes
418                  */
419                 timevalsub(&t2, &flush_kern_timer, &now);
420                 if (t2.tv_sec <= 0) {
421                         flush_kern();
422                         flush_kern_timer.tv_sec = (now.tv_sec
423                                                    + CHECK_QUIET_INTERVAL);
424                         continue;
425                 }
426                 if (timercmp(&t2, &wtime, <))
427                         wtime = t2;
428
429                 /* If it is time, then broadcast our routes.
430                  */
431                 if (supplier || advertise_mhome) {
432                         timevalsub(&t2, &next_bcast, &now);
433                         if (t2.tv_sec <= 0) {
434                                 /* Synchronize the aging and broadcast
435                                  * timers to minimize awakenings
436                                  */
437                                 age(0);
438
439                                 rip_bcast(0);
440
441                                 /* It is desirable to send routing updates
442                                  * regularly.  So schedule the next update
443                                  * 30 seconds after the previous one was
444                                  * scheduled, instead of 30 seconds after
445                                  * the previous update was finished.
446                                  * Even if we just started after discovering
447                                  * a 2nd interface or were otherwise delayed,
448                                  * pick a 30-second anniversary of the
449                                  * original broadcast time.
450                                  */
451                                 n = 1 + (0-t2.tv_sec)/SUPPLY_INTERVAL;
452                                 next_bcast.tv_sec += n*SUPPLY_INTERVAL;
453
454                                 continue;
455                         }
456
457                         if (timercmp(&t2, &wtime, <))
458                                 wtime = t2;
459                 }
460
461                 /* If we need a flash update, either do it now or
462                  * set the delay to end when it is time.
463                  *
464                  * If we are within MIN_WAITTIME seconds of a full update,
465                  * do not bother.
466                  */
467                 if (need_flash
468                     && supplier
469                     && no_flash.tv_sec+MIN_WAITTIME < next_bcast.tv_sec) {
470                         /* accurate to the millisecond */
471                         if (!timercmp(&no_flash, &now, >))
472                                 rip_bcast(1);
473                         timevalsub(&t2, &no_flash, &now);
474                         if (timercmp(&t2, &wtime, <))
475                                 wtime = t2;
476                 }
477
478                 /* trigger the main aging timer.
479                  */
480                 timevalsub(&t2, &age_timer, &now);
481                 if (t2.tv_sec <= 0) {
482                         age(0);
483                         continue;
484                 }
485                 if (timercmp(&t2, &wtime, <))
486                         wtime = t2;
487
488                 /* update the kernel routing table
489                  */
490                 timevalsub(&t2, &need_kern, &now);
491                 if (t2.tv_sec <= 0) {
492                         age(0);
493                         continue;
494                 }
495                 if (timercmp(&t2, &wtime, <))
496                         wtime = t2;
497
498                 /* take care of router discovery,
499                  * but do it in the correct the millisecond
500                  */
501                 if (!timercmp(&rdisc_timer, &now, >)) {
502                         rdisc_age(0);
503                         continue;
504                 }
505                 timevalsub(&t2, &rdisc_timer, &now);
506                 if (timercmp(&t2, &wtime, <))
507                         wtime = t2;
508
509
510                 /* wait for input or a timer to expire.
511                  */
512                 trace_flush();
513                 ibits = fdbits;
514                 n = select(sock_max, &ibits, 0, 0, &wtime);
515                 if (n <= 0) {
516                         if (n < 0 && errno != EINTR && errno != EAGAIN)
517                                 BADERR(1,"select");
518                         continue;
519                 }
520
521                 if (FD_ISSET(rt_sock, &ibits)) {
522                         read_rt();
523                         n--;
524                 }
525                 if (rdisc_sock >= 0 && FD_ISSET(rdisc_sock, &ibits)) {
526                         read_d();
527                         n--;
528                 }
529                 if (rip_sock >= 0 && FD_ISSET(rip_sock, &ibits)) {
530                         read_rip(rip_sock, 0);
531                         n--;
532                 }
533
534                 LIST_FOREACH(ifp, &ifnet, int_list) {
535                         if (n <= 0)
536                                 break;
537                         if (ifp->int_rip_sock >= 0
538                             && FD_ISSET(ifp->int_rip_sock, &ibits)) {
539                                 read_rip(ifp->int_rip_sock, ifp);
540                                 n--;
541                         }
542                 }
543         }
544 }
545
546
547 /* ARGSUSED */
548 static void
549 sigalrm(int s UNUSED)
550 {
551         /* Historically, SIGALRM would cause the daemon to check for
552          * new and broken interfaces.
553          */
554         ifinit_timer.tv_sec = now.tv_sec;
555         trace_act("SIGALRM");
556 }
557
558
559 /* watch for fatal signals */
560 static void
561 sigterm(int sig)
562 {
563         stopint = sig;
564         (void)signal(sig, SIG_DFL);     /* catch it only once */
565 }
566
567
568 void
569 fix_select(void)
570 {
571         struct interface *ifp;
572
573
574         FD_ZERO(&fdbits);
575         sock_max = 0;
576
577         FD_SET(rt_sock, &fdbits);
578         if (sock_max <= rt_sock)
579                 sock_max = rt_sock+1;
580         if (rip_sock >= 0) {
581                 FD_SET(rip_sock, &fdbits);
582                 if (sock_max <= rip_sock)
583                         sock_max = rip_sock+1;
584         }
585         LIST_FOREACH(ifp, &ifnet, int_list) {
586                 if (ifp->int_rip_sock >= 0) {
587                         FD_SET(ifp->int_rip_sock, &fdbits);
588                         if (sock_max <= ifp->int_rip_sock)
589                                 sock_max = ifp->int_rip_sock+1;
590                 }
591         }
592         if (rdisc_sock >= 0) {
593                 FD_SET(rdisc_sock, &fdbits);
594                 if (sock_max <= rdisc_sock)
595                         sock_max = rdisc_sock+1;
596         }
597 }
598
599
600 void
601 fix_sock(int sock,
602          const char *name)
603 {
604         int on;
605 #define MIN_SOCKBUF (4*1024)
606         static int rbuf;
607
608         if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
609                 logbad(1, "fcntl(%s) O_NONBLOCK: %s",
610                        name, strerror(errno));
611         on = 1;
612         if (setsockopt(sock, SOL_SOCKET,SO_BROADCAST, &on,sizeof(on)) < 0)
613                 msglog("setsockopt(%s,SO_BROADCAST): %s",
614                        name, strerror(errno));
615 #ifdef USE_PASSIFNAME
616         on = 1;
617         if (setsockopt(sock, SOL_SOCKET, SO_PASSIFNAME, &on,sizeof(on)) < 0)
618                 msglog("setsockopt(%s,SO_PASSIFNAME): %s",
619                        name, strerror(errno));
620 #endif
621
622         if (rbuf >= MIN_SOCKBUF) {
623                 if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
624                                &rbuf, sizeof(rbuf)) < 0)
625                         msglog("setsockopt(%s,SO_RCVBUF=%d): %s",
626                                name, rbuf, strerror(errno));
627         } else {
628                 for (rbuf = 60*1024; ; rbuf -= 4096) {
629                         if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
630                                        &rbuf, sizeof(rbuf)) == 0) {
631                                 trace_act("RCVBUF=%d", rbuf);
632                                 break;
633                         }
634                         if (rbuf < MIN_SOCKBUF) {
635                                 msglog("setsockopt(%s,SO_RCVBUF = %d): %s",
636                                        name, rbuf, strerror(errno));
637                                 break;
638                         }
639                 }
640         }
641 }
642
643
644 /* get a rip socket
645  */
646 static int                              /* <0 or file descriptor */
647 get_rip_sock(naddr addr,
648              int serious)               /* 1=failure to bind is serious */
649 {
650         struct sockaddr_in rsin;
651         unsigned char ttl;
652         int s;
653
654
655         if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
656                 BADERR(1,"rip_sock = socket()");
657
658         memset(&rsin, 0, sizeof(rsin));
659 #ifdef _HAVE_SIN_LEN
660         rsin.sin_len = sizeof(rsin);
661 #endif
662         rsin.sin_family = AF_INET;
663         rsin.sin_port = htons(RIP_PORT);
664         rsin.sin_addr.s_addr = addr;
665         if (bind(s, (struct sockaddr *)&rsin, sizeof(rsin)) < 0) {
666                 if (serious)
667                         BADERR(errno != EADDRINUSE, "bind(rip_sock)");
668                 return -1;
669         }
670         fix_sock(s,"rip_sock");
671
672         ttl = 1;
673         if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL,
674                        &ttl, sizeof(ttl)) < 0)
675                 DBGERR(1,"rip_sock setsockopt(IP_MULTICAST_TTL)");
676
677         return s;
678 }
679
680
681 /* turn off main RIP socket */
682 void
683 rip_off(void)
684 {
685         struct interface *ifp;
686         naddr addr;
687
688
689         if (rip_sock >= 0 && !mhome) {
690                 trace_act("turn off RIP");
691
692                 (void)close(rip_sock);
693                 rip_sock = -1;
694
695                 /* get non-broadcast sockets to listen to queries.
696                  */
697                 LIST_FOREACH(ifp, &ifnet, int_list) {
698                         if (ifp->int_state & IS_REMOTE)
699                                 continue;
700                         if (ifp->int_rip_sock < 0) {
701                                 addr = ((ifp->int_if_flags & IFF_POINTOPOINT)
702                                         ? ifp->int_dstaddr
703                                         : ifp->int_addr);
704                                 ifp->int_rip_sock = get_rip_sock(addr, 0);
705                         }
706                 }
707
708                 fix_select();
709
710                 age(0);
711         }
712 }
713
714
715 /* turn on RIP multicast input via an interface
716  */
717 static void
718 rip_mcast_on(struct interface *ifp)
719 {
720         struct group_req gr;
721         struct sockaddr_in *sin;
722
723         if (!IS_RIP_IN_OFF(ifp->int_state)
724             && (ifp->int_if_flags & IFF_MULTICAST)
725             && !(ifp->int_state & IS_ALIAS)) {
726                 memset(&gr, 0, sizeof(gr));
727                 gr.gr_interface = ifp->int_index;
728                 sin = (struct sockaddr_in *)&gr.gr_group;
729                 sin->sin_family = AF_INET;
730 #ifdef _HAVE_SIN_LEN
731                 sin->sin_len = sizeof(struct sockaddr_in);
732 #endif
733                 sin->sin_addr.s_addr = htonl(INADDR_RIP_GROUP);
734                 if (setsockopt(rip_sock, IPPROTO_IP, MCAST_JOIN_GROUP,
735                                &gr, sizeof(gr)) < 0)
736                         LOGERR("setsockopt(MCAST_JOIN_GROUP RIP)");
737         }
738 }
739
740
741 /* Prepare socket used for RIP.
742  */
743 void
744 rip_on(struct interface *ifp)
745 {
746         /* If the main RIP socket is already alive, only start receiving
747          * multicasts for this interface.
748          */
749         if (rip_sock >= 0) {
750                 if (ifp != NULL)
751                         rip_mcast_on(ifp);
752                 return;
753         }
754
755         /* If the main RIP socket is off and it makes sense to turn it on,
756          * then turn it on for all of the interfaces.
757          * It makes sense if either router discovery is off, or if
758          * router discover is on and at most one interface is doing RIP.
759          */
760         if (rip_interfaces > 0 && (!rdisc_ok || rip_interfaces > 1)) {
761                 trace_act("turn on RIP");
762
763                 /* Close all of the query sockets so that we can open
764                  * the main socket.  SO_REUSEPORT is not a solution,
765                  * since that would let two daemons bind to the broadcast
766                  * socket.
767                  */
768                 LIST_FOREACH(ifp, &ifnet, int_list) {
769                         if (ifp->int_rip_sock >= 0) {
770                                 (void)close(ifp->int_rip_sock);
771                                 ifp->int_rip_sock = -1;
772                         }
773                 }
774
775                 rip_sock = get_rip_sock(INADDR_ANY, 1);
776                 rip_sock_mcast = NULL;
777
778                 /* Do not advertise anything until we have heard something
779                  */
780                 if (next_bcast.tv_sec < now.tv_sec+MIN_WAITTIME)
781                         next_bcast.tv_sec = now.tv_sec+MIN_WAITTIME;
782
783                 LIST_FOREACH(ifp, &ifnet, int_list) {
784                         ifp->int_query_time = NEVER;
785                         rip_mcast_on(ifp);
786                 }
787                 ifinit_timer.tv_sec = now.tv_sec;
788
789         } else if (ifp != NULL
790                    && !(ifp->int_state & IS_REMOTE)
791                    && ifp->int_rip_sock < 0) {
792                 /* RIP is off, so ensure there are sockets on which
793                  * to listen for queries.
794                  */
795                 ifp->int_rip_sock = get_rip_sock(ifp->int_addr, 0);
796         }
797
798         fix_select();
799 }
800
801
802 /* die if malloc(3) fails
803  */
804 void *
805 rtmalloc(size_t size,
806          const char *msg)
807 {
808         void *p = malloc(size);
809         if (p == NULL)
810                 logbad(1,"malloc(%lu) failed in %s", (u_long)size, msg);
811         return p;
812 }
813
814
815 /* get a random instant in an interval
816  */
817 void
818 intvl_random(struct timeval *tp,        /* put value here */
819              u_long lo,                 /* value is after this second */
820              u_long hi)                 /* and before this */
821 {
822         tp->tv_sec = (time_t)(hi == lo
823                               ? lo
824                               : (lo + arc4random_uniform(1 + hi - lo)));
825         tp->tv_usec = arc4random_uniform(1000000);
826 }
827
828
829 void
830 timevaladd(struct timeval *t1,
831            struct timeval *t2)
832 {
833
834         t1->tv_sec += t2->tv_sec;
835         if ((t1->tv_usec += t2->tv_usec) >= 1000000) {
836                 t1->tv_sec++;
837                 t1->tv_usec -= 1000000;
838         }
839 }
840
841
842 /* t1 = t2 - t3
843  */
844 static void
845 timevalsub(struct timeval *t1,
846            struct timeval *t2,
847            struct timeval *t3)
848 {
849         t1->tv_sec = t2->tv_sec - t3->tv_sec;
850         if ((t1->tv_usec = t2->tv_usec - t3->tv_usec) < 0) {
851                 t1->tv_sec--;
852                 t1->tv_usec += 1000000;
853         }
854 }
855
856
857 /* put a message into the system log
858  */
859 void
860 msglog(const char *p, ...)
861 {
862         va_list args;
863
864         trace_flush();
865
866         va_start(args, p);
867         vsyslog(LOG_ERR, p, args);
868         va_end(args);
869         if (ftrace != NULL) {
870                 if (ftrace == stdout)
871                         (void)fputs("routed: ", ftrace);
872                 va_start(args, p);
873                 (void)vfprintf(ftrace, p, args);
874                 va_end(args);
875                 (void)fputc('\n', ftrace);
876         }
877 }
878
879
880 /* Put a message about a bad system into the system log if
881  * we have not complained about it recently.
882  *
883  * It is desirable to complain about all bad systems, but not too often.
884  * In the worst case, it is not practical to keep track of all bad systems.
885  * For example, there can be many systems with the wrong password.
886  */
887 void
888 msglim(struct msg_limit *lim, naddr addr, const char *p, ...)
889 {
890         va_list args;
891         int i;
892         struct msg_sub *ms1, *ms;
893         const char *p1;
894
895         /* look for the oldest slot in the table
896          * or the slot for the bad router.
897          */
898         ms = ms1 = lim->subs;
899         for (i = MSG_SUBJECT_N; ; i--, ms1++) {
900                 if (i == 0) {
901                         /* Reuse a slot at most once every 10 minutes.
902                          */
903                         if (lim->reuse > now.tv_sec) {
904                                 ms = NULL;
905                         } else {
906                                 ms = ms1;
907                                 lim->reuse = now.tv_sec + 10*60;
908                         }
909                         break;
910                 }
911                 if (ms->addr == addr) {
912                         /* Repeat a complaint about a given system at
913                          * most once an hour.
914                          */
915                         if (ms->until > now.tv_sec)
916                                 ms = NULL;
917                         break;
918                 }
919                 if (ms->until < ms1->until)
920                         ms = ms1;
921         }
922         if (ms != NULL) {
923                 ms->addr = addr;
924                 ms->until = now.tv_sec + 60*60; /* 60 minutes */
925
926                 trace_flush();
927                 for (p1 = p; *p1 == ' '; p1++)
928                         continue;
929                 va_start(args, p);
930                 vsyslog(LOG_ERR, p1, args);
931                 va_end(args);
932         }
933
934         /* always display the message if tracing */
935         if (ftrace != NULL) {
936                 va_start(args, p);
937                 (void)vfprintf(ftrace, p, args);
938                 va_end(args);
939                 (void)fputc('\n', ftrace);
940         }
941 }
942
943
944 void
945 logbad(int dump, const char *p, ...)
946 {
947         va_list args;
948
949         trace_flush();
950
951         va_start(args, p);
952         vsyslog(LOG_ERR, p, args);
953         va_end(args);
954         (void)fputs("routed: ", stderr);
955         va_start(args, p);
956         (void)vfprintf(stderr, p, args);
957         va_end(args);
958         (void)fputs("; giving up\n",stderr);
959         (void)fflush(stderr);
960
961         if (dump)
962                 abort();
963         exit(1);
964 }