1 /*
2 * Copyright (c) 2005 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * $DragonFly: src/usr.sbin/dntpd/ntpreq.c,v 1.3 2005/04/24 09:39:27 dillon Exp $
35 */
36
37 #include "defs.h"
38
39 static __inline void
s_fixedpt_ntoh(struct s_fixedpt * fixed)40 s_fixedpt_ntoh(struct s_fixedpt *fixed)
41 {
42 fixed->int_parts = ntohs(fixed->int_parts);
43 fixed->fractions = ntohs(fixed->fractions);
44 }
45
46 static __inline void
s_fixedpt_hton(struct s_fixedpt * fixed)47 s_fixedpt_hton(struct s_fixedpt *fixed)
48 {
49 fixed->int_parts = htons(fixed->int_parts);
50 fixed->fractions = htons(fixed->fractions);
51 }
52
53
54 static __inline void
l_fixedpt_ntoh(struct l_fixedpt * fixed)55 l_fixedpt_ntoh(struct l_fixedpt *fixed)
56 {
57 fixed->int_partl = ntohl(fixed->int_partl);
58 fixed->fractionl = ntohl(fixed->fractionl);
59 }
60
61 static __inline void
l_fixedpt_hton(struct l_fixedpt * fixed)62 l_fixedpt_hton(struct l_fixedpt *fixed)
63 {
64 fixed->int_partl = htonl(fixed->int_partl);
65 fixed->fractionl = htonl(fixed->fractionl);
66 }
67
68 static void
ntp_ntoh(struct ntp_msg * msg)69 ntp_ntoh(struct ntp_msg *msg)
70 {
71 msg->refid = ntohl(msg->refid);
72 s_fixedpt_ntoh(&msg->rootdelay);
73 s_fixedpt_ntoh(&msg->dispersion);
74 l_fixedpt_ntoh(&msg->reftime);
75 l_fixedpt_ntoh(&msg->orgtime);
76 l_fixedpt_ntoh(&msg->rectime);
77 l_fixedpt_ntoh(&msg->xmttime);
78 msg->keyid = ntohl(msg->keyid);
79 }
80
81 static void
ntp_hton(struct ntp_msg * msg)82 ntp_hton(struct ntp_msg *msg)
83 {
84 msg->refid = htonl(msg->refid);
85 s_fixedpt_hton(&msg->rootdelay);
86 s_fixedpt_hton(&msg->dispersion);
87 l_fixedpt_hton(&msg->reftime);
88 l_fixedpt_hton(&msg->orgtime);
89 l_fixedpt_hton(&msg->rectime);
90 l_fixedpt_hton(&msg->xmttime);
91 msg->keyid = htonl(msg->keyid);
92 }
93
94 int
udp_ntptimereq(int fd,struct timeval * rtvp,struct timeval * ltvp,struct timeval * lbtvp)95 udp_ntptimereq(int fd, struct timeval *rtvp, struct timeval *ltvp,
96 struct timeval *lbtvp)
97 {
98 struct ntp_msg wmsg;
99 struct ntp_msg rmsg;
100 struct timeval tv1;
101 struct timeval seltv;
102 fd_set rfds;
103 int error;
104 int n;
105
106 /*
107 * Setup the message
108 */
109 bzero(&wmsg, sizeof(wmsg));
110 wmsg.status = LI_ALARM | MODE_CLIENT | (NTP_VERSION << 3);
111 wmsg.ppoll = 4;
112 wmsg.precision = -6;
113 wmsg.rootdelay.int_parts = 1;
114 wmsg.dispersion.int_parts = 1;
115 wmsg.refid = 0;
116 wmsg.xmttime.int_partl = time(NULL) + JAN_1970;
117 wmsg.xmttime.fractionl = random();
118
119 /*
120 * Timed transmit
121 */
122 gettimeofday(&tv1, NULL);
123 ntp_hton(&wmsg);
124 n = write(fd, &wmsg, NTP_MSGSIZE_NOAUTH);
125 if (n != NTP_MSGSIZE_NOAUTH)
126 return(-1);
127 ntp_ntoh(&wmsg);
128
129 /*
130 * Wait for reply
131 */
132 seltv.tv_sec = 2;
133 seltv.tv_usec = 0;
134 FD_ZERO(&rfds);
135 FD_SET(fd, &rfds);
136 select(fd + 1, &rfds, NULL, NULL, &seltv);
137
138 /*
139 * Drain socket, process the first matching reply or error out.
140 * Errors are not necessarily fatal. e.g. a signal could cause select()
141 * to return early.
142 */
143 error = -1;
144 while ((n = read(fd, &rmsg, sizeof(rmsg))) >= 0) {
145 if (n < NTP_MSGSIZE_NOAUTH)
146 continue;
147 ntp_ntoh(&rmsg);
148 if (bcmp(&rmsg.orgtime, &wmsg.xmttime, sizeof(rmsg.orgtime)) != 0)
149 continue;
150
151 /*
152 * Ok, we have a good reply, how long did it take?
153 *
154 * reftime
155 * orgtime
156 * rectime
157 * xmttime
158 */
159 gettimeofday(ltvp, NULL);
160 sysntp_getbasetime(lbtvp);
161
162 l_fixedpt_to_tv(&rmsg.xmttime, rtvp);
163 tv_add_micro(rtvp, (long)(tv_delta_double(&tv1, ltvp) * 1000000.0) / 2);
164
165 error = 0;
166 break;
167 }
168 return(error);
169 }
170
171