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