1 /* $OpenBSD: envelope.c,v 1.6 2012/06/03 19:52:56 eric Exp $ */ 2 3 /* 4 * Copyright (c) 2011 Gilles Chehade <gilles@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/param.h> 23 #include <sys/socket.h> 24 #include <sys/stat.h> 25 26 #include <netinet/in.h> 27 #include <arpa/inet.h> 28 29 #include <ctype.h> 30 #include <err.h> 31 #include <errno.h> 32 #include <event.h> 33 #include <fcntl.h> 34 #include <imsg.h> 35 #include <inttypes.h> 36 #include <libgen.h> 37 #include <pwd.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <time.h> 42 #include <unistd.h> 43 44 #include "smtpd.h" 45 #include "log.h" 46 47 static int ascii_load_uint8(u_int8_t *, char *); 48 static int ascii_load_uint16(u_int16_t *, char *); 49 static int ascii_load_uint32(u_int32_t *, char *); 50 static int ascii_load_time(time_t *, char *); 51 static int ascii_load_uint32_hex(u_int32_t *, char *); 52 static int ascii_load_uint64_hex(u_int64_t *, char *); 53 static int ascii_load_type(enum delivery_type *, char *); 54 static int ascii_load_string(char *, char *, size_t); 55 static int ascii_load_sockaddr(struct sockaddr_storage *, char *); 56 static int ascii_load_mda_method(enum action_type *, char *); 57 static int ascii_load_mailaddr(struct mailaddr *, char *); 58 static int ascii_load_flags(enum delivery_flags *, char *); 59 static int ascii_load_mta_relay_flags(u_int8_t *, char *); 60 61 static int ascii_dump_uint8(u_int8_t, char *, size_t); 62 static int ascii_dump_uint32(u_int32_t, char *, size_t); 63 static int ascii_dump_time(time_t, char *, size_t); 64 static int ascii_dump_uint32_hex(u_int32_t, char *, size_t); 65 static int ascii_dump_uint64_hex(u_int64_t, char *, size_t); 66 static int ascii_dump_string(char *, char *, size_t); 67 static int ascii_dump_type(enum delivery_type, char *, size_t); 68 static int ascii_dump_mda_method(enum action_type, char *, size_t); 69 static int ascii_dump_mailaddr(struct mailaddr *, char *, size_t); 70 static int ascii_dump_flags(enum delivery_flags, char *, size_t); 71 static int ascii_dump_mta_relay_port(u_int16_t, char *, size_t); 72 static int ascii_dump_mta_relay_flags(u_int8_t, char *, size_t); 73 74 void 75 envelope_set_errormsg(struct envelope *e, char *fmt, ...) 76 { 77 int ret; 78 va_list ap; 79 80 va_start(ap, fmt); 81 ret = vsnprintf(e->errorline, sizeof(e->errorline), fmt, ap); 82 va_end(ap); 83 84 /* this should not happen */ 85 if (ret == -1) 86 err(1, "vsnprintf"); 87 88 if ((size_t)ret >= sizeof(e->errorline)) 89 strlcpy(e->errorline + (sizeof(e->errorline) - 4), "...", 4); 90 } 91 92 int 93 envelope_load_file(struct envelope *ep, FILE *fp) 94 { 95 char *buf, *lbuf; 96 char *field; 97 size_t len; 98 enum envelope_field fields[] = { 99 EVP_VERSION, 100 EVP_ID, 101 EVP_MSGID, 102 EVP_HOSTNAME, 103 EVP_SOCKADDR, 104 EVP_HELO, 105 EVP_SENDER, 106 EVP_RCPT, 107 EVP_DEST, 108 EVP_TYPE, 109 EVP_CTIME, 110 EVP_EXPIRE, 111 EVP_RETRY, 112 EVP_LASTTRY, 113 EVP_FLAGS, 114 EVP_ERRORLINE, 115 EVP_MDA_METHOD, 116 EVP_MDA_BUFFER, 117 EVP_MDA_USER, 118 EVP_MTA_RELAY_HOST, 119 EVP_MTA_RELAY_PORT, 120 EVP_MTA_RELAY_CERT, 121 EVP_MTA_RELAY_FLAGS, 122 EVP_MTA_RELAY_AUTHMAP 123 }; 124 int i; 125 int n; 126 int ret; 127 128 n = sizeof(fields) / sizeof(enum envelope_field); 129 bzero(ep, sizeof (*ep)); 130 lbuf = NULL; 131 while ((buf = fgetln(fp, &len))) { 132 if (buf[len - 1] == '\n') 133 buf[len - 1] = '\0'; 134 else { 135 if ((lbuf = malloc(len + 1)) == NULL) 136 err(1, NULL); 137 memcpy(lbuf, buf, len); 138 lbuf[len] = '\0'; 139 buf = lbuf; 140 } 141 142 for (i = 0; i < n; ++i) { 143 field = envelope_ascii_field_name(fields[i]); 144 len = strlen(field); 145 if (! strncasecmp(field, buf, len)) { 146 /* skip kw and tailing whitespaces */ 147 buf += len; 148 while (*buf && isspace(*buf)) 149 buf++; 150 151 /* we *want* ':' */ 152 if (*buf != ':') 153 continue; 154 buf++; 155 156 /* skip whitespaces after separator */ 157 while (*buf && isspace(*buf)) 158 buf++; 159 160 ret = envelope_ascii_load(fields[i], ep, buf); 161 if (ret == 0) 162 goto err; 163 break; 164 } 165 } 166 167 /* unknown keyword */ 168 if (i == n) 169 goto err; 170 } 171 free(lbuf); 172 return 1; 173 174 err: 175 free(lbuf); 176 return 0; 177 } 178 179 int 180 envelope_dump_file(struct envelope *ep, FILE *fp) 181 { 182 char buf[8192]; 183 184 enum envelope_field fields[] = { 185 EVP_VERSION, 186 EVP_MSGID, 187 EVP_TYPE, 188 EVP_HELO, 189 EVP_HOSTNAME, 190 EVP_ERRORLINE, 191 EVP_SOCKADDR, 192 EVP_SENDER, 193 EVP_RCPT, 194 EVP_DEST, 195 EVP_CTIME, 196 EVP_LASTTRY, 197 EVP_EXPIRE, 198 EVP_RETRY, 199 EVP_FLAGS 200 }; 201 enum envelope_field mda_fields[] = { 202 EVP_MDA_METHOD, 203 EVP_MDA_BUFFER, 204 EVP_MDA_USER 205 }; 206 enum envelope_field mta_fields[] = { 207 EVP_MTA_RELAY_HOST, 208 EVP_MTA_RELAY_PORT, 209 EVP_MTA_RELAY_CERT, 210 EVP_MTA_RELAY_AUTHMAP, 211 EVP_MTA_RELAY_FLAGS 212 }; 213 enum envelope_field *pfields = NULL; 214 int i; 215 int n; 216 217 n = sizeof(fields) / sizeof(enum envelope_field); 218 for (i = 0; i < n; ++i) { 219 bzero(buf, sizeof buf); 220 if (! envelope_ascii_dump(fields[i], ep, buf, sizeof buf)) 221 goto err; 222 if (buf[0] == '\0') 223 continue; 224 fprintf(fp, "%s: %s\n", 225 envelope_ascii_field_name(fields[i]), buf); 226 } 227 228 switch (ep->type) { 229 case D_MDA: 230 pfields = mda_fields; 231 n = sizeof(mda_fields) / sizeof(enum envelope_field); 232 break; 233 case D_MTA: 234 pfields = mta_fields; 235 n = sizeof(mta_fields) / sizeof(enum envelope_field); 236 break; 237 case D_BOUNCE: 238 /* nothing ! */ 239 break; 240 default: 241 goto err; 242 } 243 244 if (pfields) { 245 for (i = 0; i < n; ++i) { 246 bzero(buf, sizeof buf); 247 if (! envelope_ascii_dump(pfields[i], ep, buf, 248 sizeof buf)) 249 goto err; 250 if (buf[0] == '\0') 251 continue; 252 fprintf(fp, "%s: %s\n", 253 envelope_ascii_field_name(pfields[i]), buf); 254 } 255 } 256 257 if (fflush(fp) != 0) 258 goto err; 259 260 return 1; 261 262 err: 263 return 0; 264 } 265 266 char * 267 envelope_ascii_field_name(enum envelope_field field) 268 { 269 switch (field) { 270 case EVP_VERSION: 271 return "version"; 272 case EVP_ID: 273 return "id"; 274 case EVP_MSGID: 275 return "msgid"; 276 case EVP_TYPE: 277 return "type"; 278 case EVP_HELO: 279 return "helo"; 280 case EVP_HOSTNAME: 281 return "hostname"; 282 case EVP_ERRORLINE: 283 return "errorline"; 284 case EVP_SOCKADDR: 285 return "sockaddr"; 286 case EVP_SENDER: 287 return "sender"; 288 case EVP_RCPT: 289 return "rcpt"; 290 case EVP_DEST: 291 return "dest"; 292 case EVP_CTIME: 293 return "ctime"; 294 case EVP_EXPIRE: 295 return "expire"; 296 case EVP_RETRY: 297 return "retry"; 298 case EVP_LASTTRY: 299 return "last-try"; 300 case EVP_FLAGS: 301 return "flags"; 302 case EVP_MDA_METHOD: 303 return "mda-method"; 304 case EVP_MDA_BUFFER: 305 return "mda-buffer"; 306 case EVP_MDA_USER: 307 return "mda-user"; 308 case EVP_MTA_RELAY_HOST: 309 return "mta-relay-host"; 310 case EVP_MTA_RELAY_PORT: 311 return "mta-relay-port"; 312 case EVP_MTA_RELAY_FLAGS: 313 return "mta-relay-flags"; 314 case EVP_MTA_RELAY_CERT: 315 return "mta-relay-cert"; 316 case EVP_MTA_RELAY_AUTHMAP: 317 return "mta-relay-authmap"; 318 } 319 320 return NULL; 321 } 322 323 int 324 envelope_ascii_load(enum envelope_field field, struct envelope *ep, char *buf) 325 { 326 uint32_t msgid; 327 int r; 328 329 switch (field) { 330 case EVP_VERSION: 331 return ascii_load_uint32(&ep->version, buf); 332 case EVP_ID: 333 return ascii_load_uint64_hex(&ep->id, buf); 334 case EVP_MSGID: 335 if ((r = ascii_load_uint32_hex(&msgid, buf))) 336 ep->id = msgid_to_evpid(msgid); 337 return (r); 338 case EVP_TYPE: 339 return ascii_load_type(&ep->type, buf); 340 case EVP_HELO: 341 return ascii_load_string(ep->helo, buf, sizeof ep->helo); 342 case EVP_HOSTNAME: 343 return ascii_load_string(ep->hostname, buf, 344 sizeof ep->hostname); 345 case EVP_ERRORLINE: 346 return ascii_load_string(ep->errorline, buf, 347 sizeof ep->errorline); 348 case EVP_SOCKADDR: 349 return ascii_load_sockaddr(&ep->ss, buf); 350 case EVP_SENDER: 351 return ascii_load_mailaddr(&ep->sender, buf); 352 case EVP_RCPT: 353 return ascii_load_mailaddr(&ep->rcpt, buf); 354 case EVP_DEST: 355 return ascii_load_mailaddr(&ep->dest, buf); 356 case EVP_MDA_METHOD: 357 return ascii_load_mda_method(&ep->agent.mda.method, buf); 358 case EVP_MDA_BUFFER: 359 return ascii_load_string(ep->agent.mda.to.buffer, buf, 360 sizeof ep->agent.mda.to.buffer); 361 case EVP_MDA_USER: 362 return ascii_load_string(ep->agent.mda.as_user, buf, 363 sizeof ep->agent.mda.as_user); 364 case EVP_MTA_RELAY_HOST: 365 return ascii_load_string(ep->agent.mta.relay.hostname, buf, 366 sizeof ep->agent.mta.relay.hostname); 367 case EVP_MTA_RELAY_PORT: { 368 u_int16_t port; 369 370 if (! ascii_load_uint16(&port, buf)) 371 return 0; 372 ep->agent.mta.relay.port = htons(port); 373 return 1; 374 } 375 case EVP_MTA_RELAY_CERT: 376 return ascii_load_string(ep->agent.mta.relay.cert, buf, 377 sizeof ep->agent.mta.relay.cert); 378 case EVP_MTA_RELAY_FLAGS: 379 return ascii_load_mta_relay_flags(&ep->agent.mta.relay.flags, 380 buf); 381 case EVP_MTA_RELAY_AUTHMAP: 382 return ascii_load_string(ep->agent.mta.relay.authmap, buf, 383 sizeof ep->agent.mta.relay.authmap); 384 case EVP_CTIME: 385 return ascii_load_time(&ep->creation, buf); 386 case EVP_EXPIRE: 387 return ascii_load_time(&ep->expire, buf); 388 case EVP_RETRY: 389 return ascii_load_uint8(&ep->retry, buf); 390 case EVP_LASTTRY: 391 return ascii_load_time(&ep->lasttry, buf); 392 case EVP_FLAGS: 393 return ascii_load_flags(&ep->flags, buf); 394 } 395 return 0; 396 } 397 398 int 399 envelope_ascii_dump(enum envelope_field field, struct envelope *ep, 400 char *buf, size_t len) 401 { 402 switch (field) { 403 case EVP_VERSION: 404 return ascii_dump_uint32(SMTPD_ENVELOPE_VERSION, buf, len); 405 case EVP_ID: 406 return ascii_dump_uint64_hex(ep->id, buf, len); 407 case EVP_MSGID: 408 return ascii_dump_uint32_hex(evpid_to_msgid(ep->id), buf, len); 409 case EVP_TYPE: 410 return ascii_dump_type(ep->type, buf, len); 411 case EVP_HELO: 412 return ascii_dump_string(ep->helo, buf, len); 413 case EVP_HOSTNAME: 414 return ascii_dump_string(ep->hostname, buf, len); 415 case EVP_ERRORLINE: 416 return ascii_dump_string(ep->errorline, buf, len); 417 case EVP_SOCKADDR: 418 return ascii_dump_string(ss_to_text(&ep->ss), buf, len); 419 case EVP_SENDER: 420 return ascii_dump_mailaddr(&ep->sender, buf, len); 421 case EVP_RCPT: 422 return ascii_dump_mailaddr(&ep->rcpt, buf, len); 423 case EVP_DEST: 424 return ascii_dump_mailaddr(&ep->dest, buf, len); 425 case EVP_MDA_METHOD: 426 return ascii_dump_mda_method(ep->agent.mda.method, buf, len); 427 case EVP_MDA_BUFFER: 428 return ascii_dump_string(ep->agent.mda.to.buffer, buf, len); 429 case EVP_MDA_USER: 430 return ascii_dump_string(ep->agent.mda.as_user, buf, len); 431 case EVP_MTA_RELAY_HOST: 432 return ascii_dump_string(ep->agent.mta.relay.hostname, 433 buf, len); 434 case EVP_MTA_RELAY_PORT: 435 return ascii_dump_mta_relay_port(ep->agent.mta.relay.port, 436 buf, len); 437 case EVP_MTA_RELAY_CERT: 438 return ascii_dump_string(ep->agent.mta.relay.cert, 439 buf, len); 440 case EVP_MTA_RELAY_FLAGS: 441 return ascii_dump_mta_relay_flags(ep->agent.mta.relay.flags, 442 buf, len); 443 case EVP_MTA_RELAY_AUTHMAP: 444 return ascii_dump_string(ep->agent.mta.relay.authmap, 445 buf, len); 446 case EVP_CTIME: 447 return ascii_dump_time(ep->creation, buf, len); 448 case EVP_EXPIRE: 449 return ascii_dump_time(ep->expire, buf, len); 450 case EVP_RETRY: 451 return ascii_dump_uint8(ep->retry, buf, len); 452 case EVP_LASTTRY: 453 return ascii_dump_time(ep->lasttry, buf, len); 454 case EVP_FLAGS: 455 return ascii_dump_flags(ep->flags, buf, len); 456 } 457 return 0; 458 } 459 460 static int 461 ascii_load_uint8(u_int8_t *dest, char *buf) 462 { 463 const char *errstr; 464 465 *dest = strtonum(buf, 0, 0xff, &errstr); 466 if (errstr) 467 return 0; 468 return 1; 469 } 470 471 static int 472 ascii_load_uint16(u_int16_t *dest, char *buf) 473 { 474 const char *errstr; 475 476 *dest = strtonum(buf, 0, 0xffff, &errstr); 477 if (errstr) 478 return 0; 479 return 1; 480 } 481 482 static int 483 ascii_load_uint32(u_int32_t *dest, char *buf) 484 { 485 const char *errstr; 486 487 *dest = strtonum(buf, 0, 0xffffffff, &errstr); 488 if (errstr) 489 return 0; 490 return 1; 491 } 492 493 static int 494 ascii_load_time(time_t *dest, char *buf) 495 { 496 const char *errstr; 497 498 *dest = (time_t) strtonum(buf, 0, 0x7fffffff, &errstr); 499 if (errstr) 500 return 0; 501 return 1; 502 } 503 504 static int 505 ascii_load_uint32_hex(u_int32_t *dest, char *buf) 506 { 507 uint64_t u; 508 509 if (ascii_load_uint64_hex(&u, buf) == 0) 510 return (0); 511 if (u > (uint64_t)0xffffffff) 512 return (0); 513 *dest = (uint32_t)u; 514 return (1); 515 } 516 517 static int 518 ascii_load_uint64_hex(u_int64_t *dest, char *buf) 519 { 520 char *endptr; 521 522 *dest = strtoull(buf, &endptr, 16); 523 if (buf[0] == '\0' || *endptr != '\0') 524 return 0; 525 if (errno == ERANGE && *dest == ULLONG_MAX) 526 return 0; 527 return 1; 528 } 529 530 static int 531 ascii_load_type(enum delivery_type *dest, char *buf) 532 { 533 if (strcasecmp(buf, "mda") == 0) 534 *dest = D_MDA; 535 else if (strcasecmp(buf, "mta") == 0) 536 *dest = D_MTA; 537 else if (strcasecmp(buf, "bounce") == 0) 538 *dest = D_BOUNCE; 539 else 540 return 0; 541 return 1; 542 } 543 544 static int 545 ascii_load_string(char *dest, char *buf, size_t len) 546 { 547 if (strlcpy(dest, buf, len) >= len) 548 return 0; 549 return 1; 550 } 551 552 static int 553 ascii_load_sockaddr(struct sockaddr_storage *ss, char *buf) 554 { 555 struct sockaddr_in6 ssin6; 556 struct sockaddr_in ssin; 557 558 if (strncasecmp("IPv6:", buf, 5) == 0) { 559 if (inet_pton(AF_INET6, buf + 5, &ssin6.sin6_addr) != 1) 560 return 0; 561 ssin6.sin6_family = AF_INET6; 562 memcpy(ss, &ssin6, sizeof(ssin6)); 563 ss->ss_len = sizeof(struct sockaddr_in6); 564 } 565 else { 566 if (inet_pton(AF_INET, buf, &ssin.sin_addr) != 1) 567 return 0; 568 ssin.sin_family = AF_INET; 569 memcpy(ss, &ssin, sizeof(ssin)); 570 ss->ss_len = sizeof(struct sockaddr_in); 571 } 572 return 1; 573 } 574 575 static int 576 ascii_load_mda_method(enum action_type *dest, char *buf) 577 { 578 if (strcasecmp(buf, "mbox") == 0) 579 *dest = A_MBOX; 580 else if (strcasecmp(buf, "maildir") == 0) 581 *dest = A_MAILDIR; 582 else if (strcasecmp(buf, "filename") == 0) 583 *dest = A_FILENAME; 584 else if (strcasecmp(buf, "mda") == 0) 585 *dest = A_MDA; 586 else 587 return 0; 588 return 1; 589 } 590 591 static int 592 ascii_load_mailaddr(struct mailaddr *dest, char *buf) 593 { 594 if (! email_to_mailaddr(dest, buf)) 595 return 0; 596 return 1; 597 } 598 599 static int 600 ascii_load_flags(enum delivery_flags *dest, char *buf) 601 { 602 char *flag; 603 604 while ((flag = strsep(&buf, " ,|")) != NULL) { 605 if (strcasecmp(flag, "authenticated") == 0) 606 *dest |= DF_AUTHENTICATED; 607 else if (strcasecmp(flag, "enqueued") == 0) 608 *dest |= DF_ENQUEUED; 609 else if (strcasecmp(flag, "bounce") == 0) 610 *dest |= DF_BOUNCE; 611 else if (strcasecmp(flag, "internal") == 0) 612 *dest |= DF_INTERNAL; 613 else 614 return 0; 615 } 616 return 1; 617 } 618 619 static int 620 ascii_load_mta_relay_flags(u_int8_t *dest, char *buf) 621 { 622 char *flag; 623 624 while ((flag = strsep(&buf, " ,|")) != NULL) { 625 if (strcasecmp(flag, "smtps") == 0) 626 *dest |= F_SMTPS; 627 else if (strcasecmp(flag, "tls") == 0) 628 *dest |= F_STARTTLS; 629 else if (strcasecmp(flag, "auth") == 0) 630 *dest |= F_AUTH; 631 else 632 return 0; 633 } 634 return 1; 635 } 636 637 static int 638 ascii_dump_uint8(u_int8_t src, char *dest, size_t len) 639 { 640 return bsnprintf(dest, len, "%d", src); 641 } 642 643 static int 644 ascii_dump_uint32(u_int32_t src, char *dest, size_t len) 645 { 646 return bsnprintf(dest, len, "%d", src); 647 } 648 649 static int 650 ascii_dump_time(time_t src, char *dest, size_t len) 651 { 652 return bsnprintf(dest, len, "%" PRId64, (int64_t) src); 653 } 654 655 static int 656 ascii_dump_uint32_hex(u_int32_t src, char *dest, size_t len) 657 { 658 return bsnprintf(dest, len, "%08" PRIx32, src); 659 } 660 661 static int 662 ascii_dump_uint64_hex(u_int64_t src, char *dest, size_t len) 663 { 664 return bsnprintf(dest, len, "%016" PRIx64, src); 665 } 666 667 static int 668 ascii_dump_string(char *src, char *dest, size_t len) 669 { 670 return bsnprintf(dest, len, "%s", src); 671 } 672 673 static int 674 ascii_dump_type(enum delivery_type type, char *dest, size_t len) 675 { 676 char *p = NULL; 677 678 switch (type) { 679 case D_MDA: 680 p = "mda"; 681 break; 682 case D_MTA: 683 p = "mta"; 684 break; 685 case D_BOUNCE: 686 p = "bounce"; 687 break; 688 default: 689 return 0; 690 } 691 692 return bsnprintf(dest, len, "%s", p); 693 } 694 695 static int 696 ascii_dump_mda_method(enum action_type type, char *dest, size_t len) 697 { 698 char *p = NULL; 699 700 switch (type) { 701 case A_MAILDIR: 702 p = "maildir"; 703 break; 704 case A_MBOX: 705 p = "mbox"; 706 break; 707 case A_FILENAME: 708 p = "filename"; 709 break; 710 case A_MDA: 711 p = "mda"; 712 break; 713 default: 714 return 0; 715 } 716 return bsnprintf(dest, len, "%s", p); 717 } 718 719 static int 720 ascii_dump_mailaddr(struct mailaddr *addr, char *dest, size_t len) 721 { 722 return bsnprintf(dest, len, "%s@%s", 723 addr->user, addr->domain); 724 } 725 726 static int 727 ascii_dump_mta_relay_port(u_int16_t port, char *buf, size_t len) 728 { 729 return bsnprintf(buf, len, "%d", ntohs(port)); 730 } 731 732 static int 733 ascii_dump_mta_relay_flags(u_int8_t flags, char *buf, size_t len) 734 { 735 size_t cpylen = 0; 736 737 buf[0] = '\0'; 738 if (flags) { 739 if (flags & F_SMTPS) 740 cpylen = strlcat(buf, "smtps", len); 741 if (flags & F_STARTTLS) { 742 if (buf[0] != '\0') 743 cpylen = strlcat(buf, " ", len); 744 cpylen = strlcat(buf, "tls", len); 745 } 746 if (flags & F_AUTH) { 747 if (buf[0] != '\0') 748 cpylen = strlcat(buf, " ", len); 749 cpylen = strlcat(buf, "auth", len); 750 } 751 } 752 753 return cpylen < len ? 1 : 0; 754 } 755 756 static int 757 ascii_dump_flags(enum delivery_flags flags, char *buf, size_t len) 758 { 759 size_t cpylen = 0; 760 761 buf[0] = '\0'; 762 if (flags) { 763 if (flags & DF_AUTHENTICATED) 764 cpylen = strlcat(buf, "authenticated", len); 765 if (flags & DF_ENQUEUED) { 766 if (buf[0] != '\0') 767 cpylen = strlcat(buf, " ", len); 768 cpylen = strlcat(buf, "enqueued", len); 769 } 770 if (flags & DF_BOUNCE) { 771 if (buf[0] != '\0') 772 cpylen = strlcat(buf, " ", len); 773 cpylen = strlcat(buf, "bounce", len); 774 } 775 if (flags & DF_INTERNAL) { 776 if (buf[0] != '\0') 777 cpylen = strlcat(buf, " ", len); 778 cpylen = strlcat(buf, "internal", len); 779 } 780 } 781 782 return cpylen < len ? 1 : 0; 783 } 784