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