File:  [DragonFly] / src / usr.sbin / timed / timedc / cmds.c
Revision 1.2: download - view: text, annotated - select for diffs
Tue Jun 17 04:30:03 2003 UTC (11 years, 2 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids.  Most
ids have been removed from !lint sections and moved into comment sections.

    1: /*-
    2:  * Copyright (c) 1985, 1993
    3:  *	The Regents of the University of California.  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:  * @(#)cmds.c	8.1 (Berkeley) 6/6/93
   34:  * $FreeBSD: src/usr.sbin/timed/timedc/cmds.c,v 1.6.2.2 2001/08/31 08:02:06 kris Exp $
   35:  * $DragonFly: src/usr.sbin/timed/timedc/cmds.c,v 1.2 2003/06/17 04:30:03 dillon Exp $
   36:  */
   37: 
   38: #include "timedc.h"
   39: #include <sys/file.h>
   40: 
   41: #include <netinet/in_systm.h>
   42: #include <netinet/ip.h>
   43: #include <netinet/ip_icmp.h>
   44: 
   45: #include <err.h>
   46: #include <stdlib.h>
   47: #include <strings.h>
   48: #include <unistd.h>
   49: 
   50: #define TSPTYPES
   51: #include <protocols/timed.h>
   52: 
   53: #ifdef sgi
   54: #include <bstring.h>
   55: #include <sys/clock.h>
   56: #else
   57: #define	SECHR	(60*60)
   58: #define	SECDAY	(24*SECHR)
   59: #endif /* sgi */
   60: 
   61: # define DATE_PROTO "udp"
   62: # define DATE_PORT "time"
   63: 
   64: 
   65: int sock;
   66: int sock_raw;
   67: char myname[MAXHOSTNAMELEN];
   68: struct hostent *hp;
   69: struct sockaddr_in server;
   70: struct sockaddr_in dayaddr;
   71: extern int measure_delta;
   72: 
   73: void bytenetorder(struct tsp *);
   74: void bytehostorder(struct tsp *);
   75: 
   76: 
   77: #define BU (2208988800UL)	/* seconds before UNIX epoch */
   78: 
   79: 
   80: /* compute the difference between our date and another machine
   81:  */
   82: static int				/* difference in days from our time */
   83: daydiff(hostname)
   84: 	char *hostname;
   85: {
   86: 	int i;
   87: 	int trials;
   88: 	struct timeval tout, now;
   89: 	fd_set ready;
   90: 	struct sockaddr from;
   91: 	int fromlen;
   92: 	unsigned long sec;
   93: 
   94: 
   95: 	/* wait 2 seconds between 10 tries */
   96: 	tout.tv_sec = 2;
   97: 	tout.tv_usec = 0;
   98: 	for (trials = 0; trials < 10; trials++) {
   99: 		/* ask for the time */
  100: 		sec = 0;
  101: 		if (sendto(sock, &sec, sizeof(sec), 0,
  102: 			   (struct sockaddr*)&dayaddr, sizeof(dayaddr)) < 0) {
  103: 			warn("sendto(sock)");
  104: 			return 0;
  105: 		}
  106: 
  107: 		for (;;) {
  108: 			FD_ZERO(&ready);
  109: 			FD_SET(sock, &ready);
  110: 			i = select(sock+1, &ready, (fd_set *)0,
  111: 				   (fd_set *)0, &tout);
  112: 			if (i < 0) {
  113: 				if (errno == EINTR)
  114: 					continue;
  115: 				warn("select(date read)");
  116: 				return 0;
  117: 			}
  118: 			if (0 == i)
  119: 				break;
  120: 
  121: 			fromlen = sizeof(from);
  122: 			if (recvfrom(sock,&sec,sizeof(sec),0,
  123: 				     &from,&fromlen) < 0) {
  124: 				warn("recvfrom(date read)");
  125: 				return 0;
  126: 			}
  127: 
  128: 			sec = ntohl(sec);
  129: 			if (sec < BU) {
  130: 				warnx("%s says it is before 1970: %lu",
  131: 					hostname, sec);
  132: 				return 0;
  133: 			}
  134: 			sec -= BU;
  135: 
  136: 			(void)gettimeofday(&now, (struct timezone*)0);
  137: 			return (sec - now.tv_sec);
  138: 		}
  139: 	}
  140: 
  141: 	/* if we get here, we tried too many times */
  142: 	warnx("%s will not tell us the date", hostname);
  143: 	return 0;
  144: }
  145: 
  146: 
  147: /*
  148:  * Clockdiff computes the difference between the time of the machine on
  149:  * which it is called and the time of the machines given as argument.
  150:  * The time differences measured by clockdiff are obtained using a sequence
  151:  * of ICMP TSTAMP messages which are returned to the sender by the IP module
  152:  * in the remote machine.
  153:  * In order to compare clocks of machines in different time zones, the time
  154:  * is transmitted (as a 32-bit value) in milliseconds since midnight UT.
  155:  * If a hosts uses a different time format, it should set the high order
  156:  * bit of the 32-bit quantity it transmits.
  157:  * However, VMS apparently transmits the time in milliseconds since midnight
  158:  * local time (rather than GMT) without setting the high order bit.
  159:  * Furthermore, it does not understand daylight-saving time.  This makes
  160:  * clockdiff behaving inconsistently with hosts running VMS.
  161:  *
  162:  * In order to reduce the sensitivity to the variance of message transmission
  163:  * time, clockdiff sends a sequence of messages.  Yet, measures between
  164:  * two `distant' hosts can be affected by a small error. The error can,
  165:  * however, be reduced by increasing the number of messages sent in each
  166:  * measurement.
  167:  */
  168: void
  169: clockdiff(argc, argv)
  170: 	int argc;
  171: 	char *argv[];
  172: {
  173: 	int measure_status;
  174: 	extern int measure(u_long, u_long, char *, struct sockaddr_in*, int);
  175: 	register int avg_cnt;
  176: 	register long avg;
  177: 	struct servent *sp;
  178: 
  179: 	if (argc < 2)  {
  180: 		printf("usage: timedc clockdiff host ...\n");
  181: 		return;
  182: 	}
  183: 
  184: 	if (gethostname(myname, sizeof(myname) - 1) < 0)
  185: 		err(1, "gethostname");
  186: 
  187: 	/* get the address for the date ready */
  188: 	sp = getservbyname(DATE_PORT, DATE_PROTO);
  189: 	if (!sp) {
  190: 		warnx("%s/%s is an unknown service", DATE_PORT, DATE_PROTO);
  191: 		dayaddr.sin_port = 0;
  192: 	} else {
  193: 		dayaddr.sin_port = sp->s_port;
  194: 	}
  195: 
  196: 	while (argc > 1) {
  197: 		argc--; argv++;
  198: 		hp = gethostbyname(*argv);
  199: 		if (hp == NULL) {
  200: 			warnx("%s: %s", *argv, hstrerror(h_errno));
  201: 			continue;
  202: 		}
  203: 
  204: 		server.sin_family = hp->h_addrtype;
  205: 		bcopy(hp->h_addr, &server.sin_addr.s_addr, hp->h_length);
  206: 		for (avg_cnt = 0, avg = 0; avg_cnt < 16; avg_cnt++) {
  207: 			measure_status = measure(10000,100, *argv, &server, 1);
  208: 			if (measure_status != GOOD)
  209: 				break;
  210: 			avg += measure_delta;
  211: 		}
  212: 		if (measure_status == GOOD)
  213: 			measure_delta = avg/avg_cnt;
  214: 
  215: 		switch (measure_status) {
  216: 		case HOSTDOWN:
  217: 			printf("%s is down\n", hp->h_name);
  218: 			continue;
  219: 		case NONSTDTIME:
  220: 			printf("%s transmitts a non-standard time format\n",
  221: 			       hp->h_name);
  222: 			continue;
  223: 		case UNREACHABLE:
  224: 			printf("%s is unreachable\n", hp->h_name);
  225: 			continue;
  226: 		}
  227: 
  228: 		/*
  229: 		 * Try to get the date only after using ICMP timestamps to
  230: 		 * get the time.  This is because the date protocol
  231: 		 * is optional.
  232: 		 */
  233: 		if (dayaddr.sin_port != 0) {
  234: 			dayaddr.sin_family = hp->h_addrtype;
  235: 			bcopy(hp->h_addr, &dayaddr.sin_addr.s_addr,
  236: 			      hp->h_length);
  237: 			avg = daydiff(*argv);
  238: 			if (avg > SECDAY) {
  239: 				printf("time on %s is %ld days ahead %s\n",
  240: 				       hp->h_name, avg/SECDAY, myname);
  241: 				continue;
  242: 			} else if (avg < -SECDAY) {
  243: 				printf("time on %s is %ld days behind %s\n",
  244: 				       hp->h_name, -avg/SECDAY, myname);
  245: 				continue;
  246: 			}
  247: 		}
  248: 
  249: 		if (measure_delta > 0) {
  250: 			printf("time on %s is %d ms. ahead of time on %s\n",
  251: 			       hp->h_name, measure_delta, myname);
  252: 		} else if (measure_delta == 0) {
  253: 			printf("%s and %s have the same time\n",
  254: 			       hp->h_name, myname);
  255: 		} else {
  256: 			printf("time on %s is %d ms. behind time on %s\n",
  257: 			       hp->h_name, -measure_delta, myname);
  258: 		}
  259: 	}
  260: 	return;
  261: }
  262: 
  263: 
  264: /*
  265:  * finds location of master timedaemon
  266:  */
  267: void
  268: msite(argc, argv)
  269: 	int argc;
  270: 	char *argv[];
  271: {
  272: 	int cc;
  273: 	fd_set ready;
  274: 	struct sockaddr_in dest;
  275: 	int i, length;
  276: 	struct sockaddr_in from;
  277: 	struct timeval tout;
  278: 	struct tsp msg;
  279: 	struct servent *srvp;
  280: 	char *tgtname;
  281: 
  282: 	if (argc < 1) {
  283: 		printf("usage: timedc msite [host ...]\n");
  284: 		return;
  285: 	}
  286: 
  287: 	srvp = getservbyname("timed", "udp");
  288: 	if (srvp == 0) {
  289: 		warnx("udp/timed: unknown service");
  290: 		return;
  291: 	}
  292: 	dest.sin_port = srvp->s_port;
  293: 	dest.sin_family = AF_INET;
  294: 
  295: 	if (gethostname(myname, sizeof(myname) - 1) < 0)
  296: 		err(1, "gethostname");
  297: 	i = 1;
  298: 	do {
  299: 		tgtname = (i >= argc) ? myname : argv[i];
  300: 		hp = gethostbyname(tgtname);
  301: 		if (hp == 0) {
  302: 			warnx("%s: %s", tgtname, hstrerror(h_errno));
  303: 			continue;
  304: 		}
  305: 		bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length);
  306: 
  307: 		(void)strlcpy(msg.tsp_name, myname, sizeof(msg.tsp_name));
  308: 		msg.tsp_type = TSP_MSITE;
  309: 		msg.tsp_vers = TSPVERSION;
  310: 		bytenetorder(&msg);
  311: 		if (sendto(sock, &msg, sizeof(struct tsp), 0,
  312: 			   (struct sockaddr*)&dest,
  313: 			   sizeof(struct sockaddr)) < 0) {
  314: 			warn("sendto");
  315: 			continue;
  316: 		}
  317: 
  318: 		tout.tv_sec = 15;
  319: 		tout.tv_usec = 0;
  320: 		FD_ZERO(&ready);
  321: 		FD_SET(sock, &ready);
  322: 		if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0,
  323: 			   &tout)) {
  324: 			length = sizeof(from);
  325: 			cc = recvfrom(sock, &msg, sizeof(struct tsp), 0,
  326: 				      (struct sockaddr *)&from, &length);
  327: 			if (cc < 0) {
  328: 				warn("recvfrom");
  329: 				continue;
  330: 			}
  331: 			/*
  332: 			 * The 4.3BSD protocol spec had a 32-byte tsp_name field, and
  333: 			 * this is still OS-dependent.  Demand that the packet is at
  334: 			 * least long enough to hold a 4.3BSD packet.
  335: 			 */
  336: 			if (cc < (sizeof(struct tsp) - MAXHOSTNAMELEN + 32)) {
  337: 				fprintf(stderr, 
  338: 				   "short packet (%u/%u bytes) from %s\n",
  339: 				   cc, sizeof(struct tsp) - MAXHOSTNAMELEN + 32,
  340: 				   inet_ntoa(from.sin_addr));
  341: 				continue;
  342: 			}
  343: 			bytehostorder(&msg);
  344: 			if (msg.tsp_type == TSP_ACK) {
  345: 				printf("master timedaemon at %s is %s\n",
  346: 				       tgtname, msg.tsp_name);
  347: 			} else {
  348: 				if (msg.tsp_type >= TSPTYPENUMBER)
  349: 					printf("unknown ack received: %u\n",
  350: 						msg.tsp_type);
  351: 				else	
  352: 					printf("wrong ack received: %s\n",
  353: 				       		tsptype[msg.tsp_type]);
  354: 			}
  355: 		} else {
  356: 			printf("communication error with %s\n", tgtname);
  357: 		}
  358: 	} while (++i < argc);
  359: }
  360: 
  361: /*
  362:  * quits timedc
  363:  */
  364: void
  365: quit()
  366: {
  367: 	exit(0);
  368: }
  369: 
  370: 
  371: /*
  372:  * Causes the election timer to expire on the selected hosts
  373:  * It sends just one udp message per machine, relying on
  374:  * reliability of communication channel.
  375:  */
  376: void
  377: testing(argc, argv)
  378: 	int argc;
  379: 	char *argv[];
  380: {
  381: 	struct servent *srvp;
  382: 	struct sockaddr_in sin;
  383: 	struct tsp msg;
  384: 
  385: 	if (argc < 2)  {
  386: 		printf("usage: timedc election host1 [host2 ...]\n");
  387: 		return;
  388: 	}
  389: 
  390: 	srvp = getservbyname("timed", "udp");
  391: 	if (srvp == 0) {
  392: 		warnx("udp/timed: unknown service");
  393: 		return;
  394: 	}
  395: 
  396: 	while (argc > 1) {
  397: 		argc--; argv++;
  398: 		hp = gethostbyname(*argv);
  399: 		if (hp == NULL) {
  400: 			warnx("%s: %s", *argv, hstrerror(h_errno));
  401: 			argc--; argv++;
  402: 			continue;
  403: 		}
  404: 		sin.sin_port = srvp->s_port;
  405: 		sin.sin_family = hp->h_addrtype;
  406: 		bcopy(hp->h_addr, &sin.sin_addr.s_addr, hp->h_length);
  407: 
  408: 		msg.tsp_type = TSP_TEST;
  409: 		msg.tsp_vers = TSPVERSION;
  410: 		if (gethostname(myname, sizeof(myname) - 1) < 0)
  411: 			err(1, "gethostname");
  412: 		(void)strlcpy(msg.tsp_name, myname, sizeof(msg.tsp_name));
  413: 		bytenetorder(&msg);
  414: 		if (sendto(sock, &msg, sizeof(struct tsp), 0,
  415: 			   (struct sockaddr*)&sin,
  416: 			   sizeof(struct sockaddr)) < 0) {
  417: 			warn("sendto");
  418: 		}
  419: 	}
  420: }
  421: 
  422: 
  423: /*
  424:  * Enables or disables tracing on local timedaemon
  425:  */
  426: void
  427: tracing(argc, argv)
  428: 	int argc;
  429: 	char *argv[];
  430: {
  431: 	int onflag;
  432: 	int length;
  433: 	int cc;
  434: 	fd_set ready;
  435: 	struct sockaddr_in dest;
  436: 	struct sockaddr_in from;
  437: 	struct timeval tout;
  438: 	struct tsp msg;
  439: 	struct servent *srvp;
  440: 
  441: 	if (argc != 2) {
  442: 		printf("usage: timedc trace { on | off }\n");
  443: 		return;
  444: 	}
  445: 
  446: 	srvp = getservbyname("timed", "udp");
  447: 	if (srvp == 0) {
  448: 		warnx("udp/timed: unknown service");
  449: 		return;
  450: 	}
  451: 	dest.sin_port = srvp->s_port;
  452: 	dest.sin_family = AF_INET;
  453: 
  454: 	if (gethostname(myname, sizeof(myname) - 1) < 0)
  455: 		err(1, "gethostname");
  456: 	hp = gethostbyname(myname);
  457: 	bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length);
  458: 
  459: 	if (strcmp(argv[1], "on") == 0) {
  460: 		msg.tsp_type = TSP_TRACEON;
  461: 		onflag = ON;
  462: 	} else {
  463: 		msg.tsp_type = TSP_TRACEOFF;
  464: 		onflag = OFF;
  465: 	}
  466: 
  467: 	(void)strcpy(msg.tsp_name, myname);
  468: 	msg.tsp_vers = TSPVERSION;
  469: 	bytenetorder(&msg);
  470: 	if (sendto(sock, &msg, sizeof(struct tsp), 0,
  471: 		   (struct sockaddr*)&dest, sizeof(struct sockaddr)) < 0) {
  472: 		warn("sendto");
  473: 		return;
  474: 	}
  475: 
  476: 	tout.tv_sec = 5;
  477: 	tout.tv_usec = 0;
  478: 	FD_ZERO(&ready);
  479: 	FD_SET(sock, &ready);
  480: 	if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) {
  481: 		length = sizeof(from);
  482: 		cc = recvfrom(sock, &msg, sizeof(struct tsp), 0,
  483: 			      (struct sockaddr *)&from, &length);
  484: 		if (cc < 0) {
  485: 			warn("recvfrom");
  486: 			return;
  487: 		}
  488: 		/*
  489: 		 * The 4.3BSD protocol spec had a 32-byte tsp_name field, and
  490: 		 * this is still OS-dependent.  Demand that the packet is at
  491: 		 * least long enough to hold a 4.3BSD packet.
  492: 		 */
  493: 		if (cc < (sizeof(struct tsp) - MAXHOSTNAMELEN + 32)) {
  494: 			fprintf(stderr, "short packet (%u/%u bytes) from %s\n",
  495: 			    cc, sizeof(struct tsp) - MAXHOSTNAMELEN + 32,
  496: 			    inet_ntoa(from.sin_addr));
  497: 			return;
  498: 		}
  499: 		bytehostorder(&msg);
  500: 		if (msg.tsp_type == TSP_ACK)
  501: 			if (onflag)
  502: 				printf("timed tracing enabled\n");
  503: 			else
  504: 				printf("timed tracing disabled\n");
  505: 		else {
  506: 			if (msg.tsp_type >= TSPTYPENUMBER)
  507: 				printf("unknown ack received: %u\n",
  508: 					msg.tsp_type);
  509: 			else	
  510: 				printf("wrong ack received: %s\n",
  511: 						tsptype[msg.tsp_type]);
  512: 		}
  513: 	} else
  514: 		printf("communication error\n");
  515: }
  516: 
  517: int
  518: priv_resources()
  519: {
  520: 	int port;
  521: 	struct sockaddr_in sin;
  522: 
  523: 	sock = socket(AF_INET, SOCK_DGRAM, 0);
  524: 	if (sock < 0) {
  525: 		warn("opening socket");
  526: 		return(-1);
  527: 	}
  528: 
  529: 	sin.sin_family = AF_INET;
  530: 	sin.sin_addr.s_addr = 0;
  531: 	for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) {
  532: 		sin.sin_port = htons((u_short)port);
  533: 		if (bind(sock, (struct sockaddr*)&sin, sizeof (sin)) >= 0)
  534: 			break;
  535: 		if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) {
  536: 			warn("bind");
  537: 			(void) close(sock);
  538: 			return(-1);
  539: 		}
  540: 	}
  541: 	if (port == IPPORT_RESERVED / 2) {
  542: 		warnx("all reserved ports in use");
  543: 		(void) close(sock);
  544: 		return(-1);
  545: 	}
  546: 
  547: 	sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
  548: 	if (sock_raw < 0)  {
  549: 		warn("opening raw socket");
  550: 		(void) close(sock);
  551: 		return(-1);
  552: 	}
  553: 	return(1);
  554: }