PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

bin/date/netdate.c

http://www.minix3.org/
C | 200 lines | 142 code | 22 blank | 36 comment | 32 complexity | 6ab7ec7ba7f1917fa85a730e84fc7d08 MD5 | raw file
Possible License(s): MIT, WTFPL, AGPL-1.0, BSD-3-Clause, GPL-3.0, LGPL-2.0, JSON, 0BSD
  1. /* $NetBSD: netdate.c,v 1.30 2011/01/29 02:16:52 christos Exp $ */
  2. /*-
  3. * Copyright (c) 1990, 1993
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the University nor the names of its contributors
  15. * may be used to endorse or promote products derived from this software
  16. * without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  22. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  24. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. */
  30. #include <sys/cdefs.h>
  31. #ifndef lint
  32. #if 0
  33. static char sccsid[] = "@(#)netdate.c 8.2 (Berkeley) 4/28/95";
  34. #else
  35. __RCSID("$NetBSD: netdate.c,v 1.30 2011/01/29 02:16:52 christos Exp $");
  36. #endif
  37. #endif /* not lint */
  38. #include <sys/param.h>
  39. #include <sys/time.h>
  40. #include <sys/socket.h>
  41. #include <netinet/in.h>
  42. #include <netdb.h>
  43. #define TSPTYPES
  44. #include <protocols/timed.h>
  45. #include <err.h>
  46. #include <errno.h>
  47. #include <poll.h>
  48. #include <stdio.h>
  49. #include <string.h>
  50. #include <unistd.h>
  51. #include "extern.h"
  52. #define WAITACK 2000 /* milliseconds */
  53. #define WAITDATEACK 5000 /* milliseconds */
  54. static const char *
  55. tsp_type_to_string(const struct tsp *msg)
  56. {
  57. unsigned i;
  58. i = msg->tsp_type;
  59. return i < TSPTYPENUMBER ? tsptype[i] : "unknown";
  60. }
  61. /*
  62. * Set the date in the machines controlled by timedaemons by communicating the
  63. * new date to the local timedaemon. If the timedaemon is in the master state,
  64. * it performs the correction on all slaves. If it is in the slave state, it
  65. * notifies the master that a correction is needed.
  66. * Returns 0 on success. Returns > 0 on failure.
  67. */
  68. int
  69. netsettime(time_t tval)
  70. {
  71. struct sockaddr_in dest;
  72. struct tsp msg;
  73. char hostname[MAXHOSTNAMELEN];
  74. struct servent *sp;
  75. struct pollfd ready;
  76. int found, s, timed_ack, waittime;
  77. if ((sp = getservbyname("timed", "udp")) == NULL) {
  78. warnx("udp/timed: unknown service");
  79. return 2;
  80. }
  81. (void)memset(&dest, 0, sizeof(dest));
  82. #ifdef BSD4_4
  83. dest.sin_len = sizeof(dest);
  84. #endif
  85. dest.sin_family = AF_INET;
  86. dest.sin_port = sp->s_port;
  87. dest.sin_addr.s_addr = htonl(INADDR_ANY);
  88. s = socket(AF_INET, SOCK_DGRAM, 0);
  89. if (s == -1) {
  90. if (errno != EAFNOSUPPORT)
  91. warn("timed");
  92. return 2;
  93. }
  94. #ifdef IP_PORTRANGE
  95. {
  96. static const int on = IP_PORTRANGE_LOW;
  97. if (setsockopt(s, IPPROTO_IP, IP_PORTRANGE, &on,
  98. sizeof(on)) == -1) {
  99. warn("setsockopt");
  100. goto bad;
  101. }
  102. }
  103. #endif
  104. msg.tsp_type = TSP_SETDATE;
  105. msg.tsp_vers = TSPVERSION;
  106. if (gethostname(hostname, sizeof(hostname)) == -1) {
  107. warn("gethostname");
  108. goto bad;
  109. }
  110. (void)strlcpy(msg.tsp_name, hostname, sizeof(msg.tsp_name));
  111. msg.tsp_seq = htons((in_port_t)0);
  112. msg.tsp_time.tv_sec = htonl((in_addr_t)tval); /* XXX: y2038 */
  113. msg.tsp_time.tv_usec = htonl((in_addr_t)0);
  114. if (connect(s, (const void *)&dest, sizeof(dest)) == -1) {
  115. warn("connect");
  116. goto bad;
  117. }
  118. if (send(s, &msg, sizeof(msg), 0) == -1) {
  119. if (errno != ECONNREFUSED)
  120. warn("send");
  121. goto bad;
  122. }
  123. timed_ack = -1;
  124. waittime = WAITACK;
  125. ready.fd = s;
  126. ready.events = POLLIN;
  127. loop:
  128. found = poll(&ready, 1, waittime);
  129. {
  130. socklen_t len;
  131. int error;
  132. len = sizeof(error);
  133. if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len) == -1) {
  134. warn("getsockopt");
  135. goto bad;
  136. }
  137. if (error) {
  138. if (error != ECONNREFUSED) {
  139. errno = error;
  140. warn("send (delayed error)");
  141. }
  142. goto bad;
  143. }
  144. }
  145. if (found > 0 && ready.revents & POLLIN) {
  146. ssize_t ret;
  147. if ((ret = recv(s, &msg, sizeof(msg), 0)) == -1) {
  148. if (errno != ECONNREFUSED)
  149. warn("recv");
  150. goto bad;
  151. } else if ((size_t)ret < sizeof(msg)) {
  152. warnx("recv: incomplete packet");
  153. goto bad;
  154. }
  155. msg.tsp_seq = ntohs(msg.tsp_seq);
  156. msg.tsp_time.tv_sec = ntohl(msg.tsp_time.tv_sec);
  157. msg.tsp_time.tv_usec = ntohl(msg.tsp_time.tv_usec);
  158. switch (msg.tsp_type) {
  159. case TSP_ACK:
  160. timed_ack = TSP_ACK;
  161. waittime = WAITDATEACK;
  162. goto loop;
  163. case TSP_DATEACK:
  164. (void)close(s);
  165. return 0;
  166. default:
  167. warnx("wrong ack received from timed: %s",
  168. tsp_type_to_string(&msg));
  169. timed_ack = -1;
  170. break;
  171. }
  172. }
  173. if (timed_ack == -1)
  174. warnx("can't reach time daemon, time set locally");
  175. bad:
  176. (void)close(s);
  177. return 2;
  178. }