* Copyright (c) 1983, 1988 Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
"@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\
static char sccsid
[] = "@(#)main.c 5.23 (Berkeley) 7/1/91";
* Routing Table Management Daemon
int supplier
= -1; /* process should supply updates */
int gateway
= 0; /* 1 if we are a gateway to parts beyond */
int bufspace
= 127*1024; /* max. input buffer size to request */
struct rip
*msg
= (struct rip
*)packet
;
void hup(), rtdeleteall(), sigtrace(), timer();
int n
, cc
, nfd
, omask
, tflags
= 0;
struct timeval
*tvp
, waittime
;
register struct rip
*query
= msg
;
openlog("routed", LOG_PID
| LOG_ODELAY
, LOG_DAEMON
);
setlogmask(LOG_UPTO(LOG_WARNING
));
openlog("routed", LOG_PID
);
#define setlogmask(x) (x)
sp
= getservbyname("router", "udp");
fprintf(stderr
, "routed: router/udp: unknown service\n");
addr
.sin_family
= AF_INET
;
addr
.sin_port
= sp
->s_port
;
s
= getsocket(AF_INET
, SOCK_DGRAM
, &addr
);
while (argc
> 0 && **argv
== '-') {
if (strcmp(*argv
, "-s") == 0) {
if (strcmp(*argv
, "-q") == 0) {
if (strcmp(*argv
, "-t") == 0) {
setlogmask(LOG_UPTO(LOG_DEBUG
));
if (strcmp(*argv
, "-d") == 0) {
setlogmask(LOG_UPTO(LOG_DEBUG
));
if (strcmp(*argv
, "-g") == 0) {
"usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n");
* Any extra argument is considered
(void) gettimeofday(&now
, (struct timezone
*)NULL
);
* Collect an initial view of the world by
* checking the interface configuration and the gateway kludge
* file. Then, send a request packet on all
* directly connected networks to find out what
query
->rip_cmd
= RIPCMD_REQUEST
;
query
->rip_vers
= RIPVERSION
;
if (sizeof(query
->rip_nets
[0].rip_dst
.sa_family
) > 1) /* XXX */
query
->rip_nets
[0].rip_dst
.sa_family
= htons((u_short
)AF_UNSPEC
);
query
->rip_nets
[0].rip_dst
.sa_family
= AF_UNSPEC
;
query
->rip_nets
[0].rip_metric
= htonl((u_long
)HOPCNT_INFINITY
);
signal(SIGINT
, rtdeleteall
);
signal(SIGUSR1
, sigtrace
);
signal(SIGUSR2
, sigtrace
);
itval
.it_interval
.tv_sec
= TIMER_RATE
;
itval
.it_value
.tv_sec
= TIMER_RATE
;
itval
.it_interval
.tv_usec
= 0;
itval
.it_value
.tv_usec
= 0;
if (setitimer(ITIMER_REAL
, &itval
, (struct itimerval
*)NULL
) < 0)
syslog(LOG_ERR
, "setitimer: %m\n");
nfd
= s
+ 1; /* 1 + max(fd's) */
* If we need a dynamic update that was held off,
* needupdate will be set, and nextbcast is the time
* by which we want select to return. Compute time
* until dynamic update should be sent, and select only
* until then. If we have already passed nextbcast,
timevalsub(&waittime
, &now
);
if (waittime
.tv_sec
< 0) {
"select until dynamic update %d/%d sec/usec\n",
waittime
.tv_sec
, waittime
.tv_usec
);
tvp
= (struct timeval
*)NULL
;
n
= select(nfd
, &ibits
, 0, 0, tvp
);
* Need delayed dynamic update if select returned
* nothing and we timed out. Otherwise, ignore
syslog(LOG_ERR
, "select: %m");
omask
= sigblock(sigmask(SIGALRM
));
if (n
== 0 && needupdate
) {
"send delayed dynamic update\n");
(void) gettimeofday(&now
,
(struct timezone
*)NULL
);
toall(supply
, RTS_CHANGED
,
(struct interface
*)NULL
);
(void) gettimeofday(&now
, (struct timezone
*)NULL
);
omask
= sigblock(sigmask(SIGALRM
));
printf("s %d, ibits %x index %d, mod %d, sh %x, or %x &ibits %x\n",
(s)/(sizeof(fd_mask) * 8),
((s) % (sizeof(fd_mask) * 8)),
(1 << ((s) % (sizeof(fd_mask) * 8))),
ibits.fds_bits[(s)/(sizeof(fd_mask) * 8)] & (1 << ((s) % (sizeof(fd_mask) * 8))),
if (ibits
.fds_bits
[s
/32] & (1 << s
))
/* handle ICMP redirects */
t1
->tv_sec
+= t2
->tv_sec
;
if ((t1
->tv_usec
+= t2
->tv_usec
) > 1000000) {
t1
->tv_sec
-= t2
->tv_sec
;
if ((t1
->tv_usec
-= t2
->tv_usec
) < 0) {
char buf
[MAXPACKETSIZE
+1];
cc
= recvfrom(fd
, &inbuf
, sizeof (inbuf
), 0, &from
, &fromlen
);
if (cc
< 0 && errno
!= EWOULDBLOCK
)
if (fromlen
!= sizeof (struct sockaddr_in
))
rip_input(&from
, &inbuf
.rip
, cc
);
getsocket(domain
, type
, sin
)
if ((sock
= socket(domain
, type
, 0)) < 0) {
syslog(LOG_ERR
, "socket: %m");
if (setsockopt(sock
, SOL_SOCKET
, SO_BROADCAST
, &on
, sizeof (on
)) < 0) {
syslog(LOG_ERR
, "setsockopt SO_BROADCAST: %m");
for (on
= bufspace
; ; on
-= 1024) {
if (setsockopt(sock
, SOL_SOCKET
, SO_RCVBUF
,
syslog(LOG_ERR
, "setsockopt SO_RCVBUF: %m");
fprintf(ftrace
, "recv buf %d\n", on
);
if (bind(sock
, (struct sockaddr
*)sin
, sizeof (*sin
)) < 0) {
syslog(LOG_ERR
, "bind: %m");
if (fcntl(sock
, F_SETFL
, O_NONBLOCK
) == -1)
syslog(LOG_ERR
, "fcntl O_NONBLOCK: %m\n");