int slk_init(int fmt) { int i; PDC_LOG(("slk_init() - called\n")); // if (SP) // return ERR; switch (fmt) { case 0: /* 3 - 2 - 3 */ label_fmt = 0x323; break; case 1: /* 4 - 4 */ label_fmt = 0x44; break; case 2: /* 4 4 4 */ label_fmt = 0x444; break; case 3: /* 4 4 4 with index */ label_fmt = -0x444; break; case 55: /* 5 - 5 */ label_fmt = 0x55; break; default: label_fmt = fmt; break; } traceon( ); n_labels = 0; for( i = abs( label_fmt); i; i /= 16) n_labels += i % 16; PDC_LOG(("slk_init: fmt %d, %d labels, %p\n", fmt, n_labels, slk)); if( slk) free( slk); slk = calloc(n_labels, sizeof(struct SLK)); PDC_LOG(( "New slk: %p; SP = %p\n", slk, SP)); traceoff( ); if (!slk) n_labels = 0; if( SP) { if( SP->slk_winptr) wclear( SP->slk_winptr); PDC_slk_initialize( ); } return slk ? OK : ERR; }
void sigtrace(int s) { if (s == SIGUSR2) traceoff(); else if (ftrace == NULL && savetracename) traceon(savetracename); else bumploglevel(); }
static void pdc_ncurses_init (void) { #if defined(HAVE_NCURSES) && !defined(BUILDING_UTILS) const char *env = getenv ("CURSES_TRACE"); if (env && atoi(env) > 0) { traceon(); putenv ("NCURSES_TRACE=1"); } putenv ("PDC_RESTORE_SCREEN=1"); putenv ("PDC_PRESERVE_SCREEN=1"); #if 0 /* if stdout is redirected, initscr() fails with * "LINES value must be >= 2 and <= x: got y" */ if (isatty(fileno(stdout)) <= 0) { putenv ("COLS=2"); putenv ("LINES=2"); } #endif #endif }
int main(int argc, char *argv[]) { int i, n; struct interface *ifp; int c; struct timeval waittime; int timeout; boolean_t daemon = _B_TRUE; /* Fork off a detached daemon */ FILE *pidfp; mode_t pidmode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* 0644 */ rip6_port = htons(IPPORT_ROUTESERVER6); allrouters.sin6_family = AF_INET6; allrouters.sin6_port = rip6_port; allrouters.sin6_addr = allrouters_in6; while ((c = getopt(argc, argv, "nsqvTtdgPp:")) != EOF) { switch (c) { case 'n': install = _B_FALSE; break; case 's': supplier = _B_TRUE; break; case 'q': supplier = _B_FALSE; break; case 'v': tracing |= ACTION_BIT; break; case 'T': daemon = _B_FALSE; break; case 't': tracepackets = _B_TRUE; daemon = _B_FALSE; tracing |= (INPUT_BIT | OUTPUT_BIT); break; case 'd': break; case 'P': dopoison = _B_FALSE; break; case 'p': rip6_port = htons(atoi(optarg)); allrouters.sin6_port = rip6_port; break; default: usage(argv[0]); /* NOTREACHED */ } } /* * Any extra argument is considered * a tracing log file. */ if (optind < argc) { traceon(argv[optind]); } else if (tracing && !daemon) { traceonfp(stdout); } else if (tracing) { (void) fprintf(stderr, "Need logfile with -v\n"); usage(argv[0]); /* NOTREACHED */ } if (daemon) { int t; if (fork()) exit(EXIT_SUCCESS); for (t = 0; t < 20; t++) { if (!tracing || (t != fileno(ftrace))) (void) close(t); } (void) open("/", 0); (void) dup2(0, 1); (void) dup2(0, 2); (void) setsid(); } /* Store our process id, blow away any existing file if it exists. */ if ((pidfp = fopen(PATH_PID, "w")) == NULL) { (void) fprintf(stderr, "%s: unable to open " PATH_PID ": %s\n", argv[0], strerror(errno)); } else { (void) fprintf(pidfp, "%ld\n", getpid()); (void) fclose(pidfp); (void) chmod(PATH_PID, pidmode); } iocsoc = socket(AF_INET6, SOCK_DGRAM, 0); if (iocsoc < 0) { syslog(LOG_ERR, "main: socket: %m"); exit(EXIT_FAILURE); } setup_rtsock(); /* * Allocate the buffer to hold the RIPng packet. In reality, it will be * smaller than IPV6_MAX_PACKET octets due to (at least) the IPv6 and * UDP headers but IPV6_MAX_PACKET is a convenient size. */ packet = (char *)malloc(IPV6_MAX_PACKET); if (packet == NULL) { syslog(LOG_ERR, "main: malloc: %m"); exit(EXIT_FAILURE); } msg = (struct rip6 *)packet; /* * Allocate the buffer to hold the ancillary data. This data is used to * insure that the incoming hop count of a RIPCMD6_RESPONSE message is * IPV6_MAX_HOPS which indicates that it came from a direct neighbor * (namely, no intervening router decremented it). */ control = (char *)malloc(IPV6_MAX_PACKET); if (control == NULL) { syslog(LOG_ERR, "main: malloc: %m"); exit(EXIT_FAILURE); } openlog("in.ripngd", LOG_PID | LOG_CONS, LOG_DAEMON); (void) gettimeofday(&now, (struct timezone *)NULL); initifs(); solicitall(&allrouters); if (supplier) supplyall(&allrouters, 0, (struct interface *)NULL, _B_TRUE); (void) sigset(SIGALRM, (void (*)(int))timer); (void) sigset(SIGHUP, (void (*)(int))initifs); (void) sigset(SIGTERM, (void (*)(int))term); (void) sigset(SIGUSR1, (void (*)(int))if_dump); (void) sigset(SIGUSR2, (void (*)(int))rtdump); /* * Seed the pseudo-random number generator for GET_RANDOM(). */ srandom((uint_t)gethostid()); timer(); for (;;) { if (needupdate) { waittime = nextmcast; timevalsub(&waittime, &now); if (waittime.tv_sec < 0) { timeout = 0; } else { timeout = TIME_TO_MSECS(waittime); } if (tracing & ACTION_BIT) { (void) fprintf(ftrace, "poll until dynamic update in %d msec\n", timeout); (void) fflush(ftrace); } } else { timeout = INFTIM; } if ((n = poll(poll_ifs, poll_ifs_num, timeout)) < 0) { if (errno == EINTR) continue; syslog(LOG_ERR, "main: poll: %m"); exit(EXIT_FAILURE); } (void) sighold(SIGALRM); (void) sighold(SIGHUP); /* * Poll timed out. */ if (n == 0) { if (needupdate) { TRACE_ACTION("send delayed dynamic update", (struct rt_entry *)NULL); (void) gettimeofday(&now, (struct timezone *)NULL); supplyall(&allrouters, RTS_CHANGED, (struct interface *)NULL, _B_TRUE); lastmcast = now; needupdate = _B_FALSE; nextmcast.tv_sec = 0; } (void) sigrelse(SIGHUP); (void) sigrelse(SIGALRM); continue; } (void) gettimeofday(&now, (struct timezone *)NULL); for (i = 0; i < poll_ifs_num; i++) { /* * This case should never happen. */ if (poll_ifs[i].revents & POLLERR) { syslog(LOG_ERR, "main: poll returned a POLLERR event"); continue; } if (poll_ifs[i].revents & POLLIN) { for (ifp = ifnet; ifp != NULL; ifp = ifp->int_next) { if (poll_ifs[i].fd == ifp->int_sock) in_data(ifp); } } } (void) sigrelse(SIGHUP); (void) sigrelse(SIGALRM); } return (0); }
int ripd(int argc, char *argv[]) { int n, nfd, tflags = 0, ch; struct timeval *tvp, waittime; struct itimerval itval; struct rip *query = msg; fd_set ibits; sigset_t sigset, osigset; while ((ch = getopt(argc, argv, "sqtdg")) != EOF) { switch (ch) { case 's': supplier = 1; break; case 'q': supplier = 0; break; case 't': tflags++; break; case 'd': debug++; setlogmask(LOG_UPTO(LOG_DEBUG)); break; case 'g': gateway = 1; break; default: fprintf(stderr, "%% Incomplete command\r\n"); return(1); } } getkversion(); sock = getsocket(); assert(sock>=0); openlog("ripd", LOG_PID | LOG_ODELAY, LOG_DAEMON); if (debug == 0 && tflags == 0) { switch (fork()) { case -1: perror("fork"); exit(1); case 0: break; /* child */ default: exit(0); /* parent */ } close(0); close(1); close(2); setsid(); setlogmask(LOG_UPTO(LOG_WARNING)); } else { setlogmask(LOG_UPTO(LOG_DEBUG)); } /* pid */ pidfile = fopen( "/var/run/ripd.pid", "w" ) ; if (pidfile==NULL) { fprintf(stderr,"%% Error write pid\n"); return (-1); } else fprintf(pidfile,"%d", (int) getpid()); fclose(pidfile); /* * Any extra argument is considered * a tracing log file. * * Note: because traceon() redirects stderr, anything planning to * crash on startup should do so before this point. */ if (argc > optind) { traceon(argv[optind]); } while (tflags-- > 0) { bumploglevel(); } gettimeofday(&now, 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 * everyone else thinks. */ rtinit(); ifinit(); gwkludge(); if (gateway > 0) { rtdefault(); } if (supplier < 0) { supplier = 0; } 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); } else { /* unreachable code (at least on most platforms) */ query->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; } query->rip_nets[0].rip_metric = htonl((u_long)HOPCNT_INFINITY); toall(sndmsg, 0, NULL); signal(SIGALRM, timer); signal(SIGHUP, hup); signal(SIGTERM, hup); 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; srandom(time(NULL) ^ getpid()); if (setitimer(ITIMER_REAL, &itval, (struct itimerval *)NULL) < 0) { syslog(LOG_ERR, "setitimer: %m\n"); } FD_ZERO(&ibits); nfd = sock + 1; /* 1 + max(fd's) */ for (;;) { FD_SET(sock, &ibits); /* * 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, * just poll. */ if (needupdate) { waittime = nextbcast; timevalsub(&waittime, &now); if (waittime.tv_sec < 0) { waittime.tv_sec = 0; waittime.tv_usec = 0; } if (traceactions) fprintf(ftrace, "select until dynamic update %ld/%ld sec/usec\n", (long)waittime.tv_sec, (long)waittime.tv_usec); tvp = &waittime; } else { tvp = (struct timeval *)NULL; } n = select(nfd, &ibits, 0, 0, tvp); if (n <= 0) { /* * Need delayed dynamic update if select returned * nothing and we timed out. Otherwise, ignore * errors (e.g. EINTR). */ if (n < 0) { if (errno == EINTR) continue; syslog(LOG_ERR, "select: %m"); } sigemptyset(&sigset); sigaddset(&sigset, SIGALRM); sigprocmask(SIG_BLOCK, &sigset, &osigset); if (n == 0 && needupdate) { if (traceactions) fprintf(ftrace, "send delayed dynamic update\n"); (void) gettimeofday(&now, (struct timezone *)NULL); toall(supply, RTS_CHANGED, (struct interface *)NULL); lastbcast = now; needupdate = 0; nextbcast.tv_sec = 0; } sigprocmask(SIG_SETMASK, &osigset, NULL); continue; } gettimeofday(&now, (struct timezone *)NULL); sigemptyset(&sigset); sigaddset(&sigset, SIGALRM); sigprocmask(SIG_BLOCK, &sigset, &osigset); if (FD_ISSET(sock, &ibits)) { process(sock); } /* handle ICMP redirects */ sigprocmask(SIG_SETMASK, &osigset, NULL); } }
int slave() { int tries; long electiontime, refusetime, looktime, looptime, adjtime; u_short seq; long fastelection; #define FASTTOUT 3 struct in_addr cadr; struct timeval otime; struct sockaddr_in taddr; char tname[MAXHOSTNAMELEN]; struct tsp *msg, to; struct timeval ntime, wait, tmptv; time_t tsp_time_sec; struct tsp *answer; int timeout(); char olddate[32]; char newdate[32]; struct netinfo *ntp; struct hosttbl *htp; struct utmpx utx; old_slavenet = 0; seq = 0; refusetime = 0; adjtime = 0; (void)gettimeofday(&ntime, NULL); electiontime = ntime.tv_sec + delay2; fastelection = ntime.tv_sec + FASTTOUT; if (justquit) looktime = electiontime; else looktime = fastelection; looptime = fastelection; if (slavenet) xmit(TSP_SLAVEUP, 0, &slavenet->dest_addr); if (status & MASTER) { for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if (ntp->status == MASTER) masterup(ntp); } } loop: get_goodgroup(0); (void)gettimeofday(&ntime, NULL); if (ntime.tv_sec > electiontime) { if (trace) fprintf(fd, "election timer expired\n"); longjmp(jmpenv, 1); } if (ntime.tv_sec >= looktime) { if (trace) fprintf(fd, "Looking for nets to master\n"); if (Mflag && nignorednets > 0) { for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if (ntp->status == IGNORE || ntp->status == NOMASTER) { lookformaster(ntp); if (ntp->status == MASTER) { masterup(ntp); } else if (ntp->status == MASTER) { ntp->status = NOMASTER; } } if (ntp->status == MASTER && --ntp->quit_count < 0) ntp->quit_count = 0; } makeslave(slavenet); /* prune extras */ setstatus(); } (void)gettimeofday(&ntime, NULL); looktime = ntime.tv_sec + delay2; } if (ntime.tv_sec >= looptime) { if (trace) fprintf(fd, "Looking for loops\n"); for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if (ntp->status == MASTER) { to.tsp_type = TSP_LOOP; to.tsp_vers = TSPVERSION; to.tsp_seq = sequence++; to.tsp_hopcnt = MAX_HOPCNT; (void)strcpy(to.tsp_name, hostname); bytenetorder(&to); if (sendto(sock, (char *)&to, sizeof(struct tsp), 0, (struct sockaddr*)&ntp->dest_addr, sizeof(ntp->dest_addr)) < 0) { trace_sendto_err(ntp->dest_addr.sin_addr); } } } (void)gettimeofday(&ntime, NULL); looptime = ntime.tv_sec + delay2; } wait.tv_sec = min(electiontime,min(looktime,looptime)) - ntime.tv_sec; if (wait.tv_sec < 0) wait.tv_sec = 0; wait.tv_sec += FASTTOUT; wait.tv_usec = 0; msg = readmsg(TSP_ANY, ANYADDR, &wait, 0); if (msg != NULL) { /* * filter stuff not for us */ switch (msg->tsp_type) { case TSP_SETDATE: case TSP_TRACEOFF: case TSP_TRACEON: /* * XXX check to see they are from ourself */ break; case TSP_TEST: case TSP_MSITE: break; case TSP_MASTERUP: if (!fromnet) { if (trace) { fprintf(fd, "slave ignored: "); print(msg, &from); } goto loop; } break; default: if (!fromnet || fromnet->status == IGNORE || fromnet->status == NOMASTER) { if (trace) { fprintf(fd, "slave ignored: "); print(msg, &from); } goto loop; } break; } /* * now process the message */ switch (msg->tsp_type) { case TSP_ADJTIME: if (fromnet != slavenet) break; if (!good_host_name(msg->tsp_name)) { syslog(LOG_NOTICE, "attempted time adjustment by %s", msg->tsp_name); suppress(&from, msg->tsp_name, fromnet); break; } /* * Speed up loop detection in case we have a loop. * Otherwise the clocks can race until the loop * is found. */ (void)gettimeofday(&otime, NULL); if (adjtime < otime.tv_sec) looptime -= (looptime-otime.tv_sec)/2 + 1; setmaster(msg); if (seq != msg->tsp_seq) { seq = msg->tsp_seq; synch(tvtomsround(msg->tsp_time)); } (void)gettimeofday(&ntime, NULL); electiontime = ntime.tv_sec + delay2; fastelection = ntime.tv_sec + FASTTOUT; adjtime = ntime.tv_sec + SAMPLEINTVL*2; break; case TSP_SETTIME: if (fromnet != slavenet) break; if (seq == msg->tsp_seq) break; seq = msg->tsp_seq; /* adjust time for residence on the queue */ (void)gettimeofday(&otime, NULL); adj_msg_time(msg,&otime); /* * the following line is necessary due to syslog * calling ctime() which clobbers the static buffer */ (void)strcpy(olddate, date()); tsp_time_sec = msg->tsp_time.tv_sec; (void)strcpy(newdate, ctime(&tsp_time_sec)); if (!good_host_name(msg->tsp_name)) { syslog(LOG_NOTICE, "attempted time setting by untrusted %s to %s", msg->tsp_name, newdate); suppress(&from, msg->tsp_name, fromnet); break; } setmaster(msg); tmptv.tv_sec = msg->tsp_time.tv_sec; tmptv.tv_usec = msg->tsp_time.tv_usec; timevalsub(&ntime, &tmptv, &otime); if (ntime.tv_sec < MAXADJ && ntime.tv_sec > -MAXADJ) { /* * do not change the clock if we can adjust it */ synch(tvtomsround(ntime)); } else { utx.ut_type = OLD_TIME; gettimeofday(&utx.ut_tv, NULL); pututxline(&utx); (void)settimeofday(&tmptv, 0); utx.ut_type = NEW_TIME; gettimeofday(&utx.ut_tv, NULL); pututxline(&utx); syslog(LOG_NOTICE, "date changed by %s from %s", msg->tsp_name, olddate); if (status & MASTER) spreadtime(); } (void)gettimeofday(&ntime, NULL); electiontime = ntime.tv_sec + delay2; fastelection = ntime.tv_sec + FASTTOUT; /* This patches a bad protocol bug. Imagine a system with several networks, * where there are a pair of redundant gateways between a pair of networks, * each running timed. Assume that we start with a third machine mastering * one of the networks, and one of the gateways mastering the other. * Imagine that the third machine goes away and the non-master gateway * decides to replace it. If things are timed just 'right,' we will have * each gateway mastering one network for a little while. If a SETTIME * message gets into the network at that time, perhaps from the newly * masterful gateway as it was taking control, the SETTIME will loop * forever. Each time a gateway receives it on its slave side, it will * call spreadtime to forward it on its mastered network. We are now in * a permanent loop, since the SETTIME msgs will keep any clock * in the network from advancing. Normally, the 'LOOP' stuff will detect * and correct the situation. However, with the clocks stopped, the * 'looptime' timer cannot expire. While they are in this state, the * masters will try to saturate the network with SETTIME packets. */ looptime = ntime.tv_sec + (looptime-otime.tv_sec)/2-1; break; case TSP_MASTERUP: if (slavenet && fromnet != slavenet) break; if (!good_host_name(msg->tsp_name)) { suppress(&from, msg->tsp_name, fromnet); if (electiontime > fastelection) electiontime = fastelection; break; } makeslave(fromnet); setmaster(msg); setstatus(); answerdelay(); xmit(TSP_SLAVEUP, 0, &from); (void)gettimeofday(&ntime, NULL); electiontime = ntime.tv_sec + delay2; fastelection = ntime.tv_sec + FASTTOUT; refusetime = 0; break; case TSP_MASTERREQ: if (fromnet->status != SLAVE) break; (void)gettimeofday(&ntime, NULL); electiontime = ntime.tv_sec + delay2; break; case TSP_SETDATE: tsp_time_sec = msg->tsp_time.tv_sec; (void)strcpy(newdate, ctime(&tsp_time_sec)); schgdate(msg, newdate); break; case TSP_SETDATEREQ: if (fromnet->status != MASTER) break; tsp_time_sec = msg->tsp_time.tv_sec; (void)strcpy(newdate, ctime(&tsp_time_sec)); htp = findhost(msg->tsp_name); if (0 == htp) { syslog(LOG_WARNING, "DATEREQ from uncontrolled machine"); break; } if (!htp->good) { syslog(LOG_WARNING, "attempted date change by untrusted %s to %s", htp->name, newdate); spreadtime(); break; } schgdate(msg, newdate); break; case TSP_TRACEON: traceon(); break; case TSP_TRACEOFF: traceoff("Tracing ended at %s\n"); break; case TSP_SLAVEUP: newslave(msg); break; case TSP_ELECTION: if (fromnet->status == SLAVE) { (void)gettimeofday(&ntime, NULL); electiontime = ntime.tv_sec + delay2; fastelection = ntime.tv_sec + FASTTOUT; seq = 0; if (!good_host_name(msg->tsp_name)) { syslog(LOG_NOTICE, "suppress election of %s", msg->tsp_name); to.tsp_type = TSP_QUIT; electiontime = fastelection; } else if (cadr.s_addr != from.sin_addr.s_addr && ntime.tv_sec < refusetime) { /* if the candidate has to repeat itself, the old code would refuse it * the second time. That would prevent elections. */ to.tsp_type = TSP_REFUSE; } else { cadr.s_addr = from.sin_addr.s_addr; to.tsp_type = TSP_ACCEPT; refusetime = ntime.tv_sec + 30; } taddr = from; (void)strcpy(tname, msg->tsp_name); (void)strcpy(to.tsp_name, hostname); answerdelay(); if (!acksend(&to, &taddr, tname, TSP_ACK, 0, 0)) syslog(LOG_WARNING, "no answer from candidate %s\n", tname); } else { /* fromnet->status == MASTER */ htp = addmach(msg->tsp_name, &from,fromnet); to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); if (!acksend(&to, &htp->addr, htp->name, TSP_ACK, 0, htp->noanswer)) { syslog(LOG_ERR, "no reply from %s to ELECTION-QUIT", htp->name); (void)remmach(htp); } } break; case TSP_CONFLICT: if (fromnet->status != MASTER) break; /* * After a network partition, there can be * more than one master: the first slave to * come up will notify here the situation. */ (void)strcpy(to.tsp_name, hostname); /* The other master often gets into the same state, * with boring results. */ ntp = fromnet; /* (acksend() can leave fromnet=0 */ for (tries = 0; tries < 3; tries++) { to.tsp_type = TSP_RESOLVE; answer = acksend(&to, &ntp->dest_addr, ANYADDR, TSP_MASTERACK, ntp, 0); if (answer == NULL) break; htp = addmach(answer->tsp_name,&from,ntp); to.tsp_type = TSP_QUIT; answer = acksend(&to, &htp->addr, htp->name, TSP_ACK, 0, htp->noanswer); if (!answer) { syslog(LOG_WARNING, "conflict error: no reply from %s to QUIT", htp->name); (void)remmach(htp); } } masterup(ntp); break; case TSP_MSITE: if (!slavenet) break; taddr = from; to.tsp_type = TSP_MSITEREQ; to.tsp_vers = TSPVERSION; to.tsp_seq = 0; (void)strcpy(to.tsp_name, hostname); answer = acksend(&to, &slavenet->dest_addr, ANYADDR, TSP_ACK, slavenet, 0); if (answer != NULL && good_host_name(answer->tsp_name)) { setmaster(answer); to.tsp_type = TSP_ACK; (void)strcpy(to.tsp_name, answer->tsp_name); bytenetorder(&to); if (sendto(sock, (char *)&to, sizeof(struct tsp), 0, (struct sockaddr*)&taddr, sizeof(taddr)) < 0) { trace_sendto_err(taddr.sin_addr); } } break; case TSP_MSITEREQ: break; case TSP_ACCEPT: case TSP_REFUSE: case TSP_RESOLVE: break; case TSP_QUIT: doquit(msg); /* become a slave */ break; case TSP_TEST: electiontime = 0; break; case TSP_LOOP: /* looking for loops of masters */ if (!(status & MASTER)) break; if (fromnet->status == SLAVE) { if (!strcmp(msg->tsp_name, hostname)) { /* * Someone forwarded our message back to * us. There must be a loop. Tell the * master of this network to quit. * * The other master often gets into * the same state, with boring results. */ ntp = fromnet; for (tries = 0; tries < 3; tries++) { to.tsp_type = TSP_RESOLVE; answer = acksend(&to, &ntp->dest_addr, ANYADDR, TSP_MASTERACK, ntp,0); if (answer == NULL) break; taddr = from; (void)strcpy(tname, answer->tsp_name); to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); if (!acksend(&to, &taddr, tname, TSP_ACK, 0, 1)) { syslog(LOG_ERR, "no reply from %s to slave LOOP-QUIT", tname); } else { electiontime = 0; } } (void)gettimeofday(&ntime, NULL); looptime = ntime.tv_sec + FASTTOUT; } else { if (msg->tsp_hopcnt-- < 1) break; bytenetorder(msg); for (ntp = nettab; ntp != 0; ntp = ntp->next) { if (ntp->status == MASTER && 0 > sendto(sock, (char *)msg, sizeof(struct tsp), 0, (struct sockaddr*)&ntp->dest_addr, sizeof(ntp->dest_addr))) trace_sendto_err(ntp->dest_addr.sin_addr); } } } else { /* fromnet->status == MASTER */ /* * We should not have received this from a net * we are master on. There must be two masters, * unless the packet was really from us. */ if (from.sin_addr.s_addr == fromnet->my_addr.s_addr) { if (trace) fprintf(fd,"discarding forwarded LOOP\n"); break; } /* * The other master often gets into the same * state, with boring results. */ ntp = fromnet; for (tries = 0; tries < 3; tries++) { to.tsp_type = TSP_RESOLVE; answer = acksend(&to, &ntp->dest_addr, ANYADDR, TSP_MASTERACK, ntp,0); if (!answer) break; htp = addmach(answer->tsp_name, &from,ntp); to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); if (!acksend(&to,&htp->addr,htp->name, TSP_ACK, 0, htp->noanswer)) { syslog(LOG_ERR, "no reply from %s to master LOOP-QUIT", htp->name); (void)remmach(htp); } } (void)gettimeofday(&ntime, NULL); looptime = ntime.tv_sec + FASTTOUT; } break; default: if (trace) { fprintf(fd, "garbage message: "); print(msg, &from); } break; } } goto loop; }
/* * The main function of `master' is to periodically compute the differences * (deltas) between its clock and the clocks of the slaves, to compute the * network average delta, and to send to the slaves the differences between * their individual deltas and the network delta. * While waiting, it receives messages from the slaves (i.e. requests for * master's name, remote requests to set the network time, ...), and * takes the appropriate action. */ int master() { struct hosttbl *htp; long pollingtime; #define POLLRATE 4 int polls; struct timeval wait, ntime; time_t tsp_time_sec; struct tsp *msg, *answer, to; char newdate[32]; struct sockaddr_in taddr; char tname[MAXHOSTNAMELEN]; struct netinfo *ntp; int i; syslog(LOG_NOTICE, "This machine is master"); if (trace) fprintf(fd, "This machine is master\n"); for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if (ntp->status == MASTER) masterup(ntp); } (void)gettimeofday(&ntime, 0); pollingtime = ntime.tv_sec+3; if (justquit) polls = 0; else polls = POLLRATE-1; /* Process all outstanding messages before spending the long time necessary * to update all timers. */ loop: (void)gettimeofday(&ntime, 0); wait.tv_sec = pollingtime - ntime.tv_sec; if (wait.tv_sec < 0) wait.tv_sec = 0; wait.tv_usec = 0; msg = readmsg(TSP_ANY, ANYADDR, &wait, 0); if (!msg) { (void)gettimeofday(&ntime, 0); if (ntime.tv_sec >= pollingtime) { pollingtime = ntime.tv_sec + SAMPLEINTVL; get_goodgroup(0); /* If a bogus master told us to quit, we can have decided to ignore a * network. Therefore, periodically try to take over everything. */ polls = (polls + 1) % POLLRATE; if (0 == polls && nignorednets > 0) { trace_msg("Looking for nets to re-master\n"); for (ntp = nettab; ntp; ntp = ntp->next) { if (ntp->status == IGNORE || ntp->status == NOMASTER) { lookformaster(ntp); if (ntp->status == MASTER) { masterup(ntp); polls = POLLRATE-1; } } if (ntp->status == MASTER && --ntp->quit_count < 0) ntp->quit_count = 0; } if (polls != 0) setstatus(); } synch(0L); for (ntp = nettab; ntp != NULL; ntp = ntp->next) { to.tsp_type = TSP_LOOP; to.tsp_vers = TSPVERSION; to.tsp_seq = sequence++; to.tsp_hopcnt = MAX_HOPCNT; (void)strcpy(to.tsp_name, hostname); bytenetorder(&to); if (sendto(sock, (char *)&to, sizeof(struct tsp), 0, (struct sockaddr*)&ntp->dest_addr, sizeof(ntp->dest_addr)) < 0) { trace_sendto_err(ntp->dest_addr.sin_addr); } } } } else { switch (msg->tsp_type) { case TSP_MASTERREQ: break; case TSP_SLAVEUP: newslave(msg); break; case TSP_SETDATE: /* * XXX check to see it is from ourself */ tsp_time_sec = msg->tsp_time.tv_sec; (void)strcpy(newdate, ctime(&tsp_time_sec)); if (!good_host_name(msg->tsp_name)) { syslog(LOG_NOTICE, "attempted date change by %s to %s", msg->tsp_name, newdate); spreadtime(); break; } mchgdate(msg); (void)gettimeofday(&ntime, 0); pollingtime = ntime.tv_sec + SAMPLEINTVL; break; case TSP_SETDATEREQ: if (!fromnet || fromnet->status != MASTER) break; tsp_time_sec = msg->tsp_time.tv_sec; (void)strcpy(newdate, ctime(&tsp_time_sec)); htp = findhost(msg->tsp_name); if (htp == 0) { syslog(LOG_ERR, "attempted SET DATEREQ by uncontrolled %s to %s", msg->tsp_name, newdate); break; } if (htp->seq == msg->tsp_seq) break; htp->seq = msg->tsp_seq; if (!htp->good) { syslog(LOG_NOTICE, "attempted SET DATEREQ by untrusted %s to %s", msg->tsp_name, newdate); spreadtime(); break; } mchgdate(msg); (void)gettimeofday(&ntime, 0); pollingtime = ntime.tv_sec + SAMPLEINTVL; break; case TSP_MSITE: xmit(TSP_ACK, msg->tsp_seq, &from); break; case TSP_MSITEREQ: break; case TSP_TRACEON: traceon(); break; case TSP_TRACEOFF: traceoff("Tracing ended at %s\n"); break; case TSP_ELECTION: if (!fromnet) break; if (fromnet->status == MASTER) { pollingtime = 0; (void)addmach(msg->tsp_name, &from,fromnet); } taddr = from; (void)strcpy(tname, msg->tsp_name); to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); answer = acksend(&to, &taddr, tname, TSP_ACK, 0, 1); if (answer == NULL) { syslog(LOG_ERR, "election error by %s", tname); } break; case TSP_CONFLICT: /* * After a network partition, there can be * more than one master: the first slave to * come up will notify here the situation. */ if (!fromnet || fromnet->status != MASTER) break; (void)strcpy(to.tsp_name, hostname); /* The other master often gets into the same state, * with boring results if we stay at it forever. */ ntp = fromnet; /* (acksend() can leave fromnet=0 */ for (i = 0; i < 3; i++) { to.tsp_type = TSP_RESOLVE; (void)strcpy(to.tsp_name, hostname); answer = acksend(&to, &ntp->dest_addr, ANYADDR, TSP_MASTERACK, ntp, 0); if (!answer) break; htp = addmach(answer->tsp_name,&from,ntp); to.tsp_type = TSP_QUIT; msg = acksend(&to, &htp->addr, htp->name, TSP_ACK, 0, htp->noanswer); if (msg == NULL) { syslog(LOG_ERR, "no response from %s to CONFLICT-QUIT", htp->name); } } masterup(ntp); pollingtime = 0; break; case TSP_RESOLVE: if (!fromnet || fromnet->status != MASTER) break; /* * do not want to call synch() while waiting * to be killed! */ (void)gettimeofday(&ntime, (struct timezone *)0); pollingtime = ntime.tv_sec + SAMPLEINTVL; break; case TSP_QUIT: doquit(msg); /* become a slave */ break; case TSP_LOOP: if (!fromnet || fromnet->status != MASTER || !strcmp(msg->tsp_name, hostname)) break; /* * We should not have received this from a net * we are master on. There must be two masters. */ htp = addmach(msg->tsp_name, &from,fromnet); to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); answer = acksend(&to, &htp->addr, htp->name, TSP_ACK, 0, 1); if (!answer) { syslog(LOG_WARNING, "loop breakage: no reply from %s=%s to QUIT", htp->name, inet_ntoa(htp->addr.sin_addr)); (void)remmach(htp); } case TSP_TEST: if (trace) { fprintf(fd, "\tnets = %d, masters = %d, slaves = %d, ignored = %d\n", nnets, nmasternets, nslavenets, nignorednets); setstatus(); } pollingtime = 0; polls = POLLRATE-1; break; default: if (trace) { fprintf(fd, "garbage message: "); print(msg, &from); } break; } } goto loop; }
/* * The timedaemons synchronize the clocks of hosts in a local area network. * One daemon runs as master, all the others as slaves. The master * performs the task of computing clock differences and sends correction * values to the slaves. * Slaves start an election to choose a new master when the latter disappears * because of a machine crash, network partition, or when killed. * A resolution protocol is used to kill all but one of the masters * that happen to exist in segments of a partitioned network when the * network partition is fixed. * * Authors: Riccardo Gusella & Stefano Zatti * * overhauled at Silicon Graphics */ int main(int argc, char *argv[]) { int on; int ret; int nflag, iflag; struct timeval ntime; struct servent *srvp; char buf[BUFSIZ], *cp, *cplim; struct ifconf ifc; struct ifreq ifreq, ifreqf, *ifr; register struct netinfo *ntp; struct netinfo *ntip; struct netinfo *savefromnet; struct netent *nentp; struct nets *nt; struct sockaddr_in server; u_short port; int c; #ifdef lint ntip = NULL; #endif on = 1; nflag = OFF; iflag = OFF; opterr = 0; while ((c = getopt(argc, argv, "Mtdn:i:F:G:P:")) != -1) { switch (c) { case 'M': Mflag = 1; break; case 't': trace = 1; break; case 'n': if (iflag) { errx(1, "-i and -n make no sense together"); } else { nflag = ON; addnetname(optarg); } break; case 'i': if (nflag) { errx(1, "-i and -n make no sense together"); } else { iflag = ON; addnetname(optarg); } break; case 'F': add_good_host(optarg,1); while (optind < argc && argv[optind][0] != '-') add_good_host(argv[optind++], 1); break; case 'd': debug = 1; break; case 'G': if (goodgroup != NULL) errx(1, "only one net group"); goodgroup = optarg; break; default: usage(); break; } } if (optind < argc) usage(); /* If we care about which machine is the master, then we must * be willing to be a master */ if (goodgroup != NULL || goodhosts != NULL) Mflag = 1; if (gethostname(hostname, sizeof(hostname) - 1) < 0) err(1, "gethostname"); self.l_bak = &self; self.l_fwd = &self; self.h_bak = &self; self.h_fwd = &self; self.head = 1; self.good = 1; if (goodhosts != NULL) /* trust ourself */ add_good_host(hostname,1); srvp = getservbyname("timed", "udp"); if (srvp == NULL) errx(1, "timed/udp: unknown service"); port = srvp->s_port; bzero(&server, sizeof(struct sockaddr_in)); server.sin_port = srvp->s_port; server.sin_family = AF_INET; sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) err(1, "socket"); if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof(on)) < 0) err(1, "setsockopt"); if (bind(sock, (struct sockaddr*)&server, sizeof(server))) { if (errno == EADDRINUSE) warnx("time daemon already running"); else warn("bind"); exit(1); } sequence = arc4random(); /* initial seq number */ (void)gettimeofday(&ntime, NULL); /* rounds kernel variable time to multiple of 5 ms. */ ntime.tv_sec = 0; ntime.tv_usec = -((ntime.tv_usec/1000) % 5) * 1000; (void)adjtime(&ntime, (struct timeval *)0); for (nt = nets; nt; nt = nt->next) { nentp = getnetbyname(nt->name); if (nentp == NULL) { nt->net = inet_network(nt->name); if (nt->net != INADDR_NONE) nentp = getnetbyaddr(nt->net, AF_INET); } if (nentp != NULL) { nt->net = nentp->n_net; } else if (nt->net == INADDR_NONE) { errx(1, "unknown net %s", nt->name); } else if (nt->net == INADDR_ANY) { errx(1, "bad net %s", nt->name); } else { warnx("warning: %s unknown in /etc/networks", nt->name); } if (0 == (nt->net & 0xff000000)) nt->net <<= 8; if (0 == (nt->net & 0xff000000)) nt->net <<= 8; if (0 == (nt->net & 0xff000000)) nt->net <<= 8; } ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) err(1, "get interface configuration"); ntp = NULL; #define size(p) max((p).sa_len, sizeof(p)) cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */ for (cp = buf; cp < cplim; cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) { ifr = (struct ifreq *)cp; if (ifr->ifr_addr.sa_family != AF_INET) continue; if (!ntp) ntp = (struct netinfo*)malloc(sizeof(struct netinfo)); bzero(ntp,sizeof(*ntp)); ntp->my_addr=((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr; ntp->status = NOMASTER; ifreq = *ifr; ifreqf = *ifr; if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreqf) < 0) { warn("get interface flags"); continue; } if ((ifreqf.ifr_flags & IFF_UP) == 0) continue; if ((ifreqf.ifr_flags & IFF_BROADCAST) == 0 && (ifreqf.ifr_flags & IFF_POINTOPOINT) == 0) { continue; } if (ioctl(sock, SIOCGIFNETMASK, (char *)&ifreq) < 0) { warn("get netmask"); continue; } ntp->mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr; if (ifreqf.ifr_flags & IFF_BROADCAST) { if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { warn("get broadaddr"); continue; } ntp->dest_addr = *(struct sockaddr_in *)&ifreq.ifr_broadaddr; /* What if the broadcast address is all ones? * So we cannot just mask ntp->dest_addr. */ ntp->net = ntp->my_addr; ntp->net.s_addr &= ntp->mask; } else { if (ioctl(sock, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { warn("get destaddr"); continue; } ntp->dest_addr = *(struct sockaddr_in *)&ifreq.ifr_dstaddr; ntp->net = ntp->dest_addr.sin_addr; } ntp->dest_addr.sin_port = port; for (nt = nets; nt; nt = nt->next) { if (ntp->net.s_addr == htonl(nt->net)) break; } if ((nflag && !nt) || (iflag && nt)) continue; ntp->next = NULL; if (nettab == NULL) { nettab = ntp; } else { ntip->next = ntp; } ntip = ntp; ntp = NULL; } if (ntp) (void) free((char *)ntp); if (nettab == NULL) errx(1, "no network usable"); /* microseconds to delay before responding to a broadcast */ delay1 = casual(1, 100*1000); /* election timer delay in secs. */ delay2 = casual(MINTOUT, MAXTOUT); if (!debug) daemon(debug, 0); if (trace) traceon(); openlog("timed", LOG_CONS|LOG_PID, LOG_DAEMON); /* * keep returning here */ ret = setjmp(jmpenv); savefromnet = fromnet; setstatus(); if (Mflag) { switch (ret) { case 0: checkignorednets(); pickslavenet(0); break; case 1: /* Just lost our master */ if (slavenet != NULL) slavenet->status = election(slavenet); if (!slavenet || slavenet->status == MASTER) { checkignorednets(); pickslavenet(0); } else { makeslave(slavenet); /* prune extras */ } break; case 2: /* Just been told to quit */ justquit = 1; pickslavenet(savefromnet); break; } setstatus(); if (!(status & MASTER) && sock_raw != -1) { /* sock_raw is not being used now */ (void)close(sock_raw); sock_raw = -1; } if (status == MASTER) master(); else slave(); } else { if (sock_raw != -1) { (void)close(sock_raw); sock_raw = -1; } if (ret) { /* we just lost our master or were told to quit */ justquit = 1; } for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if (ntp->status == MASTER) { rmnetmachs(ntp); ntp->status = NOMASTER; } } checkignorednets(); pickslavenet(0); setstatus(); slave(); } /* NOTREACHED */ return(0); }
/* * synchronize all of the slaves */ void synch(long mydelta) { struct hosttbl *htp; int measure_status; struct timeval check, stop, wait; if (slvcount > 0) { if (trace) fprintf(fd, "measurements starting at %s\n", date()); (void)gettimeofday(&check, NULL); for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) { if (htp->noanswer != 0) { measure_status = measure(500, 100, htp->name, &htp->addr,0); } else { measure_status = measure(3000, 100, htp->name, &htp->addr,0); } if (measure_status != GOOD) { /* The slave did not respond. We have * just wasted lots of time on it. */ htp->delta = HOSTDOWN; if (++htp->noanswer >= LOSTHOST) { if (trace) { fprintf(fd, "purging %s for not answering ICMP\n", htp->name); (void)fflush(fd); } htp = remmach(htp); } } else { htp->delta = measure_delta; } (void)gettimeofday(&stop, NULL); timevalsub(&stop, &stop, &check); if (stop.tv_sec >= 1) { if (trace) (void)fflush(fd); /* * ack messages periodically */ wait.tv_sec = 0; wait.tv_usec = 0; if (0 != readmsg(TSP_TRACEON,ANYADDR, &wait,0)) traceon(); (void)gettimeofday(&check, NULL); } } if (trace) fprintf(fd, "measurements finished at %s\n", date()); } if (!(status & SLAVE)) { if (!dictate) { mydelta = networkdelta(); } else { dictate--; } } if (trace && (mydelta != 0 || (status & SLAVE))) fprintf(fd,"local correction of %ld ms.\n", mydelta); correct(mydelta); }
int main(int argc, char *argv[]) { int _argc = 0; char *_argv[5]; pid_t pid; int execed = 0; int n, nfd, tflags = 0, ch; struct timeval *tvp, waittime; struct itimerval itval; fd_set ibits; sigset_t sigset, osigset; while ((ch = getopt(argc, argv, "D012bsqtdg")) != EOF) { switch (ch) { case 'D': execed = 1; break; case '0': ripversion = 0; break; case '1': ripversion = 1; break; case '2': ripversion = 2; break; case 'b': multicast = 0; break; case 's': supplier = 1; break; case 'q': supplier = 0; break; case 't': tflags++; break; case 'd': debug++; setlogmask(LOG_UPTO(LOG_DEBUG)); break; case 'g': gateway = 1; break; default: fprintf(stderr, "usage: routed [ -1bsqtdg ]\n"); exit(1); } } // Modified by Mason Yu sleep(2); /* if(!check_pid()) { // Commented by Mason Yu //write_cfg(); exit(1); } */ if (!execed) { if ((pid = vfork()) < 0) { fprintf(stderr, "vfork failed\n"); exit(1); } else if (pid != 0) { exit(0); } for (_argc=0; _argc < argc; _argc++ ) _argv[_argc] = argv[_argc]; _argv[0] = runPath; _argv[argc++] = "-D"; _argv[argc++] = NULL; execv(_argv[0], _argv); /* Not reached */ fprintf(stderr, "Couldn't exec\n"); _exit(1); } else { setsid(); } getkversion(); sock = getsocket(); assert(sock>=0); openlog("routed", LOG_PID | LOG_ODELAY, LOG_DAEMON); #if 0 if (debug == 0 && tflags == 0) { #ifndef EMBED switch (fork()) { case -1: perror("fork"); exit(1); case 0: break; /* child */ default: exit(0); /* parent */ } #endif close(0); close(1); close(2); setsid(); setlogmask(LOG_UPTO(LOG_WARNING)); } else #endif { setlogmask(LOG_UPTO(LOG_DEBUG)); } /* * Any extra argument is considered * a tracing log file. * * Note: because traceon() redirects stderr, anything planning to * crash on startup should do so before this point. */ if (argc > 1) { traceon(argv[argc - 1]); } while (tflags-- > 0) { bumploglevel(); } gettimeofday(&now, 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 * everyone else thinks. */ read_cfg(); rtinit(); ifinit(); gwkludge(); if (gateway > 0) { rtdefault(); } if (supplier < 0) { supplier = 0; } signal(SIGALRM, timer); signal(SIGHUP, hup); signal(SIGTERM, hup); signal(SIGTERM, terminate_routed); //RTK WiSOC modify for deleting all route entry 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; srandom(time(NULL) ^ getpid()); if (setitimer(ITIMER_REAL, &itval, (struct itimerval *)NULL) < 0) { syslog(LOG_ERR, "setitimer: %m\n"); } // Kaohj //#ifdef EMBED //WiSOC we use pid file for system init write_pid(); //#endif rip_request_send(); rip_input_init(); DISPLAY_BANNER; FD_ZERO(&ibits); nfd = sock + 1; /* 1 + max(fd's) */ for (;;) { FD_SET(sock, &ibits); /* * 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, * just poll. */ if (needupdate) { waittime = nextbcast; timevalsub(&waittime, &now); if (waittime.tv_sec < 0) { waittime.tv_sec = 0; waittime.tv_usec = 0; } if (traceactions) fprintf(ftrace, "select until dynamic update %ld/%ld sec/usec\n", (long)waittime.tv_sec, (long)waittime.tv_usec); tvp = &waittime; } else { tvp = (struct timeval *)NULL; } n = select(nfd, &ibits, 0, 0, tvp); if (n <= 0) { /* * Need delayed dynamic update if select returned * nothing and we timed out. Otherwise, ignore * errors (e.g. EINTR). */ if (n < 0) { if (errno == EINTR) continue; syslog(LOG_ERR, "select: %m"); } sigemptyset(&sigset); sigaddset(&sigset, SIGALRM); sigprocmask(SIG_BLOCK, &sigset, &osigset); if (n == 0 && needupdate) { if (traceactions) fprintf(ftrace, "send delayed dynamic update\n"); (void) gettimeofday(&now, (struct timezone *)NULL); toall(supply, RTS_CHANGED, (struct interface *)NULL); lastbcast = now; needupdate = 0; nextbcast.tv_sec = 0; } sigprocmask(SIG_SETMASK, &osigset, NULL); continue; } gettimeofday(&now, (struct timezone *)NULL); sigemptyset(&sigset); sigaddset(&sigset, SIGALRM); sigprocmask(SIG_BLOCK, &sigset, &osigset); if (FD_ISSET(sock, &ibits)) { process(sock); } /* handle ICMP redirects */ sigprocmask(SIG_SETMASK, &osigset, NULL); } }
int main(int argc, char *argv[]) { int nfds; fd_set fdvar; time_t ttime; struct itimerval tval; argv0 = argv; argv++, argc--; while (argc > 0 && **argv == '-') { if (strcmp(*argv, "-s") == 0) { supplier = 1; argv++, argc--; continue; } if (strcmp(*argv, "-q") == 0) { supplier = 0; argv++, argc--; continue; } if (strcmp(*argv, "-R") == 0) { noteremoterequests++; argv++, argc--; continue; } if (strcmp(*argv, "-S") == 0) { dosap = 0; argv++, argc--; continue; } if (strcmp(*argv, "-t") == 0) { tracepackets++; argv++, argc--; ftrace = stderr; tracing = 1; continue; } if (strcmp(*argv, "-g") == 0) { gateway = 1; argv++, argc--; continue; } if (strcmp(*argv, "-l") == 0) { gateway = -1; argv++, argc--; continue; } if (strcmp(*argv, "-N") == 0) { dognreply = 0; argv++, argc--; continue; } fprintf(stderr, "usage: ipxrouted [ -s ] [ -q ] [ -t ] [ -g ] [ -l ] [ -N ]\n"); exit(1); } #ifndef DEBUG if (!tracepackets) daemon(0, 0); #endif openlog("IPXrouted", LOG_PID, LOG_DAEMON); addr.sipx_family = AF_IPX; addr.sipx_len = sizeof(addr); addr.sipx_port = htons(IPXPORT_RIP); ipx_anynet.s_net[0] = ipx_anynet.s_net[1] = -1; ipx_netmask.sipx_addr.x_net = ipx_anynet; ipx_netmask.sipx_len = 6; ipx_netmask.sipx_family = AF_IPX; r = socket(AF_ROUTE, SOCK_RAW, 0); /* later, get smart about lookingforinterfaces */ if (r) shutdown(r, SHUT_RD); /* for now, don't want reponses */ else { fprintf(stderr, "IPXrouted: no routing socket\n"); exit(1); } ripsock = getsocket(SOCK_DGRAM, 0, &addr); if (ripsock < 0) exit(1); if (dosap) { addr.sipx_port = htons(IPXPORT_SAP); sapsock = getsocket(SOCK_DGRAM, 0, &addr); if (sapsock < 0) exit(1); } else sapsock = -1; /* * Any extra argument is considered * a tracing log file. */ if (argc > 0) traceon(*argv); /* * Collect an initial view of the world by * snooping in the kernel. Then, send a request packet on all * directly connected networks to find out what * everyone else thinks. */ rtinit(); sapinit(); ifinit(); if (supplier < 0) supplier = 0; /* request the state of the world */ msg->rip_cmd = htons(RIPCMD_REQUEST); msg->rip_nets[0].rip_dst = ipx_anynet; msg->rip_nets[0].rip_metric = htons(HOPCNT_INFINITY); msg->rip_nets[0].rip_ticks = htons(-1); toall(sndmsg, NULL, 0); if (dosap) { sap_msg->sap_cmd = htons(SAP_REQ); sap_msg->sap[0].ServType = htons(SAP_WILDCARD); toall(sapsndmsg, NULL, 0); } signal(SIGALRM, catchtimer); signal(SIGHUP, hup); signal(SIGINT, hup); signal(SIGEMT, fkexit); signal(SIGINFO, getinfo); tval.it_interval.tv_sec = TIMER_RATE; tval.it_interval.tv_usec = 0; tval.it_value.tv_sec = TIMER_RATE; tval.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &tval, NULL); nfds = 1 + max(sapsock, ripsock); for (;;) { if (dobcast) { dobcast = 0; lastbcast = time(NULL); timer(); } FD_ZERO(&fdvar); if (dosap) { FD_SET(sapsock, &fdvar); } FD_SET(ripsock, &fdvar); if(select(nfds, &fdvar, NULL, NULL, NULL) < 0) { if(errno == EINTR) continue; perror("during select"); exit(1); } if(FD_ISSET(ripsock, &fdvar)) process(ripsock, RIP_PKT); if(dosap && FD_ISSET(sapsock, &fdvar)) process(sapsock, SAP_PKT); ttime = time(NULL); if (ttime > (lastbcast + TIMER_RATE + (TIMER_RATE * 2 / 3))) { dobcast = 1; syslog(LOG_ERR, "Missed alarm"); } } }