GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/smtpd/smtpctl/../table_proc.c Lines: 0 121 0.0 %
Date: 2017-11-07 Branches: 0 60 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: table_proc.c,v 1.6 2015/12/05 13:14:21 claudio Exp $	*/
2
3
/*
4
 * Copyright (c) 2013 Eric Faurot <eric@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 USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/queue.h>
21
#include <sys/tree.h>
22
#include <sys/socket.h>
23
24
#include <ctype.h>
25
#include <errno.h>
26
#include <event.h>
27
#include <fcntl.h>
28
#include <imsg.h>
29
#include <paths.h>
30
#include <stdio.h>
31
#include <stdlib.h>
32
#include <string.h>
33
#include <limits.h>
34
#include <unistd.h>
35
36
#include "smtpd.h"
37
#include "log.h"
38
39
struct table_proc_priv {
40
	pid_t		pid;
41
	struct imsgbuf	ibuf;
42
};
43
44
static struct imsg	 imsg;
45
static size_t		 rlen;
46
static char		*rdata;
47
48
extern char	**environ;
49
50
static void
51
table_proc_call(struct table_proc_priv *p)
52
{
53
	ssize_t	n;
54
55
	if (imsg_flush(&p->ibuf) == -1) {
56
		log_warn("warn: table-proc: imsg_flush");
57
		fatalx("table-proc: exiting");
58
	}
59
60
	while (1) {
61
		if ((n = imsg_get(&p->ibuf, &imsg)) == -1) {
62
			log_warn("warn: table-proc: imsg_get");
63
			break;
64
		}
65
		if (n) {
66
			rlen = imsg.hdr.len - IMSG_HEADER_SIZE;
67
			rdata = imsg.data;
68
69
			if (imsg.hdr.type != PROC_TABLE_OK) {
70
				log_warnx("warn: table-proc: bad response");
71
				break;
72
			}
73
			return;
74
		}
75
76
		if ((n = imsg_read(&p->ibuf)) == -1 && errno != EAGAIN) {
77
			log_warn("warn: table-proc: imsg_read");
78
			break;
79
		}
80
81
		if (n == 0) {
82
			log_warnx("warn: table-proc: pipe closed");
83
			break;
84
		}
85
	}
86
87
	fatalx("table-proc: exiting");
88
}
89
90
static void
91
table_proc_read(void *dst, size_t len)
92
{
93
	if (len > rlen) {
94
		log_warnx("warn: table-proc: bad msg len");
95
		fatalx("table-proc: exiting");
96
	}
97
98
	if (dst)
99
		memmove(dst, rdata, len);
100
101
	rlen -= len;
102
	rdata += len;
103
}
104
105
static void
106
table_proc_end(void)
107
{
108
	if (rlen) {
109
		log_warnx("warn: table-proc: bogus data");
110
		fatalx("table-proc: exiting");
111
	}
112
	imsg_free(&imsg);
113
}
114
115
/*
116
 * API
117
 */
118
119
static void *
120
table_proc_open(struct table *table)
121
{
122
	struct table_proc_priv	*priv;
123
	struct table_open_params op;
124
	int			 fd;
125
126
	priv = xcalloc(1, sizeof(*priv), "table_proc_open");
127
128
	fd = fork_proc_backend("table", table->t_config, table->t_name);
129
	if (fd == -1)
130
		fatalx("table-proc: exiting");
131
132
	imsg_init(&priv->ibuf, fd);
133
134
	memset(&op, 0, sizeof op);
135
	op.version = PROC_TABLE_API_VERSION;
136
	(void)strlcpy(op.name, table->t_name, sizeof op.name);
137
	imsg_compose(&priv->ibuf, PROC_TABLE_OPEN, 0, 0, -1, &op, sizeof op);
138
139
	table_proc_call(priv);
140
	table_proc_end();
141
142
	return (priv);
143
}
144
145
static int
146
table_proc_update(struct table *table)
147
{
148
	struct table_proc_priv	*priv = table->t_handle;
149
	int r;
150
151
	imsg_compose(&priv->ibuf, PROC_TABLE_UPDATE, 0, 0, -1, NULL, 0);
152
153
	table_proc_call(priv);
154
	table_proc_read(&r, sizeof(r));
155
	table_proc_end();
156
157
	return (r);
158
}
159
160
static void
161
table_proc_close(void *arg)
162
{
163
	struct table_proc_priv	*priv = arg;
164
165
	imsg_compose(&priv->ibuf, PROC_TABLE_CLOSE, 0, 0, -1, NULL, 0);
166
	imsg_flush(&priv->ibuf);
167
}
168
169
static int
170
imsg_add_params(struct ibuf *buf, struct dict *params)
171
{
172
	size_t count;
173
	const char *key;
174
	char *value;
175
	void *iter;
176
177
	count = 0;
178
	if (params)
179
		count = dict_count(params);
180
181
	if (imsg_add(buf, &count, sizeof(count)) == -1)
182
		return (-1);
183
184
	if (count == 0)
185
		return (0);
186
187
	iter = NULL;
188
	while (dict_iter(params, &iter, &key, (void **)&value)) {
189
		if (imsg_add(buf, key, strlen(key) + 1) == -1)
190
			return (-1);
191
		if (imsg_add(buf, value, strlen(value) + 1) == -1)
192
			return (-1);
193
	}
194
195
	return (0);
196
}
197
198
static int
199
table_proc_lookup(void *arg, struct dict *params, const char *k, enum table_service s,
200
    union lookup *lk)
201
{
202
	struct table_proc_priv	*priv = arg;
203
	struct ibuf		*buf;
204
	int			 r;
205
206
	buf = imsg_create(&priv->ibuf,
207
	    lk ? PROC_TABLE_LOOKUP : PROC_TABLE_CHECK, 0, 0,
208
	    sizeof(s) + strlen(k) + 1);
209
210
	if (buf == NULL)
211
		return (-1);
212
	if (imsg_add(buf, &s, sizeof(s)) == -1)
213
		return (-1);
214
	if (imsg_add_params(buf, params) == -1)
215
		return (-1);
216
	if (imsg_add(buf, k, strlen(k) + 1) == -1)
217
		return (-1);
218
	imsg_close(&priv->ibuf, buf);
219
220
	table_proc_call(priv);
221
	table_proc_read(&r, sizeof(r));
222
223
	if (r == 1 && lk) {
224
		if (rlen == 0) {
225
			log_warnx("warn: table-proc: empty response");
226
			fatalx("table-proc: exiting");
227
		}
228
		if (rdata[rlen - 1] != '\0') {
229
			log_warnx("warn: table-proc: not NUL-terminated");
230
			fatalx("table-proc: exiting");
231
		}
232
		r = table_parse_lookup(s, k, rdata, lk);
233
		table_proc_read(NULL, rlen);
234
	}
235
236
	table_proc_end();
237
238
	return (r);
239
}
240
241
static int
242
table_proc_fetch(void *arg, struct dict *params, enum table_service s, union lookup *lk)
243
{
244
	struct table_proc_priv	*priv = arg;
245
	struct ibuf		*buf;
246
	int			 r;
247
248
	buf = imsg_create(&priv->ibuf, PROC_TABLE_FETCH, 0, 0, sizeof(s));
249
	if (buf == NULL)
250
		return (-1);
251
	if (imsg_add(buf, &s, sizeof(s)) == -1)
252
		return (-1);
253
	if (imsg_add_params(buf, params) == -1)
254
		return (-1);
255
	imsg_close(&priv->ibuf, buf);
256
257
	table_proc_call(priv);
258
	table_proc_read(&r, sizeof(r));
259
260
	if (r == 1) {
261
		if (rlen == 0) {
262
			log_warnx("warn: table-proc: empty response");
263
			fatalx("table-proc: exiting");
264
		}
265
		if (rdata[rlen - 1] != '\0') {
266
			log_warnx("warn: table-proc: not NUL-terminated");
267
			fatalx("table-proc: exiting");
268
		}
269
		r = table_parse_lookup(s, NULL, rdata, lk);
270
		table_proc_read(NULL, rlen);
271
	}
272
273
	table_proc_end();
274
275
	return (r);
276
}
277
278
struct table_backend table_backend_proc = {
279
	K_ANY,
280
	NULL,
281
	table_proc_open,
282
	table_proc_update,
283
	table_proc_close,
284
	table_proc_lookup,
285
	table_proc_fetch,
286
};