summaryrefslogtreecommitdiff
path: root/usr.sbin/ntpd/buffer.c
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2004-05-31 13:46:17 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2004-05-31 13:46:17 +0000
commitd7c7c4844a02b9eb783517c118c1b77d75ccf603 (patch)
tree01e41bb1c6145f1d6978b6b48215ef11cba63972 /usr.sbin/ntpd/buffer.c
parent33097da5af566af8bfa55c87ab1aa6cf6c6654cd (diff)
initial cut at ntpd.
it is just capable of answering (s)ntp4 requests with the local time for now. imsg/buffer and logging framework from bgpd, ntp protocol hackery with Alexander Guy
Diffstat (limited to 'usr.sbin/ntpd/buffer.c')
-rw-r--r--usr.sbin/ntpd/buffer.c182
1 files changed, 182 insertions, 0 deletions
diff --git a/usr.sbin/ntpd/buffer.c b/usr.sbin/ntpd/buffer.c
new file mode 100644
index 00000000000..efc1bfffc8c
--- /dev/null
+++ b/usr.sbin/ntpd/buffer.c
@@ -0,0 +1,182 @@
+/* $OpenBSD: buffer.c,v 1.1 2004/05/31 13:46:16 henning Exp $ */
+
+/*
+ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.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/types.h>
+#include <sys/uio.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ntpd.h"
+
+int buf_write(int, struct buf *);
+void buf_enqueue(struct msgbuf *, struct buf *);
+void buf_dequeue(struct msgbuf *, struct buf *);
+
+struct buf *
+buf_open(ssize_t len)
+{
+ struct buf *buf;
+
+ if ((buf = calloc(1, sizeof(struct buf))) == NULL)
+ return (NULL);
+ if ((buf->buf = malloc(len)) == NULL) {
+ free(buf);
+ return (NULL);
+ }
+ buf->size = len;
+
+ return (buf);
+}
+
+int
+buf_add(struct buf *buf, void *data, ssize_t len)
+{
+ if (buf->wpos + len > buf->size)
+ return (-1);
+
+ memcpy(buf->buf + buf->wpos, data, len);
+ buf->wpos += len;
+ return (0);
+}
+
+int
+buf_close(struct msgbuf *msgbuf, struct buf *buf)
+{
+ buf_enqueue(msgbuf, buf);
+ return (1);
+}
+
+int
+buf_write(int sock, struct buf *buf)
+{
+ ssize_t n;
+
+ if ((n = write(sock, buf->buf + buf->rpos,
+ buf->size - buf->rpos)) == -1) {
+ if (errno == EAGAIN) /* cannot write immediately */
+ return (0);
+ else
+ return (-1);
+ }
+
+ if (n == 0) { /* connection closed */
+ errno = 0;
+ return (-2);
+ }
+
+ if (n < buf->size - buf->rpos) { /* not all data written yet */
+ buf->rpos += n;
+ return (0);
+ } else
+ return (1);
+}
+
+void
+buf_free(struct buf *buf)
+{
+ free(buf->buf);
+ free(buf);
+}
+
+void
+msgbuf_init(struct msgbuf *msgbuf)
+{
+ msgbuf->queued = 0;
+ msgbuf->fd = -1;
+ TAILQ_INIT(&msgbuf->bufs);
+}
+
+void
+msgbuf_clear(struct msgbuf *msgbuf)
+{
+ struct buf *buf;
+
+ while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
+ buf_dequeue(msgbuf, buf);
+}
+
+int
+msgbuf_write(struct msgbuf *msgbuf)
+{
+ /*
+ * possible race here
+ * when we cannot write out data completely from a buffer,
+ * we MUST return and NOT try to write out stuff from later buffers -
+ * the socket might have become writeable again
+ */
+ struct iovec iov[IOV_MAX];
+ struct buf *buf, *next;
+ int i = 0;
+ ssize_t n;
+
+ bzero(&iov, sizeof(iov));
+ TAILQ_FOREACH(buf, &msgbuf->bufs, entries) {
+ if (i >= IOV_MAX)
+ break;
+ iov[i].iov_base = buf->buf + buf->rpos;
+ iov[i].iov_len = buf->size - buf->rpos;
+ i++;
+ }
+
+ if ((n = writev(msgbuf->fd, iov, i)) == -1) {
+ if (errno == EAGAIN) /* cannot write immediately */
+ return (0);
+ else
+ return (-1);
+ }
+
+ if (n == 0) { /* connection closed */
+ errno = 0;
+ return (-2);
+ }
+
+ for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
+ buf = next) {
+ next = TAILQ_NEXT(buf, entries);
+ if (n >= buf->size - buf->rpos) {
+ n -= buf->size - buf->rpos;
+ buf_dequeue(msgbuf, buf);
+ } else {
+ buf->rpos += n;
+ n = 0;
+ }
+ }
+
+ return (0);
+}
+
+void
+buf_enqueue(struct msgbuf *msgbuf, struct buf *buf)
+{
+ TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entries);
+ msgbuf->queued++;
+}
+
+void
+buf_dequeue(struct msgbuf *msgbuf, struct buf *buf)
+{
+ TAILQ_REMOVE(&msgbuf->bufs, buf, entries);
+ msgbuf->queued--;
+ buf_free(buf);
+}