GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/smtpd/smtpd/../queue_ram.c Lines: 0 153 0.0 %
Date: 2017-11-13 Branches: 0 64 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: queue_ram.c,v 1.7 2015/01/20 17:37:54 deraadt Exp $	*/
2
3
/*
4
 * Copyright (c) 2012 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
#include <sys/stat.h>
24
25
#include <ctype.h>
26
#include <err.h>
27
#include <errno.h>
28
#include <event.h>
29
#include <fcntl.h>
30
#include <imsg.h>
31
#include <inttypes.h>
32
#include <libgen.h>
33
#include <pwd.h>
34
#include <stdio.h>
35
#include <stdlib.h>
36
#include <string.h>
37
#include <time.h>
38
#include <unistd.h>
39
#include <limits.h>
40
41
#include "smtpd.h"
42
#include "log.h"
43
44
struct qr_envelope {
45
	char		*buf;
46
	size_t		 len;
47
};
48
49
struct qr_message {
50
	char		*buf;
51
	size_t		 len;
52
	struct tree	 envelopes;
53
};
54
55
static struct tree messages;
56
57
static struct qr_message *
58
get_message(uint32_t msgid)
59
{
60
	struct qr_message	*msg;
61
62
        msg = tree_get(&messages, msgid);
63
        if (msg == NULL)
64
                log_warn("warn: queue-ram: message not found");
65
66
	return (msg);
67
}
68
69
static int
70
queue_ram_message_create(uint32_t *msgid)
71
{
72
	struct qr_message	*msg;
73
74
	msg = calloc(1, sizeof(*msg));
75
	if (msg == NULL) {
76
		log_warn("warn: queue-ram: calloc");
77
		return (0);
78
	}
79
	tree_init(&msg->envelopes);
80
81
	do {
82
		*msgid = queue_generate_msgid();
83
	} while (tree_check(&messages, *msgid));
84
85
	tree_xset(&messages, *msgid, msg);
86
87
	return (1);
88
}
89
90
static int
91
queue_ram_message_commit(uint32_t msgid, const char *path)
92
{
93
	struct qr_message	*msg;
94
	struct stat		 sb;
95
	size_t			 n;
96
	FILE			*f;
97
	int			 ret;
98
99
	if ((msg = tree_get(&messages, msgid)) == NULL) {
100
		log_warnx("warn: queue-ram: msgid not found");
101
		return (0);
102
	}
103
104
	f = fopen(path, "rb");
105
	if (f == NULL) {
106
		log_warn("warn: queue-ram: fopen: %s", path);
107
		return (0);
108
	}
109
	if (fstat(fileno(f), &sb) == -1) {
110
		log_warn("warn: queue-ram: fstat");
111
		fclose(f);
112
		return (0);
113
	}
114
115
	msg->len = sb.st_size;
116
	msg->buf = malloc(msg->len);
117
	if (msg->buf == NULL) {
118
		log_warn("warn: queue-ram: malloc");
119
		fclose(f);
120
		return (0);
121
	}
122
123
	ret = 0;
124
	n = fread(msg->buf, 1, msg->len, f);
125
	if (ferror(f))
126
		log_warn("warn: queue-ram: fread");
127
	else if ((off_t)n != sb.st_size)
128
		log_warnx("warn: queue-ram: bad read");
129
	else {
130
		ret = 1;
131
		stat_increment("queue.ram.message.size", msg->len);
132
	}
133
	fclose(f);
134
135
	return (ret);
136
}
137
138
static int
139
queue_ram_message_delete(uint32_t msgid)
140
{
141
	struct qr_message	*msg;
142
	struct qr_envelope	*evp;
143
	uint64_t		 evpid;
144
145
	if ((msg = tree_pop(&messages, msgid)) == NULL) {
146
		log_warnx("warn: queue-ram: not found");
147
		return (0);
148
	}
149
	while (tree_poproot(&messages, &evpid, (void**)&evp)) {
150
		stat_decrement("queue.ram.envelope.size", evp->len);
151
		free(evp->buf);
152
		free(evp);
153
	}
154
	stat_decrement("queue.ram.message.size", msg->len);
155
	free(msg->buf);
156
	free(msg);
157
	return (0);
158
}
159
160
static int
161
queue_ram_message_fd_r(uint32_t msgid)
162
{
163
	struct qr_message	*msg;
164
	size_t			 n;
165
	FILE			*f;
166
	int			 fd, fd2;
167
168
	if ((msg = tree_get(&messages, msgid)) == NULL) {
169
		log_warnx("warn: queue-ram: not found");
170
		return (-1);
171
	}
172
173
	fd = mktmpfile();
174
	if (fd == -1) {
175
		log_warn("warn: queue-ram: mktmpfile");
176
		return (-1);
177
	}
178
179
	fd2 = dup(fd);
180
	if (fd2 == -1) {
181
		log_warn("warn: queue-ram: dup");
182
		close(fd);
183
		return (-1);
184
	}
185
	f = fdopen(fd2, "w");
186
	if (f == NULL) {
187
		log_warn("warn: queue-ram: fdopen");
188
		close(fd);
189
		close(fd2);
190
		return (-1);
191
	}
192
	n = fwrite(msg->buf, 1, msg->len, f);
193
	if (n != msg->len) {
194
		log_warn("warn: queue-ram: write");
195
		close(fd);
196
		fclose(f);
197
		return (-1);
198
	}
199
	fclose(f);
200
	lseek(fd, 0, SEEK_SET);
201
	return (fd);
202
}
203
204
static int
205
queue_ram_message_corrupt(uint32_t msgid)
206
{
207
	return (queue_ram_message_delete(msgid));
208
}
209
210
static int
211
queue_ram_envelope_create(uint32_t msgid, const char *buf, size_t len,
212
    uint64_t *evpid)
213
{
214
	struct qr_envelope	*evp;
215
	struct qr_message	*msg;
216
217
	if ((msg = get_message(msgid)) == NULL)
218
		return (0);
219
220
	do {
221
		*evpid = queue_generate_evpid(msgid);
222
	} while (tree_check(&msg->envelopes, *evpid));
223
	evp = calloc(1, sizeof *evp);
224
	if (evp == NULL) {
225
		log_warn("warn: queue-ram: calloc");
226
		return (0);
227
	}
228
	evp->len = len;
229
	evp->buf = malloc(len);
230
	if (evp->buf == NULL) {
231
		log_warn("warn: queue-ram: malloc");
232
		free(evp);
233
		return (0);
234
	}
235
	memmove(evp->buf, buf, len);
236
	tree_xset(&msg->envelopes, *evpid, evp);
237
	stat_increment("queue.ram.envelope.size", len);
238
	return (1);
239
}
240
241
static int
242
queue_ram_envelope_delete(uint64_t evpid)
243
{
244
	struct qr_envelope	*evp;
245
	struct qr_message	*msg;
246
247
	if ((msg = get_message(evpid_to_msgid(evpid))) == NULL)
248
		return (0);
249
250
	if ((evp = tree_pop(&msg->envelopes, evpid)) == NULL) {
251
		log_warnx("warn: queue-ram: not found");
252
		return (0);
253
	}
254
	stat_decrement("queue.ram.envelope.size", evp->len);
255
	free(evp->buf);
256
	free(evp);
257
	if (tree_empty(&msg->envelopes)) {
258
		tree_xpop(&messages, evpid_to_msgid(evpid));
259
		stat_decrement("queue.ram.message.size", msg->len);
260
		free(msg->buf);
261
		free(msg);
262
	}
263
	return (1);
264
}
265
266
static int
267
queue_ram_envelope_update(uint64_t evpid, const char *buf, size_t len)
268
{
269
	struct qr_envelope	*evp;
270
	struct qr_message	*msg;
271
	void			*tmp;
272
273
	if ((msg = get_message(evpid_to_msgid(evpid))) == NULL)
274
		return (0);
275
276
	if ((evp = tree_get(&msg->envelopes, evpid)) == NULL) {
277
		log_warn("warn: queue-ram: not found");
278
		return (0);
279
	}
280
	tmp = malloc(len);
281
	if (tmp == NULL) {
282
		log_warn("warn: queue-ram: malloc");
283
		return (0);
284
	}
285
	memmove(tmp, buf, len);
286
	free(evp->buf);
287
	evp->len = len;
288
	evp->buf = tmp;
289
	stat_decrement("queue.ram.envelope.size", evp->len);
290
	stat_increment("queue.ram.envelope.size", len);
291
	return (1);
292
}
293
294
static int
295
queue_ram_envelope_load(uint64_t evpid, char *buf, size_t len)
296
{
297
	struct qr_envelope	*evp;
298
	struct qr_message	*msg;
299
300
	if ((msg = get_message(evpid_to_msgid(evpid))) == NULL)
301
		return (0);
302
303
	if ((evp = tree_get(&msg->envelopes, evpid)) == NULL) {
304
		log_warn("warn: queue-ram: not found");
305
		return (0);
306
	}
307
	if (len < evp->len) {
308
		log_warnx("warn: queue-ram: buffer too small");
309
		return (0);
310
	}
311
	memmove(buf, evp->buf, evp->len);
312
	return (evp->len);
313
}
314
315
static int
316
queue_ram_envelope_walk(uint64_t *evpid, char *buf, size_t len)
317
{
318
	return (-1);
319
}
320
321
static int
322
queue_ram_init(struct passwd *pw, int server, const char * conf)
323
{
324
	tree_init(&messages);
325
326
	queue_api_on_message_create(queue_ram_message_create);
327
	queue_api_on_message_commit(queue_ram_message_commit);
328
	queue_api_on_message_delete(queue_ram_message_delete);
329
	queue_api_on_message_fd_r(queue_ram_message_fd_r);
330
	queue_api_on_message_corrupt(queue_ram_message_corrupt);
331
	queue_api_on_envelope_create(queue_ram_envelope_create);
332
	queue_api_on_envelope_delete(queue_ram_envelope_delete);
333
	queue_api_on_envelope_update(queue_ram_envelope_update);
334
	queue_api_on_envelope_load(queue_ram_envelope_load);
335
	queue_api_on_envelope_walk(queue_ram_envelope_walk);
336
337
	return (1);
338
}
339
340
struct queue_backend	queue_backend_ram = {
341
	queue_ram_init,
342
};