home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / bin / date / netdate.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-04  |  5.4 KB  |  179 lines

  1. /*-
  2.  * Copyright (c) 1990 The 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[] = "@(#)netdate.c    5.2 (Berkeley) 2/25/91";
  36. #endif /* not lint */
  37.  
  38. #include <sys/param.h>
  39. #include <sys/time.h>
  40. #include <sys/socket.h>
  41. #include <sys/errno.h>
  42. #include <netinet/in.h>
  43. #include <netdb.h>
  44. #define TSPTYPES
  45. #include <protocols/timed.h>
  46. #include <unistd.h>
  47. #include <stdio.h>
  48. #include <string.h>
  49.  
  50. #define    WAITACK        2    /* seconds */
  51. #define    WAITDATEACK    5    /* seconds */
  52.  
  53. extern int retval;
  54.  
  55. /*
  56.  * Set the date in the machines controlled by timedaemons by communicating the
  57.  * new date to the local timedaemon.  If the timedaemon is in the master state,
  58.  * it performs the correction on all slaves.  If it is in the slave state, it
  59.  * notifies the master that a correction is needed.
  60.  * Returns 0 on success.  Returns > 0 on failure, setting retval to 2;
  61.  */
  62. netsettime(tval)
  63.     time_t tval;
  64. {
  65.     struct timeval tout;
  66.     struct servent *sp;
  67.     struct tsp msg;
  68.     struct sockaddr_in sin, dest, from;
  69.     fd_set ready;
  70.     long waittime;
  71.     int s, length, port, timed_ack, found, err;
  72.     char hostname[MAXHOSTNAMELEN];
  73.  
  74.     if ((sp = getservbyname("timed", "udp")) == NULL) {
  75.         (void)fprintf(stderr, "date: udp/timed: unknown service.n");
  76.         return (retval = 2);
  77.     }
  78.  
  79.     dest.sin_port = sp->s_port;
  80.     dest.sin_family = AF_INET;
  81.     dest.sin_addr.s_addr = htonl((u_long)INADDR_ANY);
  82.     s = socket(AF_INET, SOCK_DGRAM, 0);
  83.     if (s < 0) {
  84.         if (errno != EPROTONOSUPPORT)
  85.             perror("date: timed");
  86.         return(retval = 2);
  87.     }
  88.  
  89.     bzero((char *)&sin, sizeof(sin));
  90.     sin.sin_family = AF_INET;
  91.     for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) {
  92.         sin.sin_port = htons((u_short)port);
  93.         if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
  94.             break;
  95.         if (errno == EADDRINUSE)
  96.             continue;
  97.         if (errno != EADDRNOTAVAIL)
  98.             perror("date: bind");
  99.         goto bad;
  100.     }
  101.     if (port == IPPORT_RESERVED / 2) {
  102.         (void)fprintf(stderr, "date: all ports in use.\n");
  103.         goto bad;
  104.     }
  105.     msg.tsp_type = TSP_SETDATE;
  106.     msg.tsp_vers = TSPVERSION;
  107.     if (gethostname(hostname, sizeof(hostname))) {
  108.         perror("date: gethostname");
  109.         goto bad;
  110.     }
  111.     (void)strncpy(msg.tsp_name, hostname, sizeof(hostname));
  112.     msg.tsp_seq = htons((u_short)0);
  113.     msg.tsp_time.tv_sec = htonl((u_long)tval);
  114.     msg.tsp_time.tv_usec = htonl((u_long)0);
  115.     length = sizeof(struct sockaddr_in);
  116.     if (connect(s, (struct sockaddr *)&dest, length) < 0) {
  117.         perror("date: connect");
  118.         goto bad;
  119.     }
  120.     if (send(s, (char *)&msg, sizeof(struct tsp), 0) < 0) {
  121.         if (errno != ECONNREFUSED)
  122.             perror("date: send");
  123.         goto bad;
  124.     }
  125.  
  126.     timed_ack = -1;
  127.     waittime = WAITACK;
  128. loop:
  129.     tout.tv_sec = waittime;
  130.     tout.tv_usec = 0;
  131.  
  132.     FD_ZERO(&ready);
  133.     FD_SET(s, &ready);
  134.     found = select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout);
  135.  
  136.     length = sizeof(err);
  137.     if (!getsockopt(s, SOL_SOCKET, SO_ERROR, (char *)&err, &length)
  138.         && err) {
  139.         if (err != ECONNREFUSED)
  140.             perror("date: send (delayed error)");
  141.         goto bad;
  142.     }
  143.  
  144.     if (found > 0 && FD_ISSET(s, &ready)) {
  145.         length = sizeof(struct sockaddr_in);
  146.         if (recvfrom(s, &msg, sizeof(struct tsp), 0,
  147.             (struct sockaddr *)&from, &length) < 0) {
  148.             if (errno != ECONNREFUSED)
  149.                 perror("date: recvfrom");
  150.             goto bad;
  151.         }
  152.         msg.tsp_seq = ntohs(msg.tsp_seq);
  153.         msg.tsp_time.tv_sec = ntohl(msg.tsp_time.tv_sec);
  154.         msg.tsp_time.tv_usec = ntohl(msg.tsp_time.tv_usec);
  155.         switch (msg.tsp_type) {
  156.         case TSP_ACK:
  157.             timed_ack = TSP_ACK;
  158.             waittime = WAITDATEACK;
  159.             goto loop;
  160.         case TSP_DATEACK:
  161.             (void)close(s);
  162.             return (0);
  163.         default:
  164.             (void)fprintf(stderr,
  165.                 "date: wrong ack received from timed: %s.\n", 
  166.                 tsptype[msg.tsp_type]);
  167.             timed_ack = -1;
  168.             break;
  169.         }
  170.     }
  171.     if (timed_ack == -1)
  172.         (void)fprintf(stderr,
  173.             "date: can't reach time daemon, time set locally.\n");
  174.  
  175. bad:
  176.     (void)close(s);
  177.     return(retval = 2);
  178. }
  179.