1: /* 2: * Copyright (c) 1983 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #if defined(DOSCCS) && !defined(lint) 8: static char sccsid[] = "@(#)cmds.c 2.2.1 (2.11BSD GTE) 1/1/94"; 9: #endif 10: 11: #include "timedc.h" 12: #include <netinet/in_systm.h> 13: #include <netinet/ip.h> 14: #include <netinet/ip_icmp.h> 15: #define TSPTYPES 16: #include <protocols/timed.h> 17: #include <sys/file.h> 18: 19: int id; 20: int sock; 21: int sock_raw; 22: char hostname[MAXHOSTNAMELEN]; 23: struct hostent *hp, *gethostbyname(); 24: struct sockaddr_in server; 25: extern long measure_delta; 26: int bytenetorder(), bytehostorder(); 27: char *strcpy(); 28: 29: /* 30: * Clockdiff computes the difference between the time of the machine on 31: * which it is called and the time of the machines given as argument. 32: * The time differences measured by clockdiff are obtained using a sequence 33: * of ICMP TSTAMP messages which are returned to the sender by the IP module 34: * in the remote machine. 35: * In order to compare clocks of machines in different time zones, the time 36: * is transmitted (as a 32-bit value) in milliseconds since midnight UT. 37: * If a hosts uses a different time format, it should set the high order 38: * bit of the 32-bit quantity it transmits. 39: * However, VMS apparently transmits the time in milliseconds since midnight 40: * local time (rather than GMT) without setting the high order bit. 41: * Furthermore, it does not understand daylight-saving time. This makes 42: * clockdiff behaving inconsistently with hosts running VMS. 43: * 44: * In order to reduce the sensitivity to the variance of message transmission 45: * time, clockdiff sends a sequence of messages. Yet, measures between 46: * two `distant' hosts can be affected by a small error. The error can, however, 47: * be reduced by increasing the number of messages sent in each measurement. 48: */ 49: 50: clockdiff(argc, argv) 51: int argc; 52: char *argv[]; 53: { 54: int measure_status; 55: struct timeval ack; 56: int measure(); 57: 58: if(argc < 2) { 59: printf("Usage: clockdiff host ... \n"); 60: return; 61: } 62: 63: id = getpid(); 64: (void)gethostname(hostname,sizeof(hostname)); 65: 66: while (argc > 1) { 67: argc--; argv++; 68: hp = gethostbyname(*argv); 69: if (hp == NULL) { 70: printf("%s: unknown host\n", *argv); 71: continue; 72: } 73: server.sin_family = hp->h_addrtype; 74: bcopy(hp->h_addr, &(server.sin_addr.s_addr), hp->h_length); 75: ack.tv_sec = 10; 76: ack.tv_usec = 0; 77: if ((measure_status = measure(&ack, &server)) < 0) { 78: perror("measure"); 79: return; 80: } 81: switch (measure_status) { 82: 83: case HOSTDOWN: 84: printf("%s is down\n", hp->h_name); 85: continue; 86: break; 87: case NONSTDTIME: 88: printf("%s time transmitted in a non-standard format\n", hp->h_name); 89: continue; 90: break; 91: case UNREACHABLE: 92: printf("%s is unreachable\n", hp->h_name); 93: continue; 94: break; 95: default: 96: break; 97: } 98: 99: if (measure_delta > 0) 100: printf("time on %s is %D ms. ahead of time on %s\n", 101: hp->h_name, measure_delta, 102: hostname); 103: else 104: if (measure_delta == 0) 105: printf("%s and %s have the same time\n", 106: hp->h_name, hostname); 107: else 108: printf("time on %s is %D ms. behind time on %s\n", 109: hp->h_name, -measure_delta, hostname); 110: } 111: return; 112: } 113: /* 114: * finds location of master timedaemon 115: */ 116: 117: msite(argc) 118: int argc; 119: { 120: int length; 121: int cc; 122: fd_set ready; 123: struct sockaddr_in dest; 124: struct timeval tout; 125: struct sockaddr_in from; 126: struct tsp msg; 127: struct servent *srvp; 128: 129: if (argc != 1) { 130: printf("Usage: msite\n"); 131: return; 132: } 133: 134: srvp = getservbyname("timed", "udp"); 135: if (srvp == 0) { 136: fprintf(stderr, "udp/timed: unknown service\n"); 137: return; 138: } 139: dest.sin_port = srvp->s_port; 140: dest.sin_family = AF_INET; 141: 142: (void)gethostname(hostname,sizeof(hostname)); 143: hp = gethostbyname(hostname); 144: if (hp == NULL) { 145: perror("gethostbyname"); 146: return; 147: } 148: bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length); 149: 150: (void)strcpy(msg.tsp_name, hostname); 151: msg.tsp_type = TSP_MSITE; 152: msg.tsp_vers = TSPVERSION; 153: bytenetorder(&msg); 154: length = sizeof(struct sockaddr_in); 155: if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0, 156: &dest, length) < 0) { 157: perror("sendto"); 158: return; 159: } 160: 161: tout.tv_sec = 15; 162: tout.tv_usec = 0; 163: FD_ZERO(&ready); 164: FD_SET(sock, &ready); 165: if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) { 166: length = sizeof(struct sockaddr_in); 167: cc = recvfrom(sock, (char *)&msg, sizeof(struct tsp), 0, 168: &from, &length); 169: if (cc < 0) { 170: perror("recvfrom"); 171: return; 172: } 173: bytehostorder(&msg); 174: if (msg.tsp_type == TSP_ACK) 175: printf("master timedaemon runs on %s\n", msg.tsp_name); 176: else 177: printf("received wrong ack: %s\n", 178: tsptype[msg.tsp_type]); 179: } else 180: printf("communication error\n"); 181: } 182: 183: /* 184: * quits timedc 185: */ 186: 187: quit() 188: { 189: exit(0); 190: } 191: 192: #define MAXH 4 /* max no. of hosts where election can occur */ 193: 194: /* 195: * Causes the election timer to expire on the selected hosts 196: * It sends just one udp message per machine, relying on 197: * reliability of communication channel. 198: */ 199: 200: testing(argc, argv) 201: int argc; 202: char *argv[]; 203: { 204: int length; 205: int nhosts; 206: struct servent *srvp; 207: struct sockaddr_in sin[MAXH]; 208: struct tsp msg; 209: 210: if(argc < 2) { 211: printf("Usage: testing host ...\n"); 212: return; 213: } 214: 215: srvp = getservbyname("timed", "udp"); 216: if (srvp == 0) { 217: fprintf(stderr, "udp/timed: unknown service\n"); 218: return; 219: } 220: 221: nhosts = 0; 222: while (argc > 1) { 223: argc--; argv++; 224: hp = gethostbyname(*argv); 225: if (hp == NULL) { 226: printf("%s: unknown host\n", *argv); 227: argc--; argv++; 228: continue; 229: } 230: sin[nhosts].sin_port = srvp->s_port; 231: sin[nhosts].sin_family = hp->h_addrtype; 232: bcopy(hp->h_addr, &(sin[nhosts].sin_addr.s_addr), hp->h_length); 233: if (++nhosts == MAXH) 234: break; 235: } 236: 237: msg.tsp_type = TSP_TEST; 238: msg.tsp_vers = TSPVERSION; 239: (void)gethostname(hostname, sizeof(hostname)); 240: (void)strcpy(msg.tsp_name, hostname); 241: bytenetorder(&msg); /* it is not really necessary here */ 242: while (nhosts-- > 0) { 243: length = sizeof(struct sockaddr_in); 244: if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0, 245: &sin[nhosts], length) < 0) { 246: perror("sendto"); 247: return; 248: } 249: } 250: } 251: 252: /* 253: * Enables or disables tracing on local timedaemon 254: */ 255: 256: tracing(argc, argv) 257: int argc; 258: char *argv[]; 259: { 260: int onflag; 261: int length; 262: int cc; 263: fd_set ready; 264: struct sockaddr_in dest; 265: struct timeval tout; 266: struct sockaddr_in from; 267: struct tsp msg; 268: struct servent *srvp; 269: 270: if (argc != 2) { 271: printf("Usage: tracing { on | off }\n"); 272: return; 273: } 274: 275: srvp = getservbyname("timed", "udp"); 276: if (srvp == 0) { 277: fprintf(stderr, "udp/timed: unknown service\n"); 278: return; 279: } 280: dest.sin_port = srvp->s_port; 281: dest.sin_family = AF_INET; 282: 283: (void)gethostname(hostname,sizeof(hostname)); 284: hp = gethostbyname(hostname); 285: bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length); 286: 287: if (strcmp(argv[1], "on") == 0) { 288: msg.tsp_type = TSP_TRACEON; 289: onflag = ON; 290: } else { 291: msg.tsp_type = TSP_TRACEOFF; 292: onflag = OFF; 293: } 294: 295: (void)strcpy(msg.tsp_name, hostname); 296: msg.tsp_vers = TSPVERSION; 297: bytenetorder(&msg); 298: length = sizeof(struct sockaddr_in); 299: if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0, 300: &dest, length) < 0) { 301: perror("sendto"); 302: return; 303: } 304: 305: tout.tv_sec = 5; 306: tout.tv_usec = 0; 307: FD_ZERO(&ready); 308: FD_SET(sock, &ready); 309: if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) { 310: length = sizeof(struct sockaddr_in); 311: cc = recvfrom(sock, (char *)&msg, sizeof(struct tsp), 0, 312: &from, &length); 313: if (cc < 0) { 314: perror("recvfrom"); 315: return; 316: } 317: bytehostorder(&msg); 318: if (msg.tsp_type == TSP_ACK) 319: if (onflag) 320: printf("timed tracing enabled\n"); 321: else 322: printf("timed tracing disabled\n"); 323: else 324: printf("wrong ack received: %s\n", 325: tsptype[msg.tsp_type]); 326: } else 327: printf("communication error\n"); 328: } 329: 330: priv_resources() 331: { 332: int port; 333: struct sockaddr_in sin; 334: 335: sock = socket(AF_INET, SOCK_DGRAM, 0); 336: if (sock < 0) { 337: perror("opening socket"); 338: return(-1); 339: } 340: 341: sin.sin_family = AF_INET; 342: sin.sin_addr.s_addr = 0; 343: for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) { 344: sin.sin_port = htons((u_short)port); 345: if (bind(sock, (struct sockaddr *)&sin, sizeof (sin)) >= 0) 346: break; 347: if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) { 348: perror("bind"); 349: (void) close(sock); 350: return(-1); 351: } 352: } 353: if (port == IPPORT_RESERVED / 2) { 354: fprintf(stderr, "all reserved ports in use\n"); 355: (void) close(sock); 356: return(-1); 357: } 358: 359: sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); 360: if (sock_raw < 0) { 361: perror("opening raw socket"); 362: (void) close(sock_raw); 363: return(-1); 364: } 365: return(1); 366: }