Äèïëîìíàÿ ðàáîòà: Àëãîðèòìè ìàðøðóòèçàö³¿ â ìåðåæàõ
*/
rt_sock = socket(AF_ROUTE, SOCK_RAW, 0);
if (rt_sock < 0)
BADERR(1,"rt_sock = socket()");
if (fcntl(rt_sock, F_SETFL, O_NONBLOCK) == -1)
logbad(1, "fcntl(rt_sock) O_NONBLOCK:
%s", strerror(errno));
off = 0;
if (setsockopt(rt_sock, SOL_SOCKET,SO_USELOOPBACK,
&off,sizeof(off)) < 0)
LOGERR("setsockopt(SO_USELOOPBACK,0)");
fix_select();
if (background && new_tracelevel == 0)
ftrace = 0;
if (tracename != 0) {
strncpy(inittracename, tracename, sizeof(inittracename)-1);
set_tracefile(inittracename, "%s\n", -1);
} else {
tracelevel_msg("%s\n", -1); /* turn on
tracing to stdio */
}
bufinit();
/* initialize radix tree */
rtinit();
/* Pick a random part of the second for our output to minimize
* collisions.
*
* Start broadcasting after hearing from other routers, and
* at a random time so a bunch of systems do not get
synchronized
* after a power failure.
*/
intvl_random(&next_bcast, EPOCH+MIN_WAITTIME,
EPOCH+SUPPLY_INTERVAL);
age_timer.tv_usec = next_bcast.tv_usec;
age_timer.tv_sec = EPOCH+MIN_WAITTIME;
rdisc_timer = next_bcast;
ifinit_timer.tv_usec = next_bcast.tv_usec;
/* Collect an initial view of the world by checking the
interface
* configuration and the kludge file.
*/
gwkludge();
ifinit();
flush_kern();
/* Ask for routes */
rip_query();
rdisc_sol();
/* Loop forever, listening and broadcasting.
*/
for (;;) {
prev_clk = clk;
gettimeofday(&clk, 0);
timevalsub(&t2, &clk, &prev_clk);
if (t2.tv_sec < 0
|| t2.tv_sec > wtime.tv_sec + 5) {
/* Deal with time changes before other
housekeeping to
* keep everything straight.
*/
dt = t2.tv_sec;
if (dt > 0)
dt -= wtime.tv_sec;
trace_act("time changed by %d
sec", dt);
epoch.tv_sec += dt;
}
timevalsub(&now, &clk, &epoch);
now_stale = now.tv_sec - STALE_TIME;
now_expire = now.tv_sec - EXPIRE_TIME;
now_garbage = now.tv_sec - GARBAGE_TIME;
/* deal with signals that should affect tracing */
set_tracelevel();
if (stopint != 0)
/* look for new or dead interfaces */
timevalsub(&wtime, &ifinit_timer, &now);
if (wtime.tv_sec <= 0) {
wtime.tv_sec = 0;
ifinit();
rip_query();
continue;
}
/* If it is time, then broadcast our routes.
*/
if (supplier || advertise_mhome) {
timevalsub(&t2, &next_bcast,
&now);
if (t2.tv_sec <= 0) {
/* Synchronize the aging
and broadcast
* timers to minimize
awakenings
*/
age(0);
rip_bcast(0);
/* It is desirable to send
routing updates
* regularly. So schedule
the next update
* 30 seconds after the
previous one was
* secheduled, instead of
30 seconds after
* the previous update was
finished.
* Even if we just started
after discovering
* a 2nd interface or were
otherwise delayed,
* pick a 30-second
aniversary of the
* original broadcast time.
*/
n = 1 +
(0-t2.tv_sec)/SUPPLY_INTERVAL;
next_bcast.tv_sec +=
n*SUPPLY_INTERVAL;
continue;
}
if (timercmp(&t2, &wtime,
<))
wtime = t2;
}
/* If we need a flash update, either do it now or
* set the delay to end when it is time.
*
* If we are within MIN_WAITTIME seconds of a full
update,
* do not bother.
*/
if (need_flash
&& supplier
&& no_flash.tv_sec+MIN_WAITTIME <
next_bcast.tv_sec) {
/* accurate to the millisecond */
if (!timercmp(&no_flash, &now,
>))
rip_bcast(1);
timevalsub(&t2, &no_flash,
&now);
if (timercmp(&t2, &wtime,
<))
wtime = t2;
}
/* trigger the main aging timer.
*/
timevalsub(&t2, &age_timer, &now);
if (t2.tv_sec <= 0) {
age(0);
continue;
}
if (timercmp(&t2, &wtime, <))
wtime = t2;
/* update the kernel routing table
*/
timevalsub(&t2, &need_kern, &now);
if (t2.tv_sec <= 0) {
age(0);
continue;
}
if (timercmp(&t2, &wtime, <))
wtime = t2;
/* take care of router discovery,
* but do it to the millisecond
*/
if (!timercmp(&rdisc_timer, &now, >)) {
rdisc_age(0);
continue;
}
timevalsub(&t2, &rdisc_timer, &now);
if (timercmp(&t2, &wtime, <))
wtime = t2;
/* wait for input or a timer to expire.
*/
trace_flush();
ibits = fdbits;
n = select(sock_max, &ibits, 0, 0, &wtime);
if (n <= 0) {
if (n < 0 && errno != EINTR
&& errno != EAGAIN)
BADERR(1,"select");
continue;
}
if (FD_ISSET(rt_sock, &ibits)) {
read_rt();
n--;
}
if (rdisc_sock >= 0 &&
FD_ISSET(rdisc_sock, &ibits)) {
read_d();
n--;
}
if (rip_sock >= 0 && FD_ISSET(rip_sock,
&ibits)) {
read_rip(rip_sock, 0);
n--;
}
for (ifp = ifnet; n > 0 && 0 != ifp; ifp
= ifp->int_next) {
if (ifp->int_rip_sock >= 0
&&
FD_ISSET(ifp->int_rip_sock, &ibits)) {
read_rip(ifp->int_rip_sock,
ifp);
n--;
}
}
}
}
/* ARGSUSED */
void
sigalrm(int s)
{
/* Historically, SIGALRM would cause the daemon to check for
* new and broken interfaces.
*/
ifinit_timer.tv_sec = now.tv_sec;
trace_act("SIGALRM");
}
/* watch for fatal signals */
void
sigterm(int sig)
{
stopint = sig;
(void)signal(sig, SIG_DFL); /* catch it only once */
}
void
fix_select(void)
{
struct interface *ifp;
FD_ZERO(&fdbits);
sock_max = 0;
FD_SET(rt_sock, &fdbits);
if (sock_max <= rt_sock)
sock_max = rt_sock+1;
if (rip_sock >= 0) {
Ñòðàíèöû: 1, 2, 3, 4, 5, 6 |