Beispiel #1
0
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;
}
Beispiel #2
0
void sigtrace(int s)
{

	if (s == SIGUSR2)
		traceoff();
	else if (ftrace == NULL && savetracename)
		traceon(savetracename);
	else
		bumploglevel();
}
Beispiel #3
0
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
}
Beispiel #4
0
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);
}
Beispiel #5
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);
	}
}
Beispiel #6
0
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;
}
Beispiel #7
0
/*
 * 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;
}
Beispiel #8
0
/*
 * 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);
}
Beispiel #9
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);
}
Beispiel #10
0
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);
	}
}
Beispiel #11
0
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");
		}
	}
}