xref: /csrg-svn/usr.sbin/timed/timedc/cmds.c (revision 25578)
123785Sgusella /*
223785Sgusella  * Copyright (c) 1983 Regents of the University of California.
323785Sgusella  * All rights reserved.  The Berkeley software License Agreement
423785Sgusella  * specifies the terms and conditions for redistribution.
523785Sgusella  */
623785Sgusella 
723785Sgusella #ifndef lint
8*25578Sbloom static char sccsid[] = "@(#)cmds.c	2.1 (Berkeley) 12/10/85";
923785Sgusella #endif not lint
1023785Sgusella 
1123785Sgusella #include "timedc.h"
1223785Sgusella #include <netinet/in_systm.h>
1323785Sgusella #include <netinet/ip.h>
1423785Sgusella #include <netinet/ip_icmp.h>
1523785Sgusella #define TSPTYPES
1623785Sgusella #include <protocols/timed.h>
1723785Sgusella #include <sys/file.h>
1823785Sgusella 
1923785Sgusella int id;
2023785Sgusella int sock;
2123785Sgusella int sock_raw;
2224904Sbloom char hostname[MAXHOSTNAMELEN];
2323785Sgusella struct hostent *hp, *gethostbyname();
2423785Sgusella struct sockaddr_in server;
2523785Sgusella extern int measure_delta;
2623785Sgusella int bytenetorder(), bytehostorder();
2723785Sgusella char *strcpy();
2823785Sgusella 
2923785Sgusella /*
3023785Sgusella  * Clockdiff computes the difference between the time of the machine on
3123785Sgusella  * which it is called and the time of the machines given as argument.
3223785Sgusella  * The time differences measured by clockdiff are obtained using a sequence
3323785Sgusella  * of ICMP TSTAMP messages which are returned to the sender by the IP module
3423785Sgusella  * in the remote machine.
3523785Sgusella  * In order to compare clocks of machines in different time zones, the time
3623785Sgusella  * is transmitted (as a 32-bit value) in milliseconds since midnight UT.
3723785Sgusella  * If a hosts uses a different time format, it should set the high order
3823785Sgusella  * bit of the 32-bit quantity it transmits.
3923785Sgusella  * However, VMS apparently transmits the time in milliseconds since midnight
4023785Sgusella  * local time (rather than GMT) without setting the high order bit.
4123785Sgusella  * Furthermore, it does not understand daylight-saving time.  This makes
4223785Sgusella  * clockdiff behaving inconsistently with hosts running VMS.
4323785Sgusella  *
4423785Sgusella  * In order to reduce the sensitivity to the variance of message transmission
4523785Sgusella  * time, clockdiff sends a sequence of messages.  Yet, measures between
4623785Sgusella  * two `distant' hosts can be affected by a small error. The error can, however,
4723785Sgusella  * be reduced by increasing the number of messages sent in each measurement.
4823785Sgusella  */
4923785Sgusella 
5023785Sgusella clockdiff(argc, argv)
5123785Sgusella int argc;
5223785Sgusella char *argv[];
5323785Sgusella {
5423785Sgusella 	int measure_status;
5523785Sgusella 	struct timeval ack;
5623785Sgusella 	int measure();
5723785Sgusella 
5823785Sgusella 	if(argc < 2)  {
5923785Sgusella 		printf("Usage: clockdiff host ... \n");
6023785Sgusella 		return;
6123785Sgusella 	}
6223785Sgusella 
6323785Sgusella 	id = getpid();
6423785Sgusella 	(void)gethostname(hostname,sizeof(hostname));
6523785Sgusella 
6623785Sgusella 	while (argc > 1) {
6723785Sgusella 		argc--; argv++;
6823785Sgusella 		hp = gethostbyname(*argv);
6923785Sgusella 		if (hp == NULL) {
7023785Sgusella 			printf("%s: unknown host\n", *argv);
7123785Sgusella 			continue;
7223785Sgusella 		}
7323785Sgusella 		server.sin_family = hp->h_addrtype;
7423785Sgusella 		bcopy(hp->h_addr, &(server.sin_addr.s_addr), hp->h_length);
7523785Sgusella 		ack.tv_sec = 1;
7623785Sgusella 		ack.tv_usec = 500000;
77*25578Sbloom 		if ((measure_status = measure(&ack, &server, OFF)) < 0) {
7823785Sgusella 			perror("measure");
7923785Sgusella 			return;
8023785Sgusella 		}
8123785Sgusella 		switch (measure_status) {
8223785Sgusella 
8323785Sgusella 		case HOSTDOWN:
8423785Sgusella 			printf("%s is down\n", hp->h_name);
8523785Sgusella 			continue;
8623785Sgusella 			break;
8723785Sgusella 		case NONSTDTIME:
8823785Sgusella 			printf("%s time transmitted in a non-standard format\n",						 hp->h_name);
8923785Sgusella 			continue;
9023785Sgusella 			break;
9123785Sgusella 		case UNREACHABLE:
9223785Sgusella 			printf("%s is unreachable\n", hp->h_name);
9323785Sgusella 			continue;
9423785Sgusella 			break;
9523785Sgusella 		default:
9623785Sgusella 			break;
9723785Sgusella 		}
9823785Sgusella 
9923785Sgusella 		if (measure_delta > 0)
10023785Sgusella 			printf("time on %s is %d ms. ahead of time on %s\n",
10123785Sgusella 						hp->h_name, measure_delta,
10223785Sgusella 						hostname);
10323785Sgusella 		else
10423785Sgusella 			if (measure_delta == 0)
10523785Sgusella 		      		printf("%s and %s have the same time\n",
10623785Sgusella 						hp->h_name, hostname);
10723785Sgusella 			else
10823785Sgusella 		      	     printf("time on %s is %d ms. behind time on %s\n",
10923785Sgusella 					hp->h_name, -measure_delta, hostname);
11023785Sgusella 	}
11123785Sgusella 	return;
11223785Sgusella }
11323785Sgusella /*
11423785Sgusella  * finds location of master timedaemon
11523785Sgusella  */
11623785Sgusella 
11723785Sgusella msite(argc)
11823785Sgusella int argc;
11923785Sgusella {
12023785Sgusella 	int length;
121*25578Sbloom 	int cc;
122*25578Sbloom 	fd_set ready;
12323785Sgusella 	struct sockaddr_in dest;
12423785Sgusella 	struct timeval tout;
12523785Sgusella 	struct sockaddr_in from;
12623785Sgusella 	struct tsp msg;
12723785Sgusella 	struct servent *srvp;
12823785Sgusella 
12923785Sgusella 	if (argc != 1) {
13023785Sgusella 		printf("Usage: msite\n");
13123785Sgusella 		return;
13223785Sgusella 	}
13323785Sgusella 
13423785Sgusella 	srvp = getservbyname("timed", "udp");
13523785Sgusella 	if (srvp == 0) {
13623785Sgusella 		fprintf(stderr, "udp/timed: unknown service\n");
13723785Sgusella 		return;
13823785Sgusella 	}
13923785Sgusella 	dest.sin_port = srvp->s_port;
14023785Sgusella 	dest.sin_family = AF_INET;
14123785Sgusella 
14223785Sgusella 	(void)gethostname(hostname,sizeof(hostname));
14323785Sgusella 	hp = gethostbyname(hostname);
14423785Sgusella 	if (hp == NULL) {
14523785Sgusella 		perror("gethostbyname");
14623785Sgusella 		return;
14723785Sgusella 	}
14823785Sgusella 	bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length);
14923785Sgusella 
15023785Sgusella 	(void)strcpy(msg.tsp_name, hostname);
15123785Sgusella 	msg.tsp_type = TSP_MSITE;
15223785Sgusella 	msg.tsp_vers = TSPVERSION;
15323785Sgusella 	bytenetorder(&msg);
15423785Sgusella 	length = sizeof(struct sockaddr_in);
15523785Sgusella 	if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0,
15623785Sgusella 						&dest, length) < 0) {
15723785Sgusella 		perror("sendto");
15823785Sgusella 		return;
15923785Sgusella 	}
16023785Sgusella 
16123785Sgusella 	tout.tv_sec = 15;
16223785Sgusella 	tout.tv_usec = 0;
163*25578Sbloom 	FD_ZERO(&ready);
164*25578Sbloom 	FD_SET(sock, &ready);
165*25578Sbloom 	if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) {
16623785Sgusella 		length = sizeof(struct sockaddr_in);
16723785Sgusella 		cc = recvfrom(sock, (char *)&msg, sizeof(struct tsp), 0,
16823785Sgusella 							&from, &length);
16923785Sgusella 		if (cc < 0) {
17023785Sgusella 			perror("recvfrom");
17123785Sgusella 			return;
17223785Sgusella 		}
17323785Sgusella 		bytehostorder(&msg);
17423785Sgusella 		if (msg.tsp_type == TSP_ACK)
17523785Sgusella 			printf("master timedaemon runs on %s\n", msg.tsp_name);
17623785Sgusella 		else
17723785Sgusella 			printf("received wrong ack: %s\n",
17823785Sgusella 						tsptype[msg.tsp_type]);
17923785Sgusella 	} else
18023785Sgusella 		printf("communication error\n");
18123785Sgusella }
18223785Sgusella 
18323785Sgusella /*
18423785Sgusella  * quits timedc
18523785Sgusella  */
18623785Sgusella 
18723785Sgusella quit()
18823785Sgusella {
18923785Sgusella 	exit(0);
19023785Sgusella }
19123785Sgusella 
19223785Sgusella #define MAXH	4	/* max no. of hosts where election can occur */
19323785Sgusella 
19423785Sgusella /*
19523785Sgusella  * Causes the election timer to expire on the selected hosts
19623785Sgusella  * It sends just one udp message per machine, relying on
19723785Sgusella  * reliability of communication channel.
19823785Sgusella  */
19923785Sgusella 
20023785Sgusella testing(argc, argv)
20123785Sgusella int argc;
20223785Sgusella char *argv[];
20323785Sgusella {
20423785Sgusella 	int length;
20523785Sgusella 	int nhosts;
20623785Sgusella 	struct servent *srvp;
20723785Sgusella 	struct sockaddr_in sin[MAXH];
20823785Sgusella 	struct tsp msg;
20923785Sgusella 
21023785Sgusella 	if(argc < 2)  {
21123785Sgusella 		printf("Usage: testing host ...\n");
21223785Sgusella 		return;
21323785Sgusella 	}
21423785Sgusella 
21523785Sgusella 	srvp = getservbyname("timed", "udp");
21623785Sgusella 	if (srvp == 0) {
21723785Sgusella 		fprintf(stderr, "udp/timed: unknown service\n");
21823785Sgusella 		return;
21923785Sgusella 	}
22023785Sgusella 
22123785Sgusella 	nhosts = 0;
22223785Sgusella 	while (argc > 1) {
22323785Sgusella 		argc--; argv++;
22423785Sgusella 		hp = gethostbyname(*argv);
22523785Sgusella 		if (hp == NULL) {
22623785Sgusella 			printf("%s: unknown host %s\n", *argv);
22723785Sgusella 			argc--; argv++;
22823785Sgusella 			continue;
22923785Sgusella 		}
23023785Sgusella 		sin[nhosts].sin_port = srvp->s_port;
23123785Sgusella 		sin[nhosts].sin_family = hp->h_addrtype;
23223785Sgusella 		bcopy(hp->h_addr, &(sin[nhosts].sin_addr.s_addr), hp->h_length);
23323785Sgusella 		if (++nhosts == MAXH)
23423785Sgusella 			break;
23523785Sgusella 	}
23623785Sgusella 
23723785Sgusella 	msg.tsp_type = TSP_TEST;
23823785Sgusella 	msg.tsp_vers = TSPVERSION;
23923785Sgusella 	(void)gethostname(hostname, sizeof(hostname));
24023785Sgusella 	(void)strcpy(msg.tsp_name, hostname);
24123785Sgusella 	bytenetorder(&msg);	/* it is not really necessary here */
24223785Sgusella 	while (nhosts-- > 0) {
24323785Sgusella 		length = sizeof(struct sockaddr_in);
24423785Sgusella 		if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0,
24523785Sgusella 						&sin[nhosts], length) < 0) {
24623785Sgusella 			perror("sendto");
24723785Sgusella 			return;
24823785Sgusella 		}
24923785Sgusella 	}
25023785Sgusella }
25123785Sgusella 
25223785Sgusella /*
25323785Sgusella  * Enables or disables tracing on local timedaemon
25423785Sgusella  */
25523785Sgusella 
25623785Sgusella tracing(argc, argv)
25723785Sgusella int argc;
25823785Sgusella char *argv[];
25923785Sgusella {
26023785Sgusella 	int onflag;
26123785Sgusella 	int length;
262*25578Sbloom 	int cc;
263*25578Sbloom 	fd_set ready;
26423785Sgusella 	struct sockaddr_in dest;
26523785Sgusella 	struct timeval tout;
26623785Sgusella 	struct sockaddr_in from;
26723785Sgusella 	struct tsp msg;
26823785Sgusella 	struct servent *srvp;
26923785Sgusella 
27023785Sgusella 	if (argc != 2) {
27123785Sgusella 		printf("Usage: tracing { on | off }\n");
27223785Sgusella 		return;
27323785Sgusella 	}
27423785Sgusella 
27523785Sgusella 	srvp = getservbyname("timed", "udp");
27623785Sgusella 	if (srvp == 0) {
27723785Sgusella 		fprintf(stderr, "udp/timed: unknown service\n");
27823785Sgusella 		return;
27923785Sgusella 	}
28023785Sgusella 	dest.sin_port = srvp->s_port;
28123785Sgusella 	dest.sin_family = AF_INET;
28223785Sgusella 
28323785Sgusella 	(void)gethostname(hostname,sizeof(hostname));
28423785Sgusella 	hp = gethostbyname(hostname);
28523785Sgusella 	bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length);
28623785Sgusella 
28723785Sgusella 	if (strcmp(argv[1], "on") == 0) {
28823785Sgusella 		msg.tsp_type = TSP_TRACEON;
28923785Sgusella 		onflag = ON;
29023785Sgusella 	} else {
29123785Sgusella 		msg.tsp_type = TSP_TRACEOFF;
29223785Sgusella 		onflag = OFF;
29323785Sgusella 	}
29423785Sgusella 
29523785Sgusella 	(void)strcpy(msg.tsp_name, hostname);
29623785Sgusella 	msg.tsp_vers = TSPVERSION;
29723785Sgusella 	bytenetorder(&msg);
29823785Sgusella 	length = sizeof(struct sockaddr_in);
29923785Sgusella 	if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0,
30023785Sgusella 						&dest, length) < 0) {
30123785Sgusella 		perror("sendto");
30223785Sgusella 		return;
30323785Sgusella 	}
30423785Sgusella 
30523785Sgusella 	tout.tv_sec = 5;
30623785Sgusella 	tout.tv_usec = 0;
307*25578Sbloom 	FD_ZERO(&ready);
308*25578Sbloom 	FD_SET(sock, &ready);
309*25578Sbloom 	if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) {
31023785Sgusella 		length = sizeof(struct sockaddr_in);
31123785Sgusella 		cc = recvfrom(sock, (char *)&msg, sizeof(struct tsp), 0,
31223785Sgusella 							&from, &length);
31323785Sgusella 		if (cc < 0) {
31423785Sgusella 			perror("recvfrom");
31523785Sgusella 			return;
31623785Sgusella 		}
31723785Sgusella 		bytehostorder(&msg);
31823785Sgusella 		if (msg.tsp_type == TSP_ACK)
31923785Sgusella 			if (onflag)
32023785Sgusella 				printf("timed tracing enabled\n");
32123785Sgusella 			else
32223785Sgusella 				printf("timed tracing disabled\n");
32323785Sgusella 		else
32423785Sgusella 			printf("wrong ack received: %s\n",
32523785Sgusella 						tsptype[msg.tsp_type]);
32623785Sgusella 	} else
32723785Sgusella 		printf("communication error\n");
32823785Sgusella }
32923785Sgusella 
33023785Sgusella priv_resources()
33123785Sgusella {
33223785Sgusella 	int port;
33323785Sgusella 	struct sockaddr_in sin;
33423785Sgusella 
33523785Sgusella 	sock = socket(AF_INET, SOCK_DGRAM, 0);
33623785Sgusella 	if (sock < 0) {
33723785Sgusella 		perror("opening socket");
33823785Sgusella 		return(-1);
33923785Sgusella 	}
34023785Sgusella 
34123785Sgusella 	sin.sin_family = AF_INET;
34223785Sgusella 	sin.sin_addr.s_addr = 0;
34323785Sgusella 	for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) {
34423785Sgusella 		sin.sin_port = htons((u_short)port);
34523785Sgusella 		if (bind(sock, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
34623785Sgusella 			break;
34723785Sgusella 		if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) {
34823785Sgusella 			perror("bind");
34923785Sgusella 			(void) close(sock);
35023785Sgusella 			return(-1);
35123785Sgusella 		}
35223785Sgusella 	}
35323785Sgusella 	if (port == IPPORT_RESERVED / 2) {
35423785Sgusella 		fprintf(stderr, "all reserved ports in use\n");
35523785Sgusella 		(void) close(sock);
35623785Sgusella 		return(-1);
35723785Sgusella 	}
35823785Sgusella 
35923785Sgusella 	sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
36023785Sgusella 	if (sock_raw < 0)  {
36123785Sgusella 		perror("opening raw socket");
36223785Sgusella 		(void) close(sock_raw);
36323785Sgusella 		return(-1);
36423785Sgusella 	}
36523785Sgusella 	return(1);
36623785Sgusella }
367