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