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 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 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 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 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 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 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 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