Home | History | Annotate | Line # | Download | only in timedc
cmds.c revision 1.1
      1 /*
      2  * Copyright (c) 1983 Regents of the University of California.
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. All advertising materials mentioning features or use of this software
     14  *    must display the following acknowledgement:
     15  *	This product includes software developed by the University of
     16  *	California, Berkeley and its contributors.
     17  * 4. Neither the name of the University nor the names of its contributors
     18  *    may be used to endorse or promote products derived from this software
     19  *    without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  * SUCH DAMAGE.
     32  */
     33 
     34 #ifndef lint
     35 static char sccsid[] = "@(#)cmds.c	2.8 (Berkeley) 3/2/91";
     36 #endif /* not lint */
     37 
     38 #include "timedc.h"
     39 #include <netinet/in_systm.h>
     40 #include <netinet/ip.h>
     41 #include <netinet/ip_icmp.h>
     42 #define TSPTYPES
     43 #include <protocols/timed.h>
     44 #include <sys/file.h>
     45 
     46 int id;
     47 int sock;
     48 int sock_raw;
     49 char hostname[MAXHOSTNAMELEN];
     50 struct hostent *hp, *gethostbyname();
     51 struct sockaddr_in server;
     52 extern int measure_delta;
     53 int bytenetorder(), bytehostorder();
     54 char *strcpy();
     55 
     56 /*
     57  * Clockdiff computes the difference between the time of the machine on
     58  * which it is called and the time of the machines given as argument.
     59  * The time differences measured by clockdiff are obtained using a sequence
     60  * of ICMP TSTAMP messages which are returned to the sender by the IP module
     61  * in the remote machine.
     62  * In order to compare clocks of machines in different time zones, the time
     63  * is transmitted (as a 32-bit value) in milliseconds since midnight UT.
     64  * If a hosts uses a different time format, it should set the high order
     65  * bit of the 32-bit quantity it transmits.
     66  * However, VMS apparently transmits the time in milliseconds since midnight
     67  * local time (rather than GMT) without setting the high order bit.
     68  * Furthermore, it does not understand daylight-saving time.  This makes
     69  * clockdiff behaving inconsistently with hosts running VMS.
     70  *
     71  * In order to reduce the sensitivity to the variance of message transmission
     72  * time, clockdiff sends a sequence of messages.  Yet, measures between
     73  * two `distant' hosts can be affected by a small error. The error can, however,
     74  * be reduced by increasing the number of messages sent in each measurement.
     75  */
     76 
     77 clockdiff(argc, argv)
     78 int argc;
     79 char *argv[];
     80 {
     81 	int measure_status;
     82 	struct timeval ack;
     83 	int measure();
     84 
     85 	if(argc < 2)  {
     86 		printf("Usage: clockdiff host ... \n");
     87 		return;
     88 	}
     89 
     90 	id = getpid();
     91 	(void)gethostname(hostname,sizeof(hostname));
     92 
     93 	while (argc > 1) {
     94 		argc--; argv++;
     95 		hp = gethostbyname(*argv);
     96 		if (hp == NULL) {
     97 			fprintf(stderr, "timed: %s: ", *argv);
     98 			herror((char *)NULL);
     99 			continue;
    100 		}
    101 		server.sin_family = hp->h_addrtype;
    102 		bcopy(hp->h_addr, &(server.sin_addr.s_addr), hp->h_length);
    103 		ack.tv_sec = 10;
    104 		ack.tv_usec = 0;
    105 		if ((measure_status = measure(&ack, &server)) < 0) {
    106 			perror("measure");
    107 			return;
    108 		}
    109 		switch (measure_status) {
    110 
    111 		case HOSTDOWN:
    112 			printf("%s is down\n", hp->h_name);
    113 			continue;
    114 			break;
    115 		case NONSTDTIME:
    116 			printf("%s time transmitted in a non-standard format\n",						 hp->h_name);
    117 			continue;
    118 			break;
    119 		case UNREACHABLE:
    120 			printf("%s is unreachable\n", hp->h_name);
    121 			continue;
    122 			break;
    123 		default:
    124 			break;
    125 		}
    126 
    127 		if (measure_delta > 0)
    128 			printf("time on %s is %d ms. ahead of time on %s\n",
    129 						hp->h_name, measure_delta,
    130 						hostname);
    131 		else
    132 			if (measure_delta == 0)
    133 		      		printf("%s and %s have the same time\n",
    134 						hp->h_name, hostname);
    135 			else
    136 		      	     printf("time on %s is %d ms. behind time on %s\n",
    137 					hp->h_name, -measure_delta, hostname);
    138 	}
    139 	return;
    140 }
    141 /*
    142  * finds location of master timedaemon
    143  */
    144 
    145 msite(argc)
    146 int argc;
    147 {
    148 	int length;
    149 	int cc;
    150 	fd_set ready;
    151 	struct sockaddr_in dest;
    152 	struct timeval tout;
    153 	struct sockaddr_in from;
    154 	struct tsp msg;
    155 	struct servent *srvp;
    156 
    157 	if (argc != 1) {
    158 		printf("Usage: msite\n");
    159 		return;
    160 	}
    161 
    162 	srvp = getservbyname("timed", "udp");
    163 	if (srvp == 0) {
    164 		fprintf(stderr, "udp/timed: unknown service\n");
    165 		return;
    166 	}
    167 	dest.sin_port = srvp->s_port;
    168 	dest.sin_family = AF_INET;
    169 
    170 	(void)gethostname(hostname, sizeof(hostname));
    171 	hp = gethostbyname(hostname);
    172 	if (hp == NULL) {
    173 		fprintf(stderr, "timed: %s: ", hostname);
    174 		herror((char *)NULL);
    175 		return;
    176 	}
    177 	bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length);
    178 
    179 	(void)strcpy(msg.tsp_name, hostname);
    180 	msg.tsp_type = TSP_MSITE;
    181 	msg.tsp_vers = TSPVERSION;
    182 	bytenetorder(&msg);
    183 	length = sizeof(struct sockaddr_in);
    184 	if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0,
    185 	    (struct sockaddr *)&dest, length) < 0) {
    186 		perror("sendto");
    187 		return;
    188 	}
    189 
    190 	tout.tv_sec = 15;
    191 	tout.tv_usec = 0;
    192 	FD_ZERO(&ready);
    193 	FD_SET(sock, &ready);
    194 	if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) {
    195 		length = sizeof(struct sockaddr_in);
    196 		cc = recvfrom(sock, (char *)&msg, sizeof(struct tsp), 0,
    197 		    (struct sockaddr *)&from, &length);
    198 		if (cc < 0) {
    199 			perror("recvfrom");
    200 			return;
    201 		}
    202 		bytehostorder(&msg);
    203 		if (msg.tsp_type == TSP_ACK)
    204 			printf("master timedaemon runs on %s\n", msg.tsp_name);
    205 		else
    206 			printf("received wrong ack: %s\n",
    207 						tsptype[msg.tsp_type]);
    208 	} else
    209 		printf("communication error\n");
    210 }
    211 
    212 /*
    213  * quits timedc
    214  */
    215 
    216 quit()
    217 {
    218 	exit(0);
    219 }
    220 
    221 #define MAXH	4	/* max no. of hosts where election can occur */
    222 
    223 /*
    224  * Causes the election timer to expire on the selected hosts
    225  * It sends just one udp message per machine, relying on
    226  * reliability of communication channel.
    227  */
    228 
    229 testing(argc, argv)
    230 int argc;
    231 char *argv[];
    232 {
    233 	int length;
    234 	int nhosts;
    235 	struct servent *srvp;
    236 	struct sockaddr_in sin[MAXH];
    237 	struct tsp msg;
    238 
    239 	if(argc < 2)  {
    240 		printf("Usage: testing host ...\n");
    241 		return;
    242 	}
    243 
    244 	srvp = getservbyname("timed", "udp");
    245 	if (srvp == 0) {
    246 		fprintf(stderr, "udp/timed: unknown service\n");
    247 		return;
    248 	}
    249 
    250 	nhosts = 0;
    251 	while (argc > 1) {
    252 		argc--; argv++;
    253 		hp = gethostbyname(*argv);
    254 		if (hp == NULL) {
    255 			fprintf(stderr, "timed: %s: ", *argv);
    256 			herror((char *)NULL);
    257 			argc--; argv++;
    258 			continue;
    259 		}
    260 		sin[nhosts].sin_port = srvp->s_port;
    261 		sin[nhosts].sin_family = hp->h_addrtype;
    262 		bcopy(hp->h_addr, &(sin[nhosts].sin_addr.s_addr), hp->h_length);
    263 		if (++nhosts == MAXH)
    264 			break;
    265 	}
    266 
    267 	msg.tsp_type = TSP_TEST;
    268 	msg.tsp_vers = TSPVERSION;
    269 	(void)gethostname(hostname, sizeof(hostname));
    270 	(void)strcpy(msg.tsp_name, hostname);
    271 	bytenetorder(&msg);	/* it is not really necessary here */
    272 	while (nhosts-- > 0) {
    273 		length = sizeof(struct sockaddr_in);
    274 		if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0,
    275 		    (struct sockaddr *)&sin[nhosts], length) < 0) {
    276 			perror("sendto");
    277 			return;
    278 		}
    279 	}
    280 }
    281 
    282 /*
    283  * Enables or disables tracing on local timedaemon
    284  */
    285 
    286 tracing(argc, argv)
    287 int argc;
    288 char *argv[];
    289 {
    290 	int onflag;
    291 	int length;
    292 	int cc;
    293 	fd_set ready;
    294 	struct sockaddr_in dest;
    295 	struct timeval tout;
    296 	struct sockaddr_in from;
    297 	struct tsp msg;
    298 	struct servent *srvp;
    299 
    300 	if (argc != 2) {
    301 		printf("Usage: tracing { on | off }\n");
    302 		return;
    303 	}
    304 
    305 	srvp = getservbyname("timed", "udp");
    306 	if (srvp == 0) {
    307 		fprintf(stderr, "udp/timed: unknown service\n");
    308 		return;
    309 	}
    310 	dest.sin_port = srvp->s_port;
    311 	dest.sin_family = AF_INET;
    312 
    313 	(void)gethostname(hostname,sizeof(hostname));
    314 	hp = gethostbyname(hostname);
    315 	bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length);
    316 
    317 	if (strcmp(argv[1], "on") == 0) {
    318 		msg.tsp_type = TSP_TRACEON;
    319 		onflag = ON;
    320 	} else {
    321 		msg.tsp_type = TSP_TRACEOFF;
    322 		onflag = OFF;
    323 	}
    324 
    325 	(void)strcpy(msg.tsp_name, hostname);
    326 	msg.tsp_vers = TSPVERSION;
    327 	bytenetorder(&msg);
    328 	length = sizeof(struct sockaddr_in);
    329 	if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0,
    330 	    (struct sockaddr *)&dest, length) < 0) {
    331 		perror("sendto");
    332 		return;
    333 	}
    334 
    335 	tout.tv_sec = 5;
    336 	tout.tv_usec = 0;
    337 	FD_ZERO(&ready);
    338 	FD_SET(sock, &ready);
    339 	if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) {
    340 		length = sizeof(struct sockaddr_in);
    341 		cc = recvfrom(sock, (char *)&msg, sizeof(struct tsp), 0,
    342 		    (struct sockaddr *)&from, &length);
    343 		if (cc < 0) {
    344 			perror("recvfrom");
    345 			return;
    346 		}
    347 		bytehostorder(&msg);
    348 		if (msg.tsp_type == TSP_ACK)
    349 			if (onflag)
    350 				printf("timed tracing enabled\n");
    351 			else
    352 				printf("timed tracing disabled\n");
    353 		else
    354 			printf("wrong ack received: %s\n",
    355 						tsptype[msg.tsp_type]);
    356 	} else
    357 		printf("communication error\n");
    358 }
    359 
    360 priv_resources()
    361 {
    362 	int port;
    363 	struct sockaddr_in sin;
    364 
    365 	sock = socket(AF_INET, SOCK_DGRAM, 0);
    366 	if (sock < 0) {
    367 		perror("opening socket");
    368 		return(-1);
    369 	}
    370 
    371 	sin.sin_family = AF_INET;
    372 	sin.sin_addr.s_addr = 0;
    373 	for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) {
    374 		sin.sin_port = htons((u_short)port);
    375 		if (bind(sock, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
    376 			break;
    377 		if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) {
    378 			perror("bind");
    379 			(void) close(sock);
    380 			return(-1);
    381 		}
    382 	}
    383 	if (port == IPPORT_RESERVED / 2) {
    384 		fprintf(stderr, "all reserved ports in use\n");
    385 		(void) close(sock);
    386 		return(-1);
    387 	}
    388 
    389 	sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
    390 	if (sock_raw < 0)  {
    391 		perror("opening raw socket");
    392 		(void) close(sock_raw);
    393 		return(-1);
    394 	}
    395 	return(1);
    396 }
    397