1 /* $OpenBSD: smtpctl.c,v 1.83 2012/07/09 09:57:53 gilles 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 <inttypes.h> 34 #include <pwd.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <time.h> 39 #include <unistd.h> 40 41 #include "smtpd.h" 42 #include "parser.h" 43 #include "log.h" 44 45 void usage(void); 46 static void setup_env(struct smtpd *); 47 static int show_command_output(struct imsg *); 48 static int show_stats_output(struct imsg *); 49 static void show_queue(int); 50 static void show_envelope(struct envelope *, int); 51 static void getflag(u_int *, int, char *, char *, size_t); 52 53 int proctype; 54 struct imsgbuf *ibuf; 55 56 int sendmail = 0; 57 extern char *__progname; 58 59 struct smtpd *env = NULL; 60 61 __dead void 62 usage(void) 63 { 64 extern char *__progname; 65 66 if (sendmail) 67 fprintf(stderr, "usage: %s [-tv] [-f from] [-F name] to ..\n", 68 __progname); 69 else 70 fprintf(stderr, "usage: %s command [argument ...]\n", __progname); 71 exit(1); 72 } 73 74 static void 75 setup_env(struct smtpd *smtpd) 76 { 77 bzero(smtpd, sizeof (*smtpd)); 78 env = smtpd; 79 80 if ((env->sc_pw = getpwnam(SMTPD_USER)) == NULL) 81 errx(1, "unknown user %s", SMTPD_USER); 82 83 env->sc_queue = queue_backend_lookup("fs"); 84 if (env->sc_queue == NULL) 85 errx(1, "could not find queue backend"); 86 87 if (!env->sc_queue->init(0)) 88 errx(1, "invalid directory permissions"); 89 } 90 91 int 92 main(int argc, char *argv[]) 93 { 94 struct sockaddr_un sun; 95 struct parse_result *res = NULL; 96 struct imsg imsg; 97 struct smtpd smtpd; 98 int ctl_sock; 99 int done = 0; 100 int n, verbose = 0; 101 102 /* parse options */ 103 if (strcmp(__progname, "sendmail") == 0 || strcmp(__progname, "send-mail") == 0) 104 sendmail = 1; 105 else if (strcmp(__progname, "mailq") == 0) { 106 if (geteuid()) 107 errx(1, "need root privileges"); 108 setup_env(&smtpd); 109 show_queue(0); 110 return 0; 111 } else if (strcmp(__progname, "smtpctl") == 0) { 112 113 /* check for root privileges */ 114 if (geteuid()) 115 errx(1, "need root privileges"); 116 117 setup_env(&smtpd); 118 119 if ((res = parse(argc - 1, argv + 1)) == NULL) 120 exit(1); 121 122 /* handle "disconnected" commands */ 123 switch (res->action) { 124 case SHOW_QUEUE: 125 show_queue(0); 126 break; 127 case SHOW_RUNQUEUE: 128 break; 129 default: 130 goto connected; 131 } 132 return 0; 133 } else 134 errx(1, "unsupported mode"); 135 136 connected: 137 /* connect to smtpd control socket */ 138 if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) 139 err(1, "socket"); 140 141 bzero(&sun, sizeof(sun)); 142 sun.sun_family = AF_UNIX; 143 strlcpy(sun.sun_path, SMTPD_SOCKET, sizeof(sun.sun_path)); 144 if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) { 145 if (sendmail) 146 return enqueue_offline(argc, argv); 147 err(1, "connect: %s", SMTPD_SOCKET); 148 } 149 150 if ((ibuf = calloc(1, sizeof(struct imsgbuf))) == NULL) 151 err(1, NULL); 152 imsg_init(ibuf, ctl_sock); 153 154 if (sendmail) 155 return enqueue(argc, argv); 156 157 /* process user request */ 158 switch (res->action) { 159 case NONE: 160 usage(); 161 /* not reached */ 162 163 case SCHEDULE: 164 case REMOVE: { 165 u_int64_t ulval; 166 char *ep; 167 168 errno = 0; 169 ulval = strtoul(res->data, &ep, 16); 170 if (res->data[0] == '\0' || *ep != '\0') 171 errx(1, "invalid msgid/evpid"); 172 if (errno == ERANGE && ulval == ULLONG_MAX) 173 errx(1, "invalid msgid/evpid"); 174 if (ulval == 0) 175 errx(1, "invalid msgid/evpid"); 176 177 if (res->action == SCHEDULE) 178 imsg_compose(ibuf, IMSG_SCHEDULER_SCHEDULE, 0, 0, -1, &ulval, 179 sizeof(ulval)); 180 if (res->action == REMOVE) 181 imsg_compose(ibuf, IMSG_SCHEDULER_REMOVE, 0, 0, -1, &ulval, 182 sizeof(ulval)); 183 break; 184 } 185 186 case SCHEDULE_ALL: { 187 u_int64_t ulval = 0; 188 189 imsg_compose(ibuf, IMSG_SCHEDULER_SCHEDULE, 0, 0, -1, &ulval, 190 sizeof(ulval)); 191 break; 192 } 193 194 case SHUTDOWN: 195 imsg_compose(ibuf, IMSG_CTL_SHUTDOWN, 0, 0, -1, NULL, 0); 196 break; 197 case PAUSE_MDA: 198 imsg_compose(ibuf, IMSG_QUEUE_PAUSE_MDA, 0, 0, -1, NULL, 0); 199 break; 200 case PAUSE_MTA: 201 imsg_compose(ibuf, IMSG_QUEUE_PAUSE_MTA, 0, 0, -1, NULL, 0); 202 break; 203 case PAUSE_SMTP: 204 imsg_compose(ibuf, IMSG_SMTP_PAUSE, 0, 0, -1, NULL, 0); 205 break; 206 case RESUME_MDA: 207 imsg_compose(ibuf, IMSG_QUEUE_RESUME_MDA, 0, 0, -1, NULL, 0); 208 break; 209 case RESUME_MTA: 210 imsg_compose(ibuf, IMSG_QUEUE_RESUME_MTA, 0, 0, -1, NULL, 0); 211 break; 212 case RESUME_SMTP: 213 imsg_compose(ibuf, IMSG_SMTP_RESUME, 0, 0, -1, NULL, 0); 214 break; 215 case SHOW_STATS: 216 imsg_compose(ibuf, IMSG_STATS, 0, 0, -1, NULL, 0); 217 break; 218 case MONITOR: 219 /* XXX */ 220 break; 221 case LOG_VERBOSE: 222 verbose = 1; 223 /* FALLTHROUGH */ 224 case LOG_BRIEF: 225 imsg_compose(ibuf, IMSG_CTL_VERBOSE, 0, 0, -1, &verbose, 226 sizeof(verbose)); 227 printf("logging request sent.\n"); 228 done = 1; 229 break; 230 default: 231 errx(1, "unknown request (%d)", res->action); 232 } 233 234 while (ibuf->w.queued) 235 if (msgbuf_write(&ibuf->w) < 0) 236 err(1, "write error"); 237 238 while (!done) { 239 if ((n = imsg_read(ibuf)) == -1) 240 errx(1, "imsg_read error"); 241 if (n == 0) 242 errx(1, "pipe closed"); 243 244 while (!done) { 245 if ((n = imsg_get(ibuf, &imsg)) == -1) 246 errx(1, "imsg_get error"); 247 if (n == 0) 248 break; 249 switch(res->action) { 250 case REMOVE: 251 case SCHEDULE: 252 case SCHEDULE_ALL: 253 case SHUTDOWN: 254 case PAUSE_MDA: 255 case PAUSE_MTA: 256 case PAUSE_SMTP: 257 case RESUME_MDA: 258 case RESUME_MTA: 259 case RESUME_SMTP: 260 case LOG_VERBOSE: 261 case LOG_BRIEF: 262 done = show_command_output(&imsg); 263 break; 264 case SHOW_STATS: 265 done = show_stats_output(&imsg); 266 break; 267 case NONE: 268 break; 269 case MONITOR: 270 break; 271 default: 272 err(1, "unexpected reply (%d)", res->action); 273 } 274 /* insert imsg replies switch here */ 275 276 imsg_free(&imsg); 277 } 278 } 279 close(ctl_sock); 280 free(ibuf); 281 282 return (0); 283 } 284 285 static int 286 show_command_output(struct imsg *imsg) 287 { 288 switch (imsg->hdr.type) { 289 case IMSG_CTL_OK: 290 printf("command succeeded\n"); 291 break; 292 case IMSG_CTL_FAIL: 293 printf("command failed\n"); 294 break; 295 default: 296 errx(1, "wrong message in summary: %u", imsg->hdr.type); 297 } 298 return (1); 299 } 300 301 static void 302 stat_print(int stat, int what) 303 { 304 static const char *names[STATS_MAX] = { 305 "smtp.sessions", 306 "smtp.sessions.inet4", 307 "smtp.sessions.inet6", 308 "smtp.sessions.smtps", 309 "smtp.sessions.starttls", 310 311 "mta.sessions", 312 313 "mda.sessions", 314 315 "control.sessions", 316 317 "lka.sessions", 318 "lka.sessions.mx", 319 "lka.sessions.host", 320 "lka.sessions.cname", 321 "lka.sessions.failure", 322 323 "scheduler", 324 "scheduler.bounces", 325 326 "queue.inserts.local", 327 "queue.inserts.remote", 328 329 "ramqueue.envelopes", 330 "ramqueue.messages", 331 "ramqueue.batches", 332 "ramqueue.hosts", 333 }; 334 const char *sfx; 335 336 if (what == STAT_ACTIVE) 337 sfx = ".active"; 338 else if (what == STAT_MAXACTIVE) 339 sfx = ".maxactive"; 340 else 341 sfx = ""; 342 343 printf("%s%s=%zd\n", names[stat], sfx, stat_get(stat, what)); 344 } 345 346 static int 347 show_stats_output(struct imsg *imsg) 348 { 349 struct stats *stats; 350 351 if (imsg->hdr.type != IMSG_STATS) 352 errx(1, "show_stats_output: bad hdr type (%d)", imsg->hdr.type); 353 354 if (IMSG_DATA_SIZE(imsg) != sizeof(*stats)) 355 errx(1, "show_stats_output: bad data size"); 356 357 stats = imsg->data; 358 stat_init(stats->counters, STATS_MAX); 359 360 stat_print(STATS_CONTROL_SESSION, STAT_COUNT); 361 stat_print(STATS_CONTROL_SESSION, STAT_ACTIVE); 362 stat_print(STATS_CONTROL_SESSION, STAT_MAXACTIVE); 363 364 stat_print(STATS_MDA_SESSION, STAT_COUNT); 365 stat_print(STATS_MDA_SESSION, STAT_ACTIVE); 366 stat_print(STATS_MDA_SESSION, STAT_MAXACTIVE); 367 368 stat_print(STATS_MTA_SESSION, STAT_COUNT); 369 stat_print(STATS_MTA_SESSION, STAT_ACTIVE); 370 stat_print(STATS_MTA_SESSION, STAT_MAXACTIVE); 371 372 stat_print(STATS_LKA_SESSION, STAT_COUNT); 373 stat_print(STATS_LKA_SESSION, STAT_ACTIVE); 374 stat_print(STATS_LKA_SESSION, STAT_MAXACTIVE); 375 stat_print(STATS_LKA_SESSION_MX, STAT_COUNT); 376 stat_print(STATS_LKA_SESSION_HOST, STAT_COUNT); 377 stat_print(STATS_LKA_SESSION_CNAME, STAT_COUNT); 378 stat_print(STATS_LKA_FAILURE, STAT_COUNT); 379 380 printf("parent.uptime=%lld\n", 381 (long long int) (time(NULL) - stats->parent.start)); 382 383 stat_print(STATS_QUEUE_LOCAL, STAT_COUNT); 384 stat_print(STATS_QUEUE_REMOTE, STAT_COUNT); 385 386 stat_print(STATS_SCHEDULER, STAT_COUNT); 387 stat_print(STATS_SCHEDULER, STAT_ACTIVE); 388 stat_print(STATS_SCHEDULER, STAT_MAXACTIVE); 389 390 stat_print(STATS_SCHEDULER_BOUNCES, STAT_COUNT); 391 stat_print(STATS_SCHEDULER_BOUNCES, STAT_ACTIVE); 392 stat_print(STATS_SCHEDULER_BOUNCES, STAT_MAXACTIVE); 393 394 stat_print(STATS_RAMQUEUE_HOST, STAT_ACTIVE); 395 stat_print(STATS_RAMQUEUE_BATCH, STAT_ACTIVE); 396 stat_print(STATS_RAMQUEUE_MESSAGE, STAT_ACTIVE); 397 stat_print(STATS_RAMQUEUE_ENVELOPE, STAT_ACTIVE); 398 399 stat_print(STATS_RAMQUEUE_HOST, STAT_MAXACTIVE); 400 stat_print(STATS_RAMQUEUE_BATCH, STAT_MAXACTIVE); 401 stat_print(STATS_RAMQUEUE_MESSAGE, STAT_MAXACTIVE); 402 stat_print(STATS_RAMQUEUE_ENVELOPE, STAT_MAXACTIVE); 403 404 printf("smtp.errors.delays=%zd\n", stats->smtp.delays); 405 printf("smtp.errors.linetoolong=%zd\n", stats->smtp.linetoolong); 406 printf("smtp.errors.read_eof=%zd\n", stats->smtp.read_eof); 407 printf("smtp.errors.read_system=%zd\n", stats->smtp.read_error); 408 printf("smtp.errors.read_timeout=%zd\n", stats->smtp.read_timeout); 409 printf("smtp.errors.tempfail=%zd\n", stats->smtp.tempfail); 410 printf("smtp.errors.toofast=%zd\n", stats->smtp.toofast); 411 printf("smtp.errors.write_eof=%zd\n", stats->smtp.write_eof); 412 printf("smtp.errors.write_system=%zd\n", stats->smtp.write_error); 413 printf("smtp.errors.write_timeout=%zd\n", stats->smtp.write_timeout); 414 415 stat_print(STATS_SMTP_SESSION, STAT_COUNT); 416 stat_print(STATS_SMTP_SESSION_INET4, STAT_COUNT); 417 stat_print(STATS_SMTP_SESSION_INET6, STAT_COUNT); 418 printf("smtp.sessions.aborted=%zd\n", stats->smtp.read_eof + 419 stats->smtp.read_error + stats->smtp.write_eof + 420 stats->smtp.write_error); 421 422 stat_print(STATS_SMTP_SESSION, STAT_ACTIVE); 423 stat_print(STATS_SMTP_SESSION, STAT_MAXACTIVE); 424 425 printf("smtp.sessions.timeout=%zd\n", stats->smtp.read_timeout + 426 stats->smtp.write_timeout); 427 428 stat_print(STATS_SMTP_SMTPS, STAT_COUNT); 429 stat_print(STATS_SMTP_SMTPS, STAT_ACTIVE); 430 stat_print(STATS_SMTP_SMTPS, STAT_MAXACTIVE); 431 432 stat_print(STATS_SMTP_STARTTLS, STAT_COUNT); 433 stat_print(STATS_SMTP_STARTTLS, STAT_ACTIVE); 434 stat_print(STATS_SMTP_STARTTLS, STAT_MAXACTIVE); 435 436 return (1); 437 } 438 439 static void 440 show_queue(int flags) 441 { 442 struct qwalk *q; 443 struct envelope envelope; 444 u_int64_t evpid; 445 446 log_init(1); 447 448 if (chroot(PATH_SPOOL) == -1 || chdir(".") == -1) 449 err(1, "%s", PATH_SPOOL); 450 451 q = qwalk_new(0); 452 453 while (qwalk(q, &evpid)) { 454 if (! queue_envelope_load(evpid, &envelope)) 455 continue; 456 show_envelope(&envelope, flags); 457 } 458 459 qwalk_close(q); 460 } 461 462 static void 463 show_envelope(struct envelope *e, int flags) 464 { 465 char status[128]; 466 467 status[0] = '\0'; 468 469 getflag(&e->flags, DF_BOUNCE, "BOUNCE", 470 status, sizeof(status)); 471 getflag(&e->flags, DF_AUTHENTICATED, "AUTH", 472 status, sizeof(status)); 473 getflag(&e->flags, DF_ENQUEUED, "ENQUEUED", 474 status, sizeof(status)); 475 getflag(&e->flags, DF_INTERNAL, "INTERNAL", 476 status, sizeof(status)); 477 478 if (e->flags) 479 errx(1, "%016" PRIx64 ": unexpected flags 0x%04x", e->id, 480 e->flags); 481 482 if (status[0]) 483 status[strlen(status) - 1] = '\0'; 484 else 485 strlcpy(status, "-", sizeof(status)); 486 487 switch (e->type) { 488 case D_MDA: 489 printf("MDA"); 490 break; 491 case D_MTA: 492 printf("MTA"); 493 break; 494 case D_BOUNCE: 495 printf("BOUNCE"); 496 break; 497 default: 498 printf("UNKNOWN"); 499 } 500 501 printf("|%016" PRIx64 "|%s|%s@%s|%s@%s|%" PRId64 "|%" PRId64 "|%u", 502 e->id, 503 status, 504 e->sender.user, e->sender.domain, 505 e->dest.user, e->dest.domain, 506 (int64_t) e->lasttry, 507 (int64_t) e->expire, 508 e->retry); 509 510 if (e->errorline[0] != '\0') 511 printf("|%s", e->errorline); 512 513 printf("\n"); 514 } 515 516 static void 517 getflag(u_int *bitmap, int bit, char *bitstr, char *buf, size_t len) 518 { 519 if (*bitmap & bit) { 520 *bitmap &= ~bit; 521 strlcat(buf, bitstr, len); 522 strlcat(buf, ",", len); 523 } 524 } 525