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