Sync with FreeBSD (adds reload).
[dragonfly.git] / usr.sbin / dntpd / ntpreq.c
blob1bcf7337ef7c74353654896efc5de1fdbfa7d8ca
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:
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.
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.
34 * $DragonFly: src/usr.sbin/dntpd/ntpreq.c,v 1.3 2005/04/24 09:39:27 dillon Exp $
37 #include "defs.h"
39 static __inline void
40 s_fixedpt_ntoh(struct s_fixedpt *fixed)
42 fixed->int_parts = ntohs(fixed->int_parts);
43 fixed->fractions = ntohs(fixed->fractions);
46 static __inline void
47 s_fixedpt_hton(struct s_fixedpt *fixed)
49 fixed->int_parts = htons(fixed->int_parts);
50 fixed->fractions = htons(fixed->fractions);
54 static __inline void
55 l_fixedpt_ntoh(struct l_fixedpt *fixed)
57 fixed->int_partl = ntohl(fixed->int_partl);
58 fixed->fractionl = ntohl(fixed->fractionl);
61 static __inline void
62 l_fixedpt_hton(struct l_fixedpt *fixed)
64 fixed->int_partl = htonl(fixed->int_partl);
65 fixed->fractionl = htonl(fixed->fractionl);
68 static void
69 ntp_ntoh(struct ntp_msg *msg)
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);
81 static void
82 ntp_hton(struct ntp_msg *msg)
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);
94 int
95 udp_ntptimereq(int fd, struct timeval *rtvp, struct timeval *ltvp,
96 struct timeval *lbtvp)
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;
107 * Setup the message
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();
120 * Timed transmit
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);
130 * Wait for reply
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);
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.
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;
152 * Ok, we have a good reply, how long did it take?
154 * reftime
155 * orgtime
156 * rectime
157 * xmttime
159 gettimeofday(ltvp, NULL);
160 sysntp_getbasetime(lbtvp);
162 l_fixedpt_to_tv(&rmsg.xmttime, rtvp);
163 tv_add_micro(rtvp, (long)(tv_delta_double(&tv1, ltvp) * 1000000.0) / 2);
165 error = 0;
166 break;
168 return(error);