home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.sbin / timed / timedc / cmds.c next >
Encoding:
C/C++ Source or Header  |  1991-04-20  |  10.1 KB  |  397 lines

  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.