Import OpenNTPD 3.6 (the OpenBSD version, not the portable).
[dragonfly.git] / contrib / ntpd / imsg.c
1 /*      $OpenBSD: imsg.c,v 1.1 2004/05/31 13:46:16 henning Exp $ */
2
3 /*
4  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18
19 #include <sys/types.h>
20
21 #include <errno.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25
26 #include "ntpd.h"
27
28 int              imsg_compose_core(struct imsgbuf *, int, u_int32_t, void *,
29                      u_int16_t, pid_t);
30 struct buf      *imsg_create_core(struct imsgbuf *, int, u_int32_t, u_int16_t,
31                      pid_t);
32
33 void
34 imsg_init(struct imsgbuf *ibuf, int fd)
35 {
36         msgbuf_init(&ibuf->w);
37         bzero(&ibuf->r, sizeof(ibuf->r));
38         ibuf->fd = fd;
39         ibuf->w.fd = fd;
40         ibuf->pid = getpid();
41 }
42
43 int
44 imsg_read(struct imsgbuf *ibuf)
45 {
46         ssize_t                  n;
47
48         if ((n = read(ibuf->fd, ibuf->r.buf + ibuf->r.wpos,
49             sizeof(ibuf->r.buf) - ibuf->r.wpos)) == -1) {
50                 if (errno != EINTR && errno != EAGAIN) {
51                         log_warn("imsg_read: pipe read error");
52                         return (-1);
53                 }
54                 return (0);
55         }
56
57         ibuf->r.wpos += n;
58
59         return (n);
60 }
61
62 int
63 imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
64 {
65         ssize_t                  datalen = 0;
66         size_t                   av, left;
67
68         av = ibuf->r.wpos;
69
70         if (IMSG_HEADER_SIZE > av)
71                 return (0);
72
73         memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr));
74         if (imsg->hdr.len < IMSG_HEADER_SIZE ||
75             imsg->hdr.len > MAX_IMSGSIZE) {
76                 log_warnx("imsg_get: imsg hdr len out of bounds");
77                 return (-1);
78         }
79         if (imsg->hdr.len > av)
80                 return (0);
81         datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
82         ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE;
83         if ((imsg->data = malloc(datalen)) == NULL) {
84                 log_warn("imsg_get");
85                 return (-1);
86         }
87         memcpy(imsg->data, ibuf->r.rptr, datalen);
88
89         if (imsg->hdr.len < av) {
90                 left = av - imsg->hdr.len;
91                 memcpy(&ibuf->r.buf, ibuf->r.buf + imsg->hdr.len, left);
92                 ibuf->r.wpos = left;
93         } else
94                 ibuf->r.wpos = 0;
95
96         return (datalen + IMSG_HEADER_SIZE);
97 }
98
99 int
100 imsg_compose(struct imsgbuf *ibuf, int type, u_int32_t peerid, void *data,
101     u_int16_t dlen)
102 {
103         return (imsg_compose_core(ibuf, type, peerid, data, dlen, ibuf->pid));
104 }
105
106 int
107 imsg_compose_pid(struct imsgbuf *ibuf, int type, pid_t pid, void *data,
108     u_int16_t datalen)
109 {
110         return (imsg_compose_core(ibuf, type, 0, data, datalen, pid));
111 }
112
113 int
114 imsg_compose_core(struct imsgbuf *ibuf, int type, u_int32_t peerid, void *data,
115     u_int16_t datalen, pid_t pid)
116 {
117         struct buf      *wbuf;
118         struct imsg_hdr  hdr;
119         int              n;
120
121         hdr.len = datalen + IMSG_HEADER_SIZE;
122         hdr.type = type;
123         hdr.peerid = peerid;
124         hdr.pid = pid;
125         wbuf = buf_open(hdr.len);
126         if (wbuf == NULL) {
127                 log_warn("imsg_compose: buf_open");
128                 return (-1);
129         }
130         if (buf_add(wbuf, &hdr, sizeof(hdr)) == -1) {
131                 log_warnx("imsg_compose: buf_add error");
132                 buf_free(wbuf);
133                 return (-1);
134         }
135         if (datalen)
136                 if (buf_add(wbuf, data, datalen) == -1) {
137                         log_warnx("imsg_compose: buf_add error");
138                         buf_free(wbuf);
139                         return (-1);
140                 }
141
142         if ((n = buf_close(&ibuf->w, wbuf)) < 0) {
143                         log_warnx("imsg_compose: buf_add error");
144                         buf_free(wbuf);
145                         return (-1);
146         }
147         return (n);
148 }
149
150 struct buf *
151 imsg_create(struct imsgbuf *ibuf, int type, u_int32_t peerid, u_int16_t dlen)
152 {
153         return (imsg_create_core(ibuf, type, peerid, dlen, ibuf->pid));
154 }
155
156 struct buf *
157 imsg_create_pid(struct imsgbuf *ibuf, int type, pid_t pid, u_int16_t datalen)
158 {
159         return (imsg_create_core(ibuf, type, 0, datalen, pid));
160 }
161
162 struct buf *
163 imsg_create_core(struct imsgbuf *ibuf, int type, u_int32_t peerid,
164     u_int16_t datalen, pid_t pid)
165 {
166         struct buf      *wbuf;
167         struct imsg_hdr  hdr;
168
169         hdr.len = datalen + IMSG_HEADER_SIZE;
170         hdr.type = type;
171         hdr.peerid = peerid;
172         hdr.pid = pid;
173         wbuf = buf_open(hdr.len);
174         if (wbuf == NULL) {
175                 log_warn("imsg_create: buf_open");
176                 return (NULL);
177         }
178         if (buf_add(wbuf, &hdr, sizeof(hdr)) == -1) {
179                 log_warnx("imsg_create: buf_add error");
180                 buf_free(wbuf);
181                 return (NULL);
182         }
183         return (wbuf);
184 }
185
186 int
187 imsg_add(struct buf *msg, void *data, u_int16_t datalen)
188 {
189         if (datalen)
190                 if (buf_add(msg, data, datalen) == -1) {
191                         log_warnx("imsg_add: buf_add error");
192                         buf_free(msg);
193                         return (-1);
194                 }
195         return (datalen);
196 }
197
198 int
199 imsg_close(struct imsgbuf *ibuf, struct buf *msg)
200 {
201         int     n;
202
203         if ((n = buf_close(&ibuf->w, msg)) < 0) {
204                         log_warnx("imsg_close: buf_add error");
205                         buf_free(msg);
206                         return (-1);
207         }
208         return (n);
209 }
210
211 void
212 imsg_free(struct imsg *imsg)
213 {
214         free(imsg->data);
215 }