summaryrefslogtreecommitdiff
path: root/usr.sbin/ntpd/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/ntpd/client.c')
-rw-r--r--usr.sbin/ntpd/client.c129
1 files changed, 129 insertions, 0 deletions
diff --git a/usr.sbin/ntpd/client.c b/usr.sbin/ntpd/client.c
new file mode 100644
index 00000000000..c742d1d11fb
--- /dev/null
+++ b/usr.sbin/ntpd/client.c
@@ -0,0 +1,129 @@
+/* $OpenBSD: client.c,v 1.1 2004/06/17 19:17:48 henning Exp $ */
+
+/*
+ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
+ * Copyright (c) 2004 Alexander Guy <alexander.guy@andern.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "ntpd.h"
+
+int
+client_peer_init(struct ntp_peer *p)
+{
+ struct sockaddr_in *sa_in;
+ struct sockaddr_in6 *sa_in6;
+
+ if ((p->query = calloc(1, sizeof(struct ntp_msg))) == NULL)
+ fatal("client_query calloc");
+
+ switch (p->ss.ss_family) {
+ case AF_INET:
+ sa_in = (struct sockaddr_in *)&p->ss;
+ if (ntohs(sa_in->sin_port) == 0)
+ sa_in->sin_port = htons(123);
+ break;
+ case AF_INET6:
+ sa_in6 = (struct sockaddr_in6 *)&p->ss;
+ if (ntohs(sa_in6->sin6_port) == 0)
+ sa_in6->sin6_port = htons(123);
+ break;
+ default:
+ fatal("king bula sez: wrong AF in client_peer_init");
+ /* not reached */
+ }
+
+ if ((p->query->fd = socket(p->ss.ss_family, SOCK_DGRAM, 0)) == -1)
+ fatal("client_query socket");
+
+ p->query->msg.status = MODE_CLIENT | (NTP_VERSION << 3);
+ p->state = STATE_NONE;
+ p->next = time(NULL);
+
+ return (0);
+}
+
+int
+client_query(struct ntp_peer *p)
+{
+ /*
+ * Send out a random 64-bit number as our transmit time. The NTP
+ * server will copy said number into the originate field on the
+ * response that it sends us. This is totally legal per the SNTP spec.
+ *
+ * The impact of this is two fold: we no longer send out the current
+ * system time for the world to see (which may aid an attacker), and
+ * it gives us a (not very secure) way of knowing that we're not
+ * getting spoofed by an attacker that can't capture our traffic
+ * but can spoof packets from the NTP server we're communicating with.
+ *
+ * Save the real transmit timestamp locally.
+ */
+
+ p->query->msg.xmttime.int_part = arc4random();
+ p->query->msg.xmttime.fraction = arc4random();
+ get_ts(&p->query->xmttime);
+
+ ntp_sendmsg(p->query->fd, (struct sockaddr *)&p->ss, &p->query->msg,
+ NTP_MSGSIZE_NOAUTH, 0);
+ p->state = STATE_QUERY_SENT;
+ p->next = 0;
+ p->deadline = time(NULL) + MAX_QUERYTIME;
+
+ return (0);
+}
+
+int
+client_dispatch(struct ntp_peer *p)
+{
+ struct sockaddr_storage fsa;
+ socklen_t fsa_len;
+ char buf[NTP_MSGSIZE];
+ ssize_t size;
+ struct ntp_msg msg;
+ struct l_fixedpt rtt, t;
+
+ fsa_len = sizeof(fsa);
+ if ((size = recvfrom(p->query->fd, &buf, sizeof(buf), 0,
+ (struct sockaddr *)&fsa, &fsa_len)) == -1)
+ fatal("recvfrom");
+
+ ntp_getmsg(buf, size, &msg);
+
+ if (msg.orgtime.int_part != p->query->msg.xmttime.int_part ||
+ msg.orgtime.fraction != p->query->msg.xmttime.fraction) {
+ log_warn("received packet without correct cookie, discarding");
+ return (0);
+ }
+
+log_debug("reply received");
+
+ /* XXX parse */
+ get_ts(&t);
+ rtt.int_part = (t.int_part - p->query->xmttime.int_part) -
+ (msg.rectime.int_part - msg.xmttime.int_part);
+
+ p->state = STATE_REPLY_RECEIVED;
+ p->next = time(NULL) + QUERY_INTERVAL;
+ p->deadline = 0;
+
+ return (0);
+}