xref: /openbsd-src/usr.sbin/smtpd/smtpctl.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: smtpctl.c,v 1.67 2011/09/01 19:56:49 eric Exp $	*/
2 
3 /*
4  * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
5  * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
6  * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
7  * Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  */
21 
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <sys/queue.h>
25 #include <sys/tree.h>
26 #include <sys/un.h>
27 #include <sys/param.h>
28 
29 #include <err.h>
30 #include <errno.h>
31 #include <event.h>
32 #include <imsg.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <time.h>
37 #include <unistd.h>
38 
39 #include "smtpd.h"
40 #include "parser.h"
41 
42 void usage(void);
43 static void show_sizes(void);
44 static int show_command_output(struct imsg *);
45 static int show_stats_output(struct imsg *);
46 
47 int proctype;
48 struct imsgbuf	*ibuf;
49 
50 int sendmail = 0;
51 extern char *__progname;
52 
53 struct smtpd	*env = NULL;
54 
55 __dead void
56 usage(void)
57 {
58 	extern char *__progname;
59 
60 	if (sendmail)
61 		fprintf(stderr, "usage: %s [-tv] [-f from] [-F name] to ..\n",
62 		    __progname);
63 	else
64 		fprintf(stderr, "usage: %s command [argument ...]\n", __progname);
65 	exit(1);
66 }
67 
68 int
69 main(int argc, char *argv[])
70 {
71 	struct sockaddr_un	sun;
72 	struct parse_result	*res = NULL;
73 	struct imsg		imsg;
74 	int			ctl_sock;
75 	int			done = 0;
76 	int			n, verbose = 0;
77 
78 	/* parse options */
79 	if (strcmp(__progname, "sendmail") == 0 || strcmp(__progname, "send-mail") == 0)
80 		sendmail = 1;
81 	else if (strcmp(__progname, "mailq") == 0) {
82 		if (geteuid())
83 			errx(1, "need root privileges");
84 		show_queue(PATH_QUEUE, 0);
85 		return 0;
86 	} else if (strcmp(__progname, "smtpctl") == 0) {
87 		/* check for root privileges */
88 		if (geteuid())
89 			errx(1, "need root privileges");
90 
91 		if ((res = parse(argc - 1, argv + 1)) == NULL)
92 			exit(1);
93 
94 		/* handle "disconnected" commands */
95 		switch (res->action) {
96 		case SHOW_QUEUE:
97 			show_queue(PATH_QUEUE, 0);
98 			break;
99 		case SHOW_RUNQUEUE:
100 			break;
101 		case SHOW_SIZES:
102 			show_sizes();
103 			break;
104 		default:
105 			goto connected;
106 		}
107 		return 0;
108 	} else
109 		errx(1, "unsupported mode");
110 
111 connected:
112 	/* connect to smtpd control socket */
113 	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
114 		err(1, "socket");
115 
116 	bzero(&sun, sizeof(sun));
117 	sun.sun_family = AF_UNIX;
118 	strlcpy(sun.sun_path, SMTPD_SOCKET, sizeof(sun.sun_path));
119 	if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
120 		if (sendmail)
121 			return enqueue_offline(argc, argv);
122 		err(1, "connect: %s", SMTPD_SOCKET);
123 	}
124 
125 	if ((ibuf = calloc(1, sizeof(struct imsgbuf))) == NULL)
126 		err(1, NULL);
127 	imsg_init(ibuf, ctl_sock);
128 
129 	if (sendmail)
130 		return enqueue(argc, argv);
131 
132 	/* process user request */
133 	switch (res->action) {
134 	case NONE:
135 		usage();
136 		/* not reached */
137 
138 	case SCHEDULE:
139 	case REMOVE: {
140 		u_int64_t ulval;
141 		char *ep;
142 
143 		errno = 0;
144 		ulval = strtoul(res->data, &ep, 16);
145 		if (res->data[0] == '\0' || *ep != '\0')
146 			errx(1, "invalid msgid/evpid");
147 		if (errno == ERANGE && ulval == ULLONG_MAX)
148 			errx(1, "invalid msgid/evpid");
149 
150 		if (res->action == SCHEDULE)
151 			imsg_compose(ibuf, IMSG_RUNNER_SCHEDULE, 0, 0, -1, &ulval,
152 			    sizeof(ulval));
153 		if (res->action == REMOVE)
154 			imsg_compose(ibuf, IMSG_RUNNER_REMOVE, 0, 0, -1, &ulval,
155 			    sizeof(ulval));
156 		break;
157 	}
158 
159 	case SHUTDOWN:
160 		imsg_compose(ibuf, IMSG_CTL_SHUTDOWN, 0, 0, -1, NULL, 0);
161 		break;
162 	case PAUSE_MDA:
163 		imsg_compose(ibuf, IMSG_QUEUE_PAUSE_LOCAL, 0, 0, -1, NULL, 0);
164 		break;
165 	case PAUSE_MTA:
166 		imsg_compose(ibuf, IMSG_QUEUE_PAUSE_OUTGOING, 0, 0, -1, NULL, 0);
167 		break;
168 	case PAUSE_SMTP:
169 		imsg_compose(ibuf, IMSG_SMTP_PAUSE, 0, 0, -1, NULL, 0);
170 		break;
171 	case RESUME_MDA:
172 		imsg_compose(ibuf, IMSG_QUEUE_RESUME_LOCAL, 0, 0, -1, NULL, 0);
173 		break;
174 	case RESUME_MTA:
175 		imsg_compose(ibuf, IMSG_QUEUE_RESUME_OUTGOING, 0, 0, -1, NULL, 0);
176 		break;
177 	case RESUME_SMTP:
178 		imsg_compose(ibuf, IMSG_SMTP_RESUME, 0, 0, -1, NULL, 0);
179 		break;
180 	case SHOW_STATS:
181 		imsg_compose(ibuf, IMSG_STATS, 0, 0, -1, NULL, 0);
182 		break;
183 	case MONITOR:
184 		/* XXX */
185 		break;
186 	case LOG_VERBOSE:
187 		verbose = 1;
188 		/* FALLTHROUGH */
189 	case LOG_BRIEF:
190 		imsg_compose(ibuf, IMSG_CTL_VERBOSE, 0, 0, -1, &verbose,
191 		    sizeof(verbose));
192 		printf("logging request sent.\n");
193 		done = 1;
194 		break;
195 	default:
196 		err(1, "unknown request (%d)", res->action);
197 	}
198 
199 	while (ibuf->w.queued)
200 		if (msgbuf_write(&ibuf->w) < 0)
201 			err(1, "write error");
202 
203 	while (!done) {
204 		if ((n = imsg_read(ibuf)) == -1)
205 			errx(1, "imsg_read error");
206 		if (n == 0)
207 			errx(1, "pipe closed");
208 
209 		while (!done) {
210 			if ((n = imsg_get(ibuf, &imsg)) == -1)
211 				errx(1, "imsg_get error");
212 			if (n == 0)
213 				break;
214 			switch(res->action) {
215 			/* case RELOAD: */
216 			case REMOVE:
217 			case SCHEDULE:
218 			case SHUTDOWN:
219 			case PAUSE_MDA:
220 			case PAUSE_MTA:
221 			case PAUSE_SMTP:
222 			case RESUME_MDA:
223 			case RESUME_MTA:
224 			case RESUME_SMTP:
225 			case LOG_VERBOSE:
226 			case LOG_BRIEF:
227 				done = show_command_output(&imsg);
228 				break;
229 			case SHOW_STATS:
230 				done = show_stats_output(&imsg);
231 				break;
232 			case NONE:
233 				break;
234 			case MONITOR:
235 				break;
236 			default:
237 				err(1, "unexpected reply (%d)", res->action);
238 			}
239 			/* insert imsg replies switch here */
240 
241 			imsg_free(&imsg);
242 		}
243 	}
244 	close(ctl_sock);
245 	free(ibuf);
246 
247 	return (0);
248 }
249 
250 static int
251 show_command_output(struct imsg *imsg)
252 {
253 	switch (imsg->hdr.type) {
254 	case IMSG_CTL_OK:
255 		printf("command succeeded\n");
256 		break;
257 	case IMSG_CTL_FAIL:
258 		printf("command failed\n");
259 		break;
260 	default:
261 		errx(1, "wrong message in summary: %u", imsg->hdr.type);
262 	}
263 	return (1);
264 }
265 
266 void
267 show_sizes(void)
268 {
269 	/*
270 	 * size _does_ matter.
271 	 *
272 	 * small changes to ramqueue and diskqueue structures may cause
273 	 * large changes to memory and disk usage on busy/large hosts.
274 	 *
275 	 * this will help developers optimize memory/disk use, and help
276 	 * admins understand how the ramqueue.size / ramqueue.size.max
277 	 * stats are computed (smtpctl show stats).
278 	 *
279 	 * -- gilles@
280 	 *
281 	 */
282 	printf("struct ramqueue: %zu\n", sizeof (struct ramqueue));
283 	printf("struct ramqueue_host: %zu\n", sizeof (struct ramqueue_host));
284 	printf("struct ramqueue_message: %zu\n", sizeof (struct ramqueue_message));
285 	printf("struct ramqueue_envelope: %zu\n", sizeof (struct ramqueue_envelope));
286 
287 	printf("struct envelope: %zu\n", sizeof (struct envelope));
288 	printf("struct delivery: %zu\n", sizeof (struct delivery));
289 }
290 
291 static void
292 stat_print(int stat, int what)
293 {
294 	static const char *names[STATS_MAX] = {
295 		"smtp.sessions",
296 		"smtp.sessions.inet4",
297 		"smtp.sessions.inet6",
298 		"smtp.sessions.smtps",
299 		"smtp.sessions.starttls",
300 
301 		"mta.sessions",
302 
303 		"mda.sessions",
304 
305 		"control.sessions",
306 
307 		"lka.sessions",
308 		"lka.sessions.mx",
309 		"lka.sessions.host",
310 		"lka.sessions.cname",
311 		"lka.sessions.failure",
312 
313 		"runner",
314 		"runner.bounces",
315 
316 		"queue.inserts.local",
317 		"queue.inserts.remote",
318 
319 		"ramqueue.envelopes",
320 		"ramqueue.messages",
321 		"ramqueue.batches",
322 		"ramqueue.hosts",
323 	};
324 	const char *sfx;
325 
326 	if (what == STAT_ACTIVE)
327 		sfx = ".active";
328 	else if (what == STAT_MAXACTIVE)
329 		sfx = ".maxactive";
330 	else
331 		sfx = "";
332 
333 	printf("%s%s=%zd\n", names[stat], sfx, stat_get(stat, what));
334 }
335 
336 static int
337 show_stats_output(struct imsg *imsg)
338 {
339 	struct stats	*stats;
340 	struct stat_counter	*s;
341 
342 	if (imsg->hdr.type != IMSG_STATS)
343 		errx(1, "show_stats_output: bad hdr type (%d)", imsg->hdr.type);
344 
345 	if (IMSG_DATA_SIZE(imsg) != sizeof(*stats))
346 		errx(1, "show_stats_output: bad data size");
347 
348 	stats = imsg->data;
349 	stat_init(stats->counters, STATS_MAX);
350 	s = stats->counters;
351 
352 	stat_print(STATS_CONTROL_SESSION, STAT_COUNT);
353 	stat_print(STATS_CONTROL_SESSION, STAT_ACTIVE);
354 	stat_print(STATS_CONTROL_SESSION, STAT_MAXACTIVE);
355 
356 	stat_print(STATS_MDA_SESSION, STAT_COUNT);
357 	stat_print(STATS_MDA_SESSION, STAT_ACTIVE);
358 	stat_print(STATS_MDA_SESSION, STAT_MAXACTIVE);
359 
360 	stat_print(STATS_MTA_SESSION, STAT_COUNT);
361 	stat_print(STATS_MTA_SESSION, STAT_ACTIVE);
362 	stat_print(STATS_MTA_SESSION, STAT_MAXACTIVE);
363 
364 	stat_print(STATS_LKA_SESSION, STAT_COUNT);
365 	stat_print(STATS_LKA_SESSION, STAT_ACTIVE);
366 	stat_print(STATS_LKA_SESSION, STAT_MAXACTIVE);
367 	stat_print(STATS_LKA_SESSION_MX, STAT_COUNT);
368 	stat_print(STATS_LKA_SESSION_HOST, STAT_COUNT);
369 	stat_print(STATS_LKA_SESSION_CNAME, STAT_COUNT);
370 	stat_print(STATS_LKA_FAILURE, STAT_COUNT);
371 
372 	printf("parent.uptime=%lld\n",
373 	    (long long int) (time(NULL) - stats->parent.start));
374 
375 	stat_print(STATS_QUEUE_LOCAL, STAT_COUNT);
376 	stat_print(STATS_QUEUE_REMOTE, STAT_COUNT);
377 
378 	stat_print(STATS_RUNNER, STAT_COUNT);
379 	stat_print(STATS_RUNNER, STAT_ACTIVE);
380 	stat_print(STATS_RUNNER, STAT_MAXACTIVE);
381 
382 	stat_print(STATS_RUNNER_BOUNCES, STAT_COUNT);
383 	stat_print(STATS_RUNNER_BOUNCES, STAT_ACTIVE);
384 	stat_print(STATS_RUNNER_BOUNCES, STAT_MAXACTIVE);
385 
386 	stat_print(STATS_RAMQUEUE_HOST, STAT_ACTIVE);
387 	stat_print(STATS_RAMQUEUE_BATCH, STAT_ACTIVE);
388 	stat_print(STATS_RAMQUEUE_MESSAGE, STAT_ACTIVE);
389 	stat_print(STATS_RAMQUEUE_ENVELOPE, STAT_ACTIVE);
390 
391 	stat_print(STATS_RAMQUEUE_HOST, STAT_MAXACTIVE);
392 	stat_print(STATS_RAMQUEUE_BATCH, STAT_MAXACTIVE);
393 	stat_print(STATS_RAMQUEUE_MESSAGE, STAT_MAXACTIVE);
394 	stat_print(STATS_RAMQUEUE_ENVELOPE, STAT_MAXACTIVE);
395 
396 	printf("ramqueue.size=%zd\n",
397 	    s[STATS_RAMQUEUE_HOST].active * sizeof(struct ramqueue_host) +
398 	    s[STATS_RAMQUEUE_BATCH].active * sizeof(struct ramqueue_batch) +
399 	    s[STATS_RAMQUEUE_MESSAGE].active * sizeof(struct ramqueue_message) +
400 	    s[STATS_RAMQUEUE_ENVELOPE].active * sizeof(struct ramqueue_envelope));
401 	printf("ramqueue.size.max=%zd\n",
402 	    s[STATS_RAMQUEUE_HOST].maxactive * sizeof(struct ramqueue_host) +
403 	    s[STATS_RAMQUEUE_BATCH].maxactive * sizeof(struct ramqueue_batch) +
404 	    s[STATS_RAMQUEUE_MESSAGE].maxactive * sizeof(struct ramqueue_message) +
405 	    s[STATS_RAMQUEUE_ENVELOPE].maxactive * sizeof(struct ramqueue_envelope));
406 
407 	printf("smtp.errors.delays=%zd\n", stats->smtp.delays);
408 	printf("smtp.errors.linetoolong=%zd\n", stats->smtp.linetoolong);
409 	printf("smtp.errors.read_eof=%zd\n", stats->smtp.read_eof);
410 	printf("smtp.errors.read_system=%zd\n", stats->smtp.read_error);
411 	printf("smtp.errors.read_timeout=%zd\n", stats->smtp.read_timeout);
412 	printf("smtp.errors.tempfail=%zd\n", stats->smtp.tempfail);
413 	printf("smtp.errors.toofast=%zd\n", stats->smtp.toofast);
414 	printf("smtp.errors.write_eof=%zd\n", stats->smtp.write_eof);
415 	printf("smtp.errors.write_system=%zd\n", stats->smtp.write_error);
416 	printf("smtp.errors.write_timeout=%zd\n", stats->smtp.write_timeout);
417 
418 	stat_print(STATS_SMTP_SESSION, STAT_COUNT);
419 	stat_print(STATS_SMTP_SESSION_INET4, STAT_COUNT);
420 	stat_print(STATS_SMTP_SESSION_INET6, STAT_COUNT);
421 	printf("smtp.sessions.aborted=%zd\n", stats->smtp.read_eof +
422 	    stats->smtp.read_error + stats->smtp.write_eof +
423 	    stats->smtp.write_error);
424 
425 	stat_print(STATS_SMTP_SESSION, STAT_ACTIVE);
426 	stat_print(STATS_SMTP_SESSION, STAT_MAXACTIVE);
427 
428 	printf("smtp.sessions.timeout=%zd\n", stats->smtp.read_timeout +
429 	    stats->smtp.write_timeout);
430 
431 	stat_print(STATS_SMTP_SMTPS, STAT_COUNT);
432 	stat_print(STATS_SMTP_SMTPS, STAT_ACTIVE);
433 	stat_print(STATS_SMTP_SMTPS, STAT_MAXACTIVE);
434 
435 	stat_print(STATS_SMTP_STARTTLS, STAT_COUNT);
436 	stat_print(STATS_SMTP_STARTTLS, STAT_ACTIVE);
437 	stat_print(STATS_SMTP_STARTTLS, STAT_MAXACTIVE);
438 
439 	return (1);
440 }
441