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*24904Sbloom static char sccsid[] = "@(#)cmds.c 1.2 (Berkeley) 09/18/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; 22*24904Sbloom 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; 7723785Sgusella if ((measure_status = measure(&ack, 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; 12123785Sgusella int cc, ready, found; 12223785Sgusella struct sockaddr_in dest; 12323785Sgusella struct timeval tout; 12423785Sgusella struct sockaddr_in from; 12523785Sgusella struct tsp msg; 12623785Sgusella struct servent *srvp; 12723785Sgusella 12823785Sgusella if (argc != 1) { 12923785Sgusella printf("Usage: msite\n"); 13023785Sgusella return; 13123785Sgusella } 13223785Sgusella 13323785Sgusella srvp = getservbyname("timed", "udp"); 13423785Sgusella if (srvp == 0) { 13523785Sgusella fprintf(stderr, "udp/timed: unknown service\n"); 13623785Sgusella return; 13723785Sgusella } 13823785Sgusella dest.sin_port = srvp->s_port; 13923785Sgusella dest.sin_family = AF_INET; 14023785Sgusella 14123785Sgusella (void)gethostname(hostname,sizeof(hostname)); 14223785Sgusella hp = gethostbyname(hostname); 14323785Sgusella if (hp == NULL) { 14423785Sgusella perror("gethostbyname"); 14523785Sgusella return; 14623785Sgusella } 14723785Sgusella bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length); 14823785Sgusella 14923785Sgusella (void)strcpy(msg.tsp_name, hostname); 15023785Sgusella msg.tsp_type = TSP_MSITE; 15123785Sgusella msg.tsp_vers = TSPVERSION; 15223785Sgusella bytenetorder(&msg); 15323785Sgusella length = sizeof(struct sockaddr_in); 15423785Sgusella if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0, 15523785Sgusella &dest, length) < 0) { 15623785Sgusella perror("sendto"); 15723785Sgusella return; 15823785Sgusella } 15923785Sgusella 16023785Sgusella tout.tv_sec = 15; 16123785Sgusella tout.tv_usec = 0; 16223785Sgusella ready = 1<<sock; 16323785Sgusella found = select(20, &ready, (int *)0, (int *)0, &tout); 16423785Sgusella if (found) { 16523785Sgusella length = sizeof(struct sockaddr_in); 16623785Sgusella cc = recvfrom(sock, (char *)&msg, sizeof(struct tsp), 0, 16723785Sgusella &from, &length); 16823785Sgusella if (cc < 0) { 16923785Sgusella perror("recvfrom"); 17023785Sgusella return; 17123785Sgusella } 17223785Sgusella bytehostorder(&msg); 17323785Sgusella if (msg.tsp_type == TSP_ACK) 17423785Sgusella printf("master timedaemon runs on %s\n", msg.tsp_name); 17523785Sgusella else 17623785Sgusella printf("received wrong ack: %s\n", 17723785Sgusella tsptype[msg.tsp_type]); 17823785Sgusella } else 17923785Sgusella printf("communication error\n"); 18023785Sgusella } 18123785Sgusella 18223785Sgusella /* 18323785Sgusella * quits timedc 18423785Sgusella */ 18523785Sgusella 18623785Sgusella quit() 18723785Sgusella { 18823785Sgusella exit(0); 18923785Sgusella } 19023785Sgusella 19123785Sgusella #define MAXH 4 /* max no. of hosts where election can occur */ 19223785Sgusella 19323785Sgusella /* 19423785Sgusella * Causes the election timer to expire on the selected hosts 19523785Sgusella * It sends just one udp message per machine, relying on 19623785Sgusella * reliability of communication channel. 19723785Sgusella */ 19823785Sgusella 19923785Sgusella testing(argc, argv) 20023785Sgusella int argc; 20123785Sgusella char *argv[]; 20223785Sgusella { 20323785Sgusella int length; 20423785Sgusella int nhosts; 20523785Sgusella struct servent *srvp; 20623785Sgusella struct sockaddr_in sin[MAXH]; 20723785Sgusella struct tsp msg; 20823785Sgusella 20923785Sgusella if(argc < 2) { 21023785Sgusella printf("Usage: testing host ...\n"); 21123785Sgusella return; 21223785Sgusella } 21323785Sgusella 21423785Sgusella srvp = getservbyname("timed", "udp"); 21523785Sgusella if (srvp == 0) { 21623785Sgusella fprintf(stderr, "udp/timed: unknown service\n"); 21723785Sgusella return; 21823785Sgusella } 21923785Sgusella 22023785Sgusella nhosts = 0; 22123785Sgusella while (argc > 1) { 22223785Sgusella argc--; argv++; 22323785Sgusella hp = gethostbyname(*argv); 22423785Sgusella if (hp == NULL) { 22523785Sgusella printf("%s: unknown host %s\n", *argv); 22623785Sgusella argc--; argv++; 22723785Sgusella continue; 22823785Sgusella } 22923785Sgusella sin[nhosts].sin_port = srvp->s_port; 23023785Sgusella sin[nhosts].sin_family = hp->h_addrtype; 23123785Sgusella bcopy(hp->h_addr, &(sin[nhosts].sin_addr.s_addr), hp->h_length); 23223785Sgusella if (++nhosts == MAXH) 23323785Sgusella break; 23423785Sgusella } 23523785Sgusella 23623785Sgusella msg.tsp_type = TSP_TEST; 23723785Sgusella msg.tsp_vers = TSPVERSION; 23823785Sgusella (void)gethostname(hostname, sizeof(hostname)); 23923785Sgusella (void)strcpy(msg.tsp_name, hostname); 24023785Sgusella bytenetorder(&msg); /* it is not really necessary here */ 24123785Sgusella while (nhosts-- > 0) { 24223785Sgusella length = sizeof(struct sockaddr_in); 24323785Sgusella if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0, 24423785Sgusella &sin[nhosts], length) < 0) { 24523785Sgusella perror("sendto"); 24623785Sgusella return; 24723785Sgusella } 24823785Sgusella } 24923785Sgusella } 25023785Sgusella 25123785Sgusella /* 25223785Sgusella * Enables or disables tracing on local timedaemon 25323785Sgusella */ 25423785Sgusella 25523785Sgusella tracing(argc, argv) 25623785Sgusella int argc; 25723785Sgusella char *argv[]; 25823785Sgusella { 25923785Sgusella int onflag; 26023785Sgusella int length; 26123785Sgusella int cc, ready, found; 26223785Sgusella struct sockaddr_in dest; 26323785Sgusella struct timeval tout; 26423785Sgusella struct sockaddr_in from; 26523785Sgusella struct tsp msg; 26623785Sgusella struct servent *srvp; 26723785Sgusella 26823785Sgusella if (argc != 2) { 26923785Sgusella printf("Usage: tracing { on | off }\n"); 27023785Sgusella return; 27123785Sgusella } 27223785Sgusella 27323785Sgusella srvp = getservbyname("timed", "udp"); 27423785Sgusella if (srvp == 0) { 27523785Sgusella fprintf(stderr, "udp/timed: unknown service\n"); 27623785Sgusella return; 27723785Sgusella } 27823785Sgusella dest.sin_port = srvp->s_port; 27923785Sgusella dest.sin_family = AF_INET; 28023785Sgusella 28123785Sgusella (void)gethostname(hostname,sizeof(hostname)); 28223785Sgusella hp = gethostbyname(hostname); 28323785Sgusella bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length); 28423785Sgusella 28523785Sgusella if (strcmp(argv[1], "on") == 0) { 28623785Sgusella msg.tsp_type = TSP_TRACEON; 28723785Sgusella onflag = ON; 28823785Sgusella } else { 28923785Sgusella msg.tsp_type = TSP_TRACEOFF; 29023785Sgusella onflag = OFF; 29123785Sgusella } 29223785Sgusella 29323785Sgusella (void)strcpy(msg.tsp_name, hostname); 29423785Sgusella msg.tsp_vers = TSPVERSION; 29523785Sgusella bytenetorder(&msg); 29623785Sgusella length = sizeof(struct sockaddr_in); 29723785Sgusella if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0, 29823785Sgusella &dest, length) < 0) { 29923785Sgusella perror("sendto"); 30023785Sgusella return; 30123785Sgusella } 30223785Sgusella 30323785Sgusella tout.tv_sec = 5; 30423785Sgusella tout.tv_usec = 0; 30523785Sgusella ready = 1<<sock; 30623785Sgusella found = select(20, &ready, (int *)0, (int *)0, &tout); 30723785Sgusella if (found) { 30823785Sgusella length = sizeof(struct sockaddr_in); 30923785Sgusella cc = recvfrom(sock, (char *)&msg, sizeof(struct tsp), 0, 31023785Sgusella &from, &length); 31123785Sgusella if (cc < 0) { 31223785Sgusella perror("recvfrom"); 31323785Sgusella return; 31423785Sgusella } 31523785Sgusella bytehostorder(&msg); 31623785Sgusella if (msg.tsp_type == TSP_ACK) 31723785Sgusella if (onflag) 31823785Sgusella printf("timed tracing enabled\n"); 31923785Sgusella else 32023785Sgusella printf("timed tracing disabled\n"); 32123785Sgusella else 32223785Sgusella printf("wrong ack received: %s\n", 32323785Sgusella tsptype[msg.tsp_type]); 32423785Sgusella } else 32523785Sgusella printf("communication error\n"); 32623785Sgusella } 32723785Sgusella 32823785Sgusella priv_resources() 32923785Sgusella { 33023785Sgusella int port; 33123785Sgusella struct sockaddr_in sin; 33223785Sgusella 33323785Sgusella sock = socket(AF_INET, SOCK_DGRAM, 0); 33423785Sgusella if (sock < 0) { 33523785Sgusella perror("opening socket"); 33623785Sgusella return(-1); 33723785Sgusella } 33823785Sgusella 33923785Sgusella sin.sin_family = AF_INET; 34023785Sgusella sin.sin_addr.s_addr = 0; 34123785Sgusella for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) { 34223785Sgusella sin.sin_port = htons((u_short)port); 34323785Sgusella if (bind(sock, (struct sockaddr *)&sin, sizeof (sin)) >= 0) 34423785Sgusella break; 34523785Sgusella if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) { 34623785Sgusella perror("bind"); 34723785Sgusella (void) close(sock); 34823785Sgusella return(-1); 34923785Sgusella } 35023785Sgusella } 35123785Sgusella if (port == IPPORT_RESERVED / 2) { 35223785Sgusella fprintf(stderr, "all reserved ports in use\n"); 35323785Sgusella (void) close(sock); 35423785Sgusella return(-1); 35523785Sgusella } 35623785Sgusella 35723785Sgusella sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); 35823785Sgusella if (sock_raw < 0) { 35923785Sgusella perror("opening raw socket"); 36023785Sgusella (void) close(sock_raw); 36123785Sgusella return(-1); 36223785Sgusella } 36323785Sgusella return(1); 36423785Sgusella } 365