]>
Commit | Line | Data |
---|---|---|
800d775e | 1 | /* |
a7ab6ec8 | 2 | * Copyright (c) 2010, Oracle America, Inc. |
cb636bb2 | 3 | * |
a7ab6ec8 UD |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions are | |
6 | * met: | |
cb636bb2 | 7 | * |
a7ab6ec8 UD |
8 | * * Redistributions of source code must retain the above copyright |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * * Redistributions in binary form must reproduce the above | |
11 | * copyright notice, this list of conditions and the following | |
12 | * disclaimer in the documentation and/or other materials | |
13 | * provided with the distribution. | |
14 | * * Neither the name of the "Oracle America, Inc." nor the names of its | |
15 | * contributors may be used to endorse or promote products derived | |
16 | * from this software without specific prior written permission. | |
ba488034 | 17 | * |
a7ab6ec8 UD |
18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
21 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
22 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |
23 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | |
25 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
27 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
800d775e UD |
30 | */ |
31 | /* | |
32 | * rtime - get time from remote machine | |
33 | * | |
34 | * gets time, obtaining value from host | |
35 | * on the udp/time socket. Since timeserver returns | |
36 | * with time of day in seconds since Jan 1, 1900, must | |
37 | * subtract seconds before Jan 1, 1970 to get | |
38 | * what unix uses. | |
39 | */ | |
40 | #include <stdio.h> | |
41 | #include <unistd.h> | |
42 | #include <rpc/rpc.h> | |
43 | #include <rpc/clnt.h> | |
44 | #include <sys/types.h> | |
ba488034 | 45 | #include <sys/poll.h> |
800d775e UD |
46 | #include <sys/socket.h> |
47 | #include <sys/time.h> | |
48 | #include <rpc/auth_des.h> | |
49 | #include <errno.h> | |
50 | #include <netinet/in.h> | |
51 | ||
52 | #define NYEARS (u_long)(1970 - 1900) | |
53 | #define TOFFSET (u_long)(60*60*24*(365*NYEARS + (NYEARS/4))) | |
54 | ||
55 | static void do_close (int); | |
56 | ||
57 | static void | |
58 | do_close (int s) | |
59 | { | |
60 | int save; | |
61 | ||
62 | save = errno; | |
50304ef0 | 63 | __close (s); |
800d775e UD |
64 | __set_errno (save); |
65 | } | |
66 | ||
67 | int | |
f8afba91 UD |
68 | rtime (struct sockaddr_in *addrp, struct rpc_timeval *timep, |
69 | struct rpc_timeval *timeout) | |
800d775e UD |
70 | { |
71 | int s; | |
ba488034 UD |
72 | struct pollfd fd; |
73 | int milliseconds; | |
800d775e | 74 | int res; |
425838aa UD |
75 | /* RFC 868 says the time is transmitted as a 32-bit value. */ |
76 | uint32_t thetime; | |
800d775e | 77 | struct sockaddr_in from; |
9cfe5381 | 78 | socklen_t fromlen; |
800d775e UD |
79 | int type; |
80 | ||
81 | if (timeout == NULL) | |
82 | type = SOCK_STREAM; | |
83 | else | |
84 | type = SOCK_DGRAM; | |
85 | ||
50304ef0 | 86 | s = __socket (AF_INET, type, 0); |
800d775e UD |
87 | if (s < 0) |
88 | return (-1); | |
89 | ||
90 | addrp->sin_family = AF_INET; | |
91 | addrp->sin_port = htons (IPPORT_TIMESERVER); | |
92 | if (type == SOCK_DGRAM) | |
93 | { | |
b2bffca2 UD |
94 | res = __sendto (s, (char *) &thetime, sizeof (thetime), 0, |
95 | (struct sockaddr *) addrp, sizeof (*addrp)); | |
800d775e UD |
96 | if (res < 0) |
97 | { | |
98 | do_close (s); | |
99 | return -1; | |
100 | } | |
ba488034 UD |
101 | milliseconds = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000); |
102 | fd.fd = s; | |
103 | fd.events = POLLIN; | |
800d775e | 104 | do |
ba488034 | 105 | res = __poll (&fd, 1, milliseconds); |
800d775e UD |
106 | while (res < 0 && errno == EINTR); |
107 | if (res <= 0) | |
108 | { | |
109 | if (res == 0) | |
110 | __set_errno (ETIMEDOUT); | |
111 | do_close (s); | |
112 | return (-1); | |
113 | } | |
114 | fromlen = sizeof (from); | |
b2bffca2 UD |
115 | res = __recvfrom (s, (char *) &thetime, sizeof (thetime), 0, |
116 | (struct sockaddr *) &from, &fromlen); | |
800d775e UD |
117 | do_close (s); |
118 | if (res < 0) | |
119 | return -1; | |
120 | } | |
121 | else | |
122 | { | |
50304ef0 | 123 | if (__connect (s, (struct sockaddr *) addrp, sizeof (*addrp)) < 0) |
800d775e UD |
124 | { |
125 | do_close (s); | |
126 | return -1; | |
127 | } | |
50304ef0 | 128 | res = __read (s, (char *) &thetime, sizeof (thetime)); |
800d775e UD |
129 | do_close (s); |
130 | if (res < 0) | |
131 | return (-1); | |
132 | } | |
133 | if (res != sizeof (thetime)) | |
134 | { | |
135 | __set_errno (EIO); | |
136 | return -1; | |
137 | } | |
138 | thetime = ntohl (thetime); | |
139 | timep->tv_sec = thetime - TOFFSET; | |
140 | timep->tv_usec = 0; | |
141 | return 0; | |
142 | } | |
7a8bdff0 | 143 | libc_hidden_def (rtime) |