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