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 634775Sbostic * provided that the above copyright notice and this paragraph are 734775Sbostic * duplicated in all such forms and that any documentation, 834775Sbostic * advertising materials, and other materials related to such 934775Sbostic * distribution and use acknowledge that the software was developed 1034775Sbostic * by the University of California, Berkeley. The name of the 1134775Sbostic * University may not be used to endorse or promote products derived 1234775Sbostic * from this software without specific prior written permission. 1334775Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434775Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534775Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1623785Sgusella */ 1723785Sgusella 1823785Sgusella #ifndef lint 19*35784Sbostic static char sccsid[] = "@(#)cmds.c 2.6 (Berkeley) 10/11/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) { 81*35784Sbostic fprintf(stderr, "timed: %s: ", *argv); 82*35784Sbostic herror((char *)NULL); 8323785Sgusella continue; 8423785Sgusella } 8523785Sgusella server.sin_family = hp->h_addrtype; 8623785Sgusella bcopy(hp->h_addr, &(server.sin_addr.s_addr), hp->h_length); 8727239Sbloom ack.tv_sec = 10; 8827239Sbloom ack.tv_usec = 0; 8927239Sbloom if ((measure_status = measure(&ack, &server)) < 0) { 9023785Sgusella perror("measure"); 9123785Sgusella return; 9223785Sgusella } 9323785Sgusella switch (measure_status) { 9423785Sgusella 9523785Sgusella case HOSTDOWN: 9623785Sgusella printf("%s is down\n", hp->h_name); 9723785Sgusella continue; 9823785Sgusella break; 9923785Sgusella case NONSTDTIME: 10023785Sgusella printf("%s time transmitted in a non-standard format\n", hp->h_name); 10123785Sgusella continue; 10223785Sgusella break; 10323785Sgusella case UNREACHABLE: 10423785Sgusella printf("%s is unreachable\n", hp->h_name); 10523785Sgusella continue; 10623785Sgusella break; 10723785Sgusella default: 10823785Sgusella break; 10923785Sgusella } 11023785Sgusella 11123785Sgusella if (measure_delta > 0) 11223785Sgusella printf("time on %s is %d ms. ahead of time on %s\n", 11323785Sgusella hp->h_name, measure_delta, 11423785Sgusella hostname); 11523785Sgusella else 11623785Sgusella if (measure_delta == 0) 11723785Sgusella printf("%s and %s have the same time\n", 11823785Sgusella hp->h_name, hostname); 11923785Sgusella else 12023785Sgusella printf("time on %s is %d ms. behind time on %s\n", 12123785Sgusella hp->h_name, -measure_delta, hostname); 12223785Sgusella } 12323785Sgusella return; 12423785Sgusella } 12523785Sgusella /* 12623785Sgusella * finds location of master timedaemon 12723785Sgusella */ 12823785Sgusella 12923785Sgusella msite(argc) 13023785Sgusella int argc; 13123785Sgusella { 13223785Sgusella int length; 13325578Sbloom int cc; 13425578Sbloom fd_set ready; 13523785Sgusella struct sockaddr_in dest; 13623785Sgusella struct timeval tout; 13723785Sgusella struct sockaddr_in from; 13823785Sgusella struct tsp msg; 13923785Sgusella struct servent *srvp; 14023785Sgusella 14123785Sgusella if (argc != 1) { 14223785Sgusella printf("Usage: msite\n"); 14323785Sgusella return; 14423785Sgusella } 14523785Sgusella 14623785Sgusella srvp = getservbyname("timed", "udp"); 14723785Sgusella if (srvp == 0) { 14823785Sgusella fprintf(stderr, "udp/timed: unknown service\n"); 14923785Sgusella return; 150*35784Sbostic } 15123785Sgusella dest.sin_port = srvp->s_port; 15223785Sgusella dest.sin_family = AF_INET; 15323785Sgusella 154*35784Sbostic (void)gethostname(hostname, sizeof(hostname)); 15523785Sgusella hp = gethostbyname(hostname); 15623785Sgusella if (hp == NULL) { 157*35784Sbostic fprintf(stderr, "timed: %s: ", hostname); 158*35784Sbostic herror((char *)NULL); 15923785Sgusella return; 16023785Sgusella } 16123785Sgusella bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length); 16223785Sgusella 16323785Sgusella (void)strcpy(msg.tsp_name, hostname); 16423785Sgusella msg.tsp_type = TSP_MSITE; 16523785Sgusella msg.tsp_vers = TSPVERSION; 16623785Sgusella bytenetorder(&msg); 16723785Sgusella length = sizeof(struct sockaddr_in); 16823785Sgusella if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0, 16923785Sgusella &dest, length) < 0) { 17023785Sgusella perror("sendto"); 17123785Sgusella return; 17223785Sgusella } 17323785Sgusella 17423785Sgusella tout.tv_sec = 15; 17523785Sgusella tout.tv_usec = 0; 17625578Sbloom FD_ZERO(&ready); 17725578Sbloom FD_SET(sock, &ready); 17825578Sbloom if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) { 17923785Sgusella length = sizeof(struct sockaddr_in); 18023785Sgusella cc = recvfrom(sock, (char *)&msg, sizeof(struct tsp), 0, 18123785Sgusella &from, &length); 18223785Sgusella if (cc < 0) { 18323785Sgusella perror("recvfrom"); 18423785Sgusella return; 18523785Sgusella } 18623785Sgusella bytehostorder(&msg); 18723785Sgusella if (msg.tsp_type == TSP_ACK) 18823785Sgusella printf("master timedaemon runs on %s\n", msg.tsp_name); 18923785Sgusella else 19023785Sgusella printf("received wrong ack: %s\n", 19123785Sgusella tsptype[msg.tsp_type]); 19223785Sgusella } else 19323785Sgusella printf("communication error\n"); 19423785Sgusella } 19523785Sgusella 19623785Sgusella /* 19723785Sgusella * quits timedc 19823785Sgusella */ 19923785Sgusella 20023785Sgusella quit() 20123785Sgusella { 20223785Sgusella exit(0); 20323785Sgusella } 20423785Sgusella 20523785Sgusella #define MAXH 4 /* max no. of hosts where election can occur */ 20623785Sgusella 20723785Sgusella /* 20823785Sgusella * Causes the election timer to expire on the selected hosts 20923785Sgusella * It sends just one udp message per machine, relying on 21023785Sgusella * reliability of communication channel. 21123785Sgusella */ 21223785Sgusella 21323785Sgusella testing(argc, argv) 21423785Sgusella int argc; 21523785Sgusella char *argv[]; 21623785Sgusella { 21723785Sgusella int length; 21823785Sgusella int nhosts; 21923785Sgusella struct servent *srvp; 22023785Sgusella struct sockaddr_in sin[MAXH]; 22123785Sgusella struct tsp msg; 22223785Sgusella 22323785Sgusella if(argc < 2) { 22423785Sgusella printf("Usage: testing host ...\n"); 22523785Sgusella return; 22623785Sgusella } 22723785Sgusella 22823785Sgusella srvp = getservbyname("timed", "udp"); 22923785Sgusella if (srvp == 0) { 23023785Sgusella fprintf(stderr, "udp/timed: unknown service\n"); 23123785Sgusella return; 23223785Sgusella } 23323785Sgusella 23423785Sgusella nhosts = 0; 23523785Sgusella while (argc > 1) { 23623785Sgusella argc--; argv++; 23723785Sgusella hp = gethostbyname(*argv); 23823785Sgusella if (hp == NULL) { 239*35784Sbostic fprintf(stderr, "timed: %s: ", *argv); 240*35784Sbostic herror((char *)NULL); 24123785Sgusella argc--; argv++; 24223785Sgusella continue; 24323785Sgusella } 24423785Sgusella sin[nhosts].sin_port = srvp->s_port; 24523785Sgusella sin[nhosts].sin_family = hp->h_addrtype; 24623785Sgusella bcopy(hp->h_addr, &(sin[nhosts].sin_addr.s_addr), hp->h_length); 24723785Sgusella if (++nhosts == MAXH) 24823785Sgusella break; 24923785Sgusella } 25023785Sgusella 25123785Sgusella msg.tsp_type = TSP_TEST; 25223785Sgusella msg.tsp_vers = TSPVERSION; 25323785Sgusella (void)gethostname(hostname, sizeof(hostname)); 25423785Sgusella (void)strcpy(msg.tsp_name, hostname); 25523785Sgusella bytenetorder(&msg); /* it is not really necessary here */ 25623785Sgusella while (nhosts-- > 0) { 25723785Sgusella length = sizeof(struct sockaddr_in); 25823785Sgusella if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0, 25923785Sgusella &sin[nhosts], length) < 0) { 26023785Sgusella perror("sendto"); 26123785Sgusella return; 26223785Sgusella } 26323785Sgusella } 26423785Sgusella } 26523785Sgusella 26623785Sgusella /* 26723785Sgusella * Enables or disables tracing on local timedaemon 26823785Sgusella */ 26923785Sgusella 27023785Sgusella tracing(argc, argv) 27123785Sgusella int argc; 27223785Sgusella char *argv[]; 27323785Sgusella { 27423785Sgusella int onflag; 27523785Sgusella int length; 27625578Sbloom int cc; 27725578Sbloom fd_set ready; 27823785Sgusella struct sockaddr_in dest; 27923785Sgusella struct timeval tout; 28023785Sgusella struct sockaddr_in from; 28123785Sgusella struct tsp msg; 28223785Sgusella struct servent *srvp; 28323785Sgusella 28423785Sgusella if (argc != 2) { 28523785Sgusella printf("Usage: tracing { on | off }\n"); 28623785Sgusella return; 28723785Sgusella } 28823785Sgusella 28923785Sgusella srvp = getservbyname("timed", "udp"); 29023785Sgusella if (srvp == 0) { 29123785Sgusella fprintf(stderr, "udp/timed: unknown service\n"); 29223785Sgusella return; 29323785Sgusella } 29423785Sgusella dest.sin_port = srvp->s_port; 29523785Sgusella dest.sin_family = AF_INET; 29623785Sgusella 29723785Sgusella (void)gethostname(hostname,sizeof(hostname)); 29823785Sgusella hp = gethostbyname(hostname); 29923785Sgusella bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length); 30023785Sgusella 30123785Sgusella if (strcmp(argv[1], "on") == 0) { 30223785Sgusella msg.tsp_type = TSP_TRACEON; 30323785Sgusella onflag = ON; 30423785Sgusella } else { 30523785Sgusella msg.tsp_type = TSP_TRACEOFF; 30623785Sgusella onflag = OFF; 30723785Sgusella } 30823785Sgusella 30923785Sgusella (void)strcpy(msg.tsp_name, hostname); 31023785Sgusella msg.tsp_vers = TSPVERSION; 31123785Sgusella bytenetorder(&msg); 31223785Sgusella length = sizeof(struct sockaddr_in); 31323785Sgusella if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0, 31423785Sgusella &dest, length) < 0) { 31523785Sgusella perror("sendto"); 31623785Sgusella return; 31723785Sgusella } 31823785Sgusella 31923785Sgusella tout.tv_sec = 5; 32023785Sgusella tout.tv_usec = 0; 32125578Sbloom FD_ZERO(&ready); 32225578Sbloom FD_SET(sock, &ready); 32325578Sbloom if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) { 32423785Sgusella length = sizeof(struct sockaddr_in); 32523785Sgusella cc = recvfrom(sock, (char *)&msg, sizeof(struct tsp), 0, 32623785Sgusella &from, &length); 32723785Sgusella if (cc < 0) { 32823785Sgusella perror("recvfrom"); 32923785Sgusella return; 33023785Sgusella } 33123785Sgusella bytehostorder(&msg); 33223785Sgusella if (msg.tsp_type == TSP_ACK) 33323785Sgusella if (onflag) 33423785Sgusella printf("timed tracing enabled\n"); 33523785Sgusella else 33623785Sgusella printf("timed tracing disabled\n"); 33723785Sgusella else 33823785Sgusella printf("wrong ack received: %s\n", 33923785Sgusella tsptype[msg.tsp_type]); 34023785Sgusella } else 34123785Sgusella printf("communication error\n"); 34223785Sgusella } 34323785Sgusella 34423785Sgusella priv_resources() 34523785Sgusella { 34623785Sgusella int port; 34723785Sgusella struct sockaddr_in sin; 34823785Sgusella 34923785Sgusella sock = socket(AF_INET, SOCK_DGRAM, 0); 35023785Sgusella if (sock < 0) { 35123785Sgusella perror("opening socket"); 35223785Sgusella return(-1); 35323785Sgusella } 35423785Sgusella 35523785Sgusella sin.sin_family = AF_INET; 35623785Sgusella sin.sin_addr.s_addr = 0; 35723785Sgusella for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) { 35823785Sgusella sin.sin_port = htons((u_short)port); 35923785Sgusella if (bind(sock, (struct sockaddr *)&sin, sizeof (sin)) >= 0) 36023785Sgusella break; 36123785Sgusella if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) { 36223785Sgusella perror("bind"); 36323785Sgusella (void) close(sock); 36423785Sgusella return(-1); 36523785Sgusella } 36623785Sgusella } 36723785Sgusella if (port == IPPORT_RESERVED / 2) { 36823785Sgusella fprintf(stderr, "all reserved ports in use\n"); 36923785Sgusella (void) close(sock); 37023785Sgusella return(-1); 37123785Sgusella } 37223785Sgusella 37323785Sgusella sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); 37423785Sgusella if (sock_raw < 0) { 37523785Sgusella perror("opening raw socket"); 37623785Sgusella (void) close(sock_raw); 37723785Sgusella return(-1); 37823785Sgusella } 37923785Sgusella return(1); 38023785Sgusella } 381