1 /* 2 * Copyright (c) 1998-2007 Sendmail, Inc. and its suppliers. 3 * All rights reserved. 4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 5 * Copyright (c) 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * By using this file, you agree to the terms and conditions set 9 * forth in the LICENSE file which can be found at the top level of 10 * the sendmail distribution. 11 * 12 */ 13 14 #include <sendmail.h> 15 #include "map.h" 16 17 SM_RCSID("@(#)$Id: daemon.c,v 8.678 2007/03/08 00:33:40 ca Exp $") 18 19 #if defined(SOCK_STREAM) || defined(__GNU_LIBRARY__) 20 # define USE_SOCK_STREAM 1 21 #endif /* defined(SOCK_STREAM) || defined(__GNU_LIBRARY__) */ 22 23 #if defined(USE_SOCK_STREAM) 24 # if NETINET || NETINET6 25 # include <arpa/inet.h> 26 # endif /* NETINET || NETINET6 */ 27 # if NAMED_BIND 28 # ifndef NO_DATA 29 # define NO_DATA NO_ADDRESS 30 # endif /* ! NO_DATA */ 31 # endif /* NAMED_BIND */ 32 #endif /* defined(USE_SOCK_STREAM) */ 33 34 #if STARTTLS 35 # include <openssl/rand.h> 36 #endif /* STARTTLS */ 37 38 #include <sm/time.h> 39 40 #if IP_SRCROUTE && NETINET 41 # include <netinet/in_systm.h> 42 # include <netinet/ip.h> 43 # if HAS_IN_H 44 # include <netinet/in.h> 45 # ifndef IPOPTION 46 # define IPOPTION ip_opts 47 # define IP_LIST ip_opts 48 # define IP_DST ip_dst 49 # endif /* ! IPOPTION */ 50 # else /* HAS_IN_H */ 51 # include <netinet/ip_var.h> 52 # ifndef IPOPTION 53 # define IPOPTION ipoption 54 # define IP_LIST ipopt_list 55 # define IP_DST ipopt_dst 56 # endif /* ! IPOPTION */ 57 # endif /* HAS_IN_H */ 58 #endif /* IP_SRCROUTE && NETINET */ 59 60 #include <sm/fdset.h> 61 62 #define DAEMON_C 1 63 #include <daemon.h> 64 65 static void connecttimeout __P((int)); 66 static int opendaemonsocket __P((DAEMON_T *, bool)); 67 static unsigned short setupdaemon __P((SOCKADDR *)); 68 static void getrequests_checkdiskspace __P((ENVELOPE *e)); 69 static void setsockaddroptions __P((char *, DAEMON_T *)); 70 static void printdaemonflags __P((DAEMON_T *)); 71 static int addr_family __P((char *)); 72 static int addrcmp __P((struct hostent *, char *, SOCKADDR *)); 73 static void authtimeout __P((int)); 74 75 /* 76 ** DAEMON.C -- routines to use when running as a daemon. 77 ** 78 ** This entire file is highly dependent on the 4.2 BSD 79 ** interprocess communication primitives. No attempt has 80 ** been made to make this file portable to Version 7, 81 ** Version 6, MPX files, etc. If you should try such a 82 ** thing yourself, I recommend chucking the entire file 83 ** and starting from scratch. Basic semantics are: 84 ** 85 ** getrequests(e) 86 ** Opens a port and initiates a connection. 87 ** Returns in a child. Must set InChannel and 88 ** OutChannel appropriately. 89 ** clrdaemon() 90 ** Close any open files associated with getting 91 ** the connection; this is used when running the queue, 92 ** etc., to avoid having extra file descriptors during 93 ** the queue run and to avoid confusing the network 94 ** code (if it cares). 95 ** makeconnection(host, port, mci, e, enough) 96 ** Make a connection to the named host on the given 97 ** port. Returns zero on success, else an exit status 98 ** describing the error. 99 ** host_map_lookup(map, hbuf, avp, pstat) 100 ** Convert the entry in hbuf into a canonical form. 101 */ 102 103 static int NDaemons = 0; /* actual number of daemons */ 104 105 static time_t NextDiskSpaceCheck = 0; 106 107 /* 108 ** GETREQUESTS -- open mail IPC port and get requests. 109 ** 110 ** Parameters: 111 ** e -- the current envelope. 112 ** 113 ** Returns: 114 ** pointer to flags. 115 ** 116 ** Side Effects: 117 ** Waits until some interesting activity occurs. When 118 ** it does, a child is created to process it, and the 119 ** parent waits for completion. Return from this 120 ** routine is always in the child. The file pointers 121 ** "InChannel" and "OutChannel" should be set to point 122 ** to the communication channel. 123 ** May restart persistent queue runners if they have ended 124 ** for some reason. 125 */ 126 127 BITMAP256 * 128 getrequests(e) 129 ENVELOPE *e; 130 { 131 int t; 132 int idx, curdaemon = -1; 133 int i, olddaemon = 0; 134 #if XDEBUG 135 bool j_has_dot; 136 #endif /* XDEBUG */ 137 char status[MAXLINE]; 138 SOCKADDR sa; 139 SOCKADDR_LEN_T len = sizeof(sa); 140 #if _FFR_QUEUE_RUN_PARANOIA 141 time_t lastrun; 142 #endif /* _FFR_QUEUE_RUN_PARANOIA */ 143 # if NETUNIX 144 extern int ControlSocket; 145 # endif /* NETUNIX */ 146 extern ENVELOPE BlankEnvelope; 147 148 149 /* initialize data for function that generates queue ids */ 150 init_qid_alg(); 151 for (idx = 0; idx < NDaemons; idx++) 152 { 153 Daemons[idx].d_port = setupdaemon(&(Daemons[idx].d_addr)); 154 Daemons[idx].d_firsttime = true; 155 Daemons[idx].d_refuse_connections_until = (time_t) 0; 156 } 157 158 /* 159 ** Try to actually open the connection. 160 */ 161 162 if (tTd(15, 1)) 163 { 164 for (idx = 0; idx < NDaemons; idx++) 165 { 166 sm_dprintf("getrequests: daemon %s: port %d\n", 167 Daemons[idx].d_name, 168 ntohs(Daemons[idx].d_port)); 169 } 170 } 171 172 /* get a socket for the SMTP connection */ 173 for (idx = 0; idx < NDaemons; idx++) 174 Daemons[idx].d_socksize = opendaemonsocket(&Daemons[idx], true); 175 176 if (opencontrolsocket() < 0) 177 sm_syslog(LOG_WARNING, NOQID, 178 "daemon could not open control socket %s: %s", 179 ControlSocketName, sm_errstring(errno)); 180 181 /* If there are any queue runners released reapchild() co-ord's */ 182 (void) sm_signal(SIGCHLD, reapchild); 183 184 /* write the pid to file, command line args to syslog */ 185 log_sendmail_pid(e); 186 187 #if XDEBUG 188 { 189 char jbuf[MAXHOSTNAMELEN]; 190 191 expand("\201j", jbuf, sizeof(jbuf), e); 192 j_has_dot = strchr(jbuf, '.') != NULL; 193 } 194 #endif /* XDEBUG */ 195 196 /* Add parent process as first item */ 197 proc_list_add(CurrentPid, "Sendmail daemon", PROC_DAEMON, 0, -1, NULL); 198 199 if (tTd(15, 1)) 200 { 201 for (idx = 0; idx < NDaemons; idx++) 202 sm_dprintf("getrequests: daemon %s: %d\n", 203 Daemons[idx].d_name, 204 Daemons[idx].d_socket); 205 } 206 207 for (;;) 208 { 209 register pid_t pid; 210 auto SOCKADDR_LEN_T lotherend; 211 bool timedout = false; 212 bool control = false; 213 int save_errno; 214 int pipefd[2]; 215 time_t now; 216 #if STARTTLS 217 long seed; 218 #endif /* STARTTLS */ 219 220 /* see if we are rejecting connections */ 221 (void) sm_blocksignal(SIGALRM); 222 CHECK_RESTART; 223 224 for (idx = 0; idx < NDaemons; idx++) 225 { 226 /* 227 ** XXX do this call outside the loop? 228 ** no: refuse_connections may sleep(). 229 */ 230 231 now = curtime(); 232 if (now < Daemons[idx].d_refuse_connections_until) 233 continue; 234 if (bitnset(D_DISABLE, Daemons[idx].d_flags)) 235 continue; 236 if (refuseconnections(e, idx, curdaemon == idx)) 237 { 238 if (Daemons[idx].d_socket >= 0) 239 { 240 /* close socket so peer fails quickly */ 241 (void) close(Daemons[idx].d_socket); 242 Daemons[idx].d_socket = -1; 243 } 244 245 /* refuse connections for next 15 seconds */ 246 Daemons[idx].d_refuse_connections_until = now + 15; 247 } 248 else if (Daemons[idx].d_socket < 0 || 249 Daemons[idx].d_firsttime) 250 { 251 if (!Daemons[idx].d_firsttime && LogLevel > 8) 252 sm_syslog(LOG_INFO, NOQID, 253 "accepting connections again for daemon %s", 254 Daemons[idx].d_name); 255 256 /* arrange to (re)open the socket if needed */ 257 (void) opendaemonsocket(&Daemons[idx], false); 258 Daemons[idx].d_firsttime = false; 259 } 260 } 261 262 /* May have been sleeping above, check again */ 263 CHECK_RESTART; 264 265 getrequests_checkdiskspace(e); 266 267 #if XDEBUG 268 /* check for disaster */ 269 { 270 char jbuf[MAXHOSTNAMELEN]; 271 272 expand("\201j", jbuf, sizeof(jbuf), e); 273 if (!wordinclass(jbuf, 'w')) 274 { 275 dumpstate("daemon lost $j"); 276 sm_syslog(LOG_ALERT, NOQID, 277 "daemon process doesn't have $j in $=w; see syslog"); 278 abort(); 279 } 280 else if (j_has_dot && strchr(jbuf, '.') == NULL) 281 { 282 dumpstate("daemon $j lost dot"); 283 sm_syslog(LOG_ALERT, NOQID, 284 "daemon process $j lost dot; see syslog"); 285 abort(); 286 } 287 } 288 #endif /* XDEBUG */ 289 290 #if 0 291 /* 292 ** Andrew Sun <asun@ieps-sun.ml.com> claims that this will 293 ** fix the SVr4 problem. But it seems to have gone away, 294 ** so is it worth doing this? 295 */ 296 297 if (DaemonSocket >= 0 && 298 SetNonBlocking(DaemonSocket, false) < 0) 299 log an error here; 300 #endif /* 0 */ 301 (void) sm_releasesignal(SIGALRM); 302 303 for (;;) 304 { 305 bool setproc = false; 306 int highest = -1; 307 fd_set readfds; 308 struct timeval timeout; 309 310 CHECK_RESTART; 311 FD_ZERO(&readfds); 312 for (idx = 0; idx < NDaemons; idx++) 313 { 314 /* wait for a connection */ 315 if (Daemons[idx].d_socket >= 0) 316 { 317 if (!setproc && 318 !bitnset(D_ETRNONLY, 319 Daemons[idx].d_flags)) 320 { 321 sm_setproctitle(true, e, 322 "accepting connections"); 323 setproc = true; 324 } 325 if (Daemons[idx].d_socket > highest) 326 highest = Daemons[idx].d_socket; 327 SM_FD_SET(Daemons[idx].d_socket, 328 &readfds); 329 } 330 } 331 332 #if NETUNIX 333 if (ControlSocket >= 0) 334 { 335 if (ControlSocket > highest) 336 highest = ControlSocket; 337 SM_FD_SET(ControlSocket, &readfds); 338 } 339 #endif /* NETUNIX */ 340 341 timeout.tv_sec = 5; 342 timeout.tv_usec = 0; 343 344 t = select(highest + 1, FDSET_CAST &readfds, 345 NULL, NULL, &timeout); 346 347 /* Did someone signal while waiting? */ 348 CHECK_RESTART; 349 350 curdaemon = -1; 351 if (doqueuerun()) 352 { 353 (void) runqueue(true, false, false, false); 354 #if _FFR_QUEUE_RUN_PARANOIA 355 lastrun = now; 356 #endif /* _FFR_QUEUE_RUN_PARANOIA */ 357 } 358 #if _FFR_QUEUE_RUN_PARANOIA 359 else if (CheckQueueRunners > 0 && QueueIntvl > 0 && 360 lastrun + QueueIntvl + CheckQueueRunners < now) 361 { 362 363 /* 364 ** set lastrun unconditionally to avoid 365 ** calling checkqueuerunner() all the time. 366 ** That's also why we currently ignore the 367 ** result of the function call. 368 */ 369 370 (void) checkqueuerunner(); 371 lastrun = now; 372 } 373 #endif /* _FFR_QUEUE_RUN_PARANOIA */ 374 375 if (t <= 0) 376 { 377 timedout = true; 378 break; 379 } 380 381 control = false; 382 errno = 0; 383 384 /* look "round-robin" for an active socket */ 385 if ((idx = olddaemon + 1) >= NDaemons) 386 idx = 0; 387 for (i = 0; i < NDaemons; i++) 388 { 389 if (Daemons[idx].d_socket >= 0 && 390 SM_FD_ISSET(Daemons[idx].d_socket, 391 &readfds)) 392 { 393 lotherend = Daemons[idx].d_socksize; 394 memset(&RealHostAddr, '\0', 395 sizeof(RealHostAddr)); 396 t = accept(Daemons[idx].d_socket, 397 (struct sockaddr *)&RealHostAddr, 398 &lotherend); 399 400 /* 401 ** If remote side closes before 402 ** accept() finishes, sockaddr 403 ** might not be fully filled in. 404 */ 405 406 if (t >= 0 && 407 (lotherend == 0 || 408 # ifdef BSD4_4_SOCKADDR 409 RealHostAddr.sa.sa_len == 0 || 410 # endif /* BSD4_4_SOCKADDR */ 411 RealHostAddr.sa.sa_family != Daemons[idx].d_addr.sa.sa_family)) 412 { 413 (void) close(t); 414 t = -1; 415 errno = EINVAL; 416 } 417 olddaemon = curdaemon = idx; 418 break; 419 } 420 if (++idx >= NDaemons) 421 idx = 0; 422 } 423 #if NETUNIX 424 if (curdaemon == -1 && ControlSocket >= 0 && 425 SM_FD_ISSET(ControlSocket, &readfds)) 426 { 427 struct sockaddr_un sa_un; 428 429 lotherend = sizeof(sa_un); 430 memset(&sa_un, '\0', sizeof(sa_un)); 431 t = accept(ControlSocket, 432 (struct sockaddr *)&sa_un, 433 &lotherend); 434 435 /* 436 ** If remote side closes before 437 ** accept() finishes, sockaddr 438 ** might not be fully filled in. 439 */ 440 441 if (t >= 0 && 442 (lotherend == 0 || 443 # ifdef BSD4_4_SOCKADDR 444 sa_un.sun_len == 0 || 445 # endif /* BSD4_4_SOCKADDR */ 446 sa_un.sun_family != AF_UNIX)) 447 { 448 (void) close(t); 449 t = -1; 450 errno = EINVAL; 451 } 452 if (t >= 0) 453 control = true; 454 } 455 #else /* NETUNIX */ 456 if (curdaemon == -1) 457 { 458 /* No daemon to service */ 459 continue; 460 } 461 #endif /* NETUNIX */ 462 if (t >= 0 || errno != EINTR) 463 break; 464 } 465 if (timedout) 466 { 467 timedout = false; 468 continue; 469 } 470 save_errno = errno; 471 (void) sm_blocksignal(SIGALRM); 472 if (t < 0) 473 { 474 errno = save_errno; 475 476 /* let's ignore these temporary errors */ 477 if (save_errno == EINTR 478 #ifdef EAGAIN 479 || save_errno == EAGAIN 480 #endif /* EAGAIN */ 481 #ifdef ECONNABORTED 482 || save_errno == ECONNABORTED 483 #endif /* ECONNABORTED */ 484 #ifdef EWOULDBLOCK 485 || save_errno == EWOULDBLOCK 486 #endif /* EWOULDBLOCK */ 487 ) 488 continue; 489 490 syserr("getrequests: accept"); 491 492 if (curdaemon >= 0) 493 { 494 /* arrange to re-open socket next time around */ 495 (void) close(Daemons[curdaemon].d_socket); 496 Daemons[curdaemon].d_socket = -1; 497 #if SO_REUSEADDR_IS_BROKEN 498 /* 499 ** Give time for bound socket to be released. 500 ** This creates a denial-of-service if you can 501 ** force accept() to fail on affected systems. 502 */ 503 504 Daemons[curdaemon].d_refuse_connections_until = 505 curtime() + 15; 506 #endif /* SO_REUSEADDR_IS_BROKEN */ 507 } 508 continue; 509 } 510 511 if (!control) 512 { 513 /* set some daemon related macros */ 514 switch (Daemons[curdaemon].d_addr.sa.sa_family) 515 { 516 case AF_UNSPEC: 517 macdefine(&BlankEnvelope.e_macro, A_PERM, 518 macid("{daemon_family}"), "unspec"); 519 break; 520 #if _FFR_DAEMON_NETUNIX 521 # if NETUNIX 522 case AF_UNIX: 523 macdefine(&BlankEnvelope.e_macro, A_PERM, 524 macid("{daemon_family}"), "local"); 525 break; 526 # endif /* NETUNIX */ 527 #endif /* _FFR_DAEMON_NETUNIX */ 528 #if NETINET 529 case AF_INET: 530 macdefine(&BlankEnvelope.e_macro, A_PERM, 531 macid("{daemon_family}"), "inet"); 532 break; 533 #endif /* NETINET */ 534 #if NETINET6 535 case AF_INET6: 536 macdefine(&BlankEnvelope.e_macro, A_PERM, 537 macid("{daemon_family}"), "inet6"); 538 break; 539 #endif /* NETINET6 */ 540 #if NETISO 541 case AF_ISO: 542 macdefine(&BlankEnvelope.e_macro, A_PERM, 543 macid("{daemon_family}"), "iso"); 544 break; 545 #endif /* NETISO */ 546 #if NETNS 547 case AF_NS: 548 macdefine(&BlankEnvelope.e_macro, A_PERM, 549 macid("{daemon_family}"), "ns"); 550 break; 551 #endif /* NETNS */ 552 #if NETX25 553 case AF_CCITT: 554 macdefine(&BlankEnvelope.e_macro, A_PERM, 555 macid("{daemon_family}"), "x.25"); 556 break; 557 #endif /* NETX25 */ 558 } 559 macdefine(&BlankEnvelope.e_macro, A_PERM, 560 macid("{daemon_name}"), 561 Daemons[curdaemon].d_name); 562 if (Daemons[curdaemon].d_mflags != NULL) 563 macdefine(&BlankEnvelope.e_macro, A_PERM, 564 macid("{daemon_flags}"), 565 Daemons[curdaemon].d_mflags); 566 else 567 macdefine(&BlankEnvelope.e_macro, A_PERM, 568 macid("{daemon_flags}"), ""); 569 } 570 571 /* 572 ** If connection rate is exceeded here, connection shall be 573 ** refused later by a new call after fork() by the 574 ** validate_connection() function. Closing the connection 575 ** at this point violates RFC 2821. 576 ** Do NOT remove this call, its side effects are needed. 577 */ 578 579 connection_rate_check(&RealHostAddr, NULL); 580 581 /* 582 ** Create a subprocess to process the mail. 583 */ 584 585 if (tTd(15, 2)) 586 sm_dprintf("getrequests: forking (fd = %d)\n", t); 587 588 /* 589 ** Advance state of PRNG. 590 ** This is necessary because otherwise all child processes 591 ** will produce the same PRN sequence and hence the selection 592 ** of a queue directory (and other things, e.g., MX selection) 593 ** are not "really" random. 594 */ 595 #if STARTTLS 596 /* XXX get some better "random" data? */ 597 seed = get_random(); 598 RAND_seed((void *) &NextDiskSpaceCheck, 599 sizeof(NextDiskSpaceCheck)); 600 RAND_seed((void *) &now, sizeof(now)); 601 RAND_seed((void *) &seed, sizeof(seed)); 602 #else /* STARTTLS */ 603 (void) get_random(); 604 #endif /* STARTTLS */ 605 606 #if NAMED_BIND 607 /* 608 ** Update MX records for FallbackMX. 609 ** Let's hope this is fast otherwise we screw up the 610 ** response time. 611 */ 612 613 if (FallbackMX != NULL) 614 (void) getfallbackmxrr(FallbackMX); 615 #endif /* NAMED_BIND */ 616 617 if (tTd(93, 100)) 618 { 619 /* don't fork, handle connection in this process */ 620 pid = 0; 621 pipefd[0] = pipefd[1] = -1; 622 } 623 else 624 { 625 /* 626 ** Create a pipe to keep the child from writing to 627 ** the socket until after the parent has closed 628 ** it. Otherwise the parent may hang if the child 629 ** has closed it first. 630 */ 631 632 if (pipe(pipefd) < 0) 633 pipefd[0] = pipefd[1] = -1; 634 635 (void) sm_blocksignal(SIGCHLD); 636 pid = fork(); 637 if (pid < 0) 638 { 639 syserr("daemon: cannot fork"); 640 if (pipefd[0] != -1) 641 { 642 (void) close(pipefd[0]); 643 (void) close(pipefd[1]); 644 } 645 (void) sm_releasesignal(SIGCHLD); 646 (void) sleep(10); 647 (void) close(t); 648 continue; 649 } 650 } 651 652 if (pid == 0) 653 { 654 char *p; 655 SM_FILE_T *inchannel, *outchannel = NULL; 656 657 /* 658 ** CHILD -- return to caller. 659 ** Collect verified idea of sending host. 660 ** Verify calling user id if possible here. 661 */ 662 663 /* Reset global flags */ 664 RestartRequest = NULL; 665 RestartWorkGroup = false; 666 ShutdownRequest = NULL; 667 PendingSignal = 0; 668 CurrentPid = getpid(); 669 close_sendmail_pid(); 670 671 (void) sm_releasesignal(SIGALRM); 672 (void) sm_releasesignal(SIGCHLD); 673 (void) sm_signal(SIGCHLD, SIG_DFL); 674 (void) sm_signal(SIGHUP, SIG_DFL); 675 (void) sm_signal(SIGTERM, intsig); 676 677 /* turn on profiling */ 678 /* SM_PROF(0); */ 679 680 /* 681 ** Initialize exception stack and default exception 682 ** handler for child process. 683 */ 684 685 sm_exc_newthread(fatal_error); 686 687 if (!control) 688 { 689 macdefine(&BlankEnvelope.e_macro, A_TEMP, 690 macid("{daemon_addr}"), 691 anynet_ntoa(&Daemons[curdaemon].d_addr)); 692 (void) sm_snprintf(status, sizeof(status), "%d", 693 ntohs(Daemons[curdaemon].d_port)); 694 macdefine(&BlankEnvelope.e_macro, A_TEMP, 695 macid("{daemon_port}"), status); 696 } 697 698 for (idx = 0; idx < NDaemons; idx++) 699 { 700 if (Daemons[idx].d_socket >= 0) 701 (void) close(Daemons[idx].d_socket); 702 Daemons[idx].d_socket = -1; 703 } 704 clrcontrol(); 705 706 /* Avoid SMTP daemon actions if control command */ 707 if (control) 708 { 709 /* Add control socket process */ 710 proc_list_add(CurrentPid, 711 "console socket child", 712 PROC_CONTROL_CHILD, 0, -1, NULL); 713 } 714 else 715 { 716 proc_list_clear(); 717 718 /* clean up background delivery children */ 719 (void) sm_signal(SIGCHLD, reapchild); 720 721 /* Add parent process as first child item */ 722 proc_list_add(CurrentPid, "daemon child", 723 PROC_DAEMON_CHILD, 0, -1, NULL); 724 /* don't schedule queue runs if ETRN */ 725 QueueIntvl = 0; 726 727 /* 728 ** Hack: override global variables if 729 ** the corresponding DaemonPortOption 730 ** is set. 731 */ 732 #if _FFR_SS_PER_DAEMON 733 if (Daemons[curdaemon].d_supersafe != 734 DPO_NOTSET) 735 SuperSafe = Daemons[curdaemon]. 736 d_supersafe; 737 #endif /* _FFR_SS_PER_DAEMON */ 738 if (Daemons[curdaemon].d_dm != DM_NOTSET) 739 set_delivery_mode( 740 Daemons[curdaemon].d_dm, e); 741 742 if (Daemons[curdaemon].d_refuseLA != 743 DPO_NOTSET) 744 RefuseLA = Daemons[curdaemon]. 745 d_refuseLA; 746 if (Daemons[curdaemon].d_queueLA != DPO_NOTSET) 747 QueueLA = Daemons[curdaemon].d_queueLA; 748 if (Daemons[curdaemon].d_delayLA != DPO_NOTSET) 749 DelayLA = Daemons[curdaemon].d_delayLA; 750 if (Daemons[curdaemon].d_maxchildren != 751 DPO_NOTSET) 752 MaxChildren = Daemons[curdaemon]. 753 d_maxchildren; 754 755 sm_setproctitle(true, e, "startup with %s", 756 anynet_ntoa(&RealHostAddr)); 757 } 758 759 if (pipefd[0] != -1) 760 { 761 auto char c; 762 763 /* 764 ** Wait for the parent to close the write end 765 ** of the pipe, which we will see as an EOF. 766 ** This guarantees that we won't write to the 767 ** socket until after the parent has closed 768 ** the pipe. 769 */ 770 771 /* close the write end of the pipe */ 772 (void) close(pipefd[1]); 773 774 /* we shouldn't be interrupted, but ... */ 775 while (read(pipefd[0], &c, 1) < 0 && 776 errno == EINTR) 777 continue; 778 (void) close(pipefd[0]); 779 } 780 781 /* control socket processing */ 782 if (control) 783 { 784 control_command(t, e); 785 /* NOTREACHED */ 786 exit(EX_SOFTWARE); 787 } 788 789 /* determine host name */ 790 p = hostnamebyanyaddr(&RealHostAddr); 791 if (strlen(p) > MAXNAME) /* XXX - 1 ? */ 792 p[MAXNAME] = '\0'; 793 RealHostName = newstr(p); 794 if (RealHostName[0] == '[') 795 { 796 macdefine(&BlankEnvelope.e_macro, A_PERM, 797 macid("{client_resolve}"), 798 h_errno == TRY_AGAIN ? "TEMP" : "FAIL"); 799 } 800 else 801 { 802 macdefine(&BlankEnvelope.e_macro, A_PERM, 803 macid("{client_resolve}"), "OK"); 804 } 805 sm_setproctitle(true, e, "startup with %s", p); 806 markstats(e, NULL, STATS_CONNECT); 807 808 if ((inchannel = sm_io_open(SmFtStdiofd, 809 SM_TIME_DEFAULT, 810 (void *) &t, 811 SM_IO_RDONLY_B, 812 NULL)) == NULL || 813 (t = dup(t)) < 0 || 814 (outchannel = sm_io_open(SmFtStdiofd, 815 SM_TIME_DEFAULT, 816 (void *) &t, 817 SM_IO_WRONLY_B, 818 NULL)) == NULL) 819 { 820 syserr("cannot open SMTP server channel, fd=%d", 821 t); 822 finis(false, true, EX_OK); 823 } 824 sm_io_automode(inchannel, outchannel); 825 826 InChannel = inchannel; 827 OutChannel = outchannel; 828 DisConnected = false; 829 830 #if XLA 831 if (!xla_host_ok(RealHostName)) 832 { 833 message("421 4.4.5 Too many SMTP sessions for this host"); 834 finis(false, true, EX_OK); 835 } 836 #endif /* XLA */ 837 /* find out name for interface of connection */ 838 if (getsockname(sm_io_getinfo(InChannel, SM_IO_WHAT_FD, 839 NULL), &sa.sa, &len) == 0) 840 { 841 p = hostnamebyanyaddr(&sa); 842 if (tTd(15, 9)) 843 sm_dprintf("getreq: got name %s\n", p); 844 macdefine(&BlankEnvelope.e_macro, A_TEMP, 845 macid("{if_name}"), p); 846 847 /* 848 ** Do this only if it is not the loopback 849 ** interface. 850 */ 851 852 if (!isloopback(sa)) 853 { 854 char *addr; 855 char family[5]; 856 857 addr = anynet_ntoa(&sa); 858 (void) sm_snprintf(family, 859 sizeof(family), 860 "%d", sa.sa.sa_family); 861 macdefine(&BlankEnvelope.e_macro, 862 A_TEMP, 863 macid("{if_addr}"), addr); 864 macdefine(&BlankEnvelope.e_macro, 865 A_TEMP, 866 macid("{if_family}"), family); 867 if (tTd(15, 7)) 868 sm_dprintf("getreq: got addr %s and family %s\n", 869 addr, family); 870 } 871 else 872 { 873 macdefine(&BlankEnvelope.e_macro, 874 A_PERM, 875 macid("{if_addr}"), NULL); 876 macdefine(&BlankEnvelope.e_macro, 877 A_PERM, 878 macid("{if_family}"), NULL); 879 } 880 } 881 else 882 { 883 if (tTd(15, 7)) 884 sm_dprintf("getreq: getsockname failed\n"); 885 macdefine(&BlankEnvelope.e_macro, A_PERM, 886 macid("{if_name}"), NULL); 887 macdefine(&BlankEnvelope.e_macro, A_PERM, 888 macid("{if_addr}"), NULL); 889 macdefine(&BlankEnvelope.e_macro, A_PERM, 890 macid("{if_family}"), NULL); 891 } 892 break; 893 } 894 895 /* parent -- keep track of children */ 896 if (control) 897 { 898 (void) sm_snprintf(status, sizeof(status), 899 "control socket server child"); 900 proc_list_add(pid, status, PROC_CONTROL, 0, -1, NULL); 901 } 902 else 903 { 904 (void) sm_snprintf(status, sizeof(status), 905 "SMTP server child for %s", 906 anynet_ntoa(&RealHostAddr)); 907 proc_list_add(pid, status, PROC_DAEMON, 0, -1, 908 &RealHostAddr); 909 } 910 (void) sm_releasesignal(SIGCHLD); 911 912 /* close the read end of the synchronization pipe */ 913 if (pipefd[0] != -1) 914 { 915 (void) close(pipefd[0]); 916 pipefd[0] = -1; 917 } 918 919 /* close the port so that others will hang (for a while) */ 920 (void) close(t); 921 922 /* release the child by closing the read end of the sync pipe */ 923 if (pipefd[1] != -1) 924 { 925 (void) close(pipefd[1]); 926 pipefd[1] = -1; 927 } 928 } 929 if (tTd(15, 2)) 930 sm_dprintf("getreq: returning\n"); 931 932 #if MILTER 933 /* set the filters for this daemon */ 934 if (Daemons[curdaemon].d_inputfilterlist != NULL) 935 { 936 for (i = 0; 937 (i < MAXFILTERS && 938 Daemons[curdaemon].d_inputfilters[i] != NULL); 939 i++) 940 { 941 InputFilters[i] = Daemons[curdaemon].d_inputfilters[i]; 942 } 943 if (i < MAXFILTERS) 944 InputFilters[i] = NULL; 945 } 946 #endif /* MILTER */ 947 return &Daemons[curdaemon].d_flags; 948 } 949 950 /* 951 ** GETREQUESTS_CHECKDISKSPACE -- check available diskspace. 952 ** 953 ** Parameters: 954 ** e -- envelope. 955 ** 956 ** Returns: 957 ** none. 958 ** 959 ** Side Effects: 960 ** Modifies Daemon flags (D_ETRNONLY) if not enough disk space. 961 */ 962 963 static void 964 getrequests_checkdiskspace(e) 965 ENVELOPE *e; 966 { 967 bool logged = false; 968 int idx; 969 time_t now; 970 971 now = curtime(); 972 if (now < NextDiskSpaceCheck) 973 return; 974 975 /* Check if there is available disk space in all queue groups. */ 976 if (!enoughdiskspace(0, NULL)) 977 { 978 for (idx = 0; idx < NDaemons; ++idx) 979 { 980 if (bitnset(D_ETRNONLY, Daemons[idx].d_flags)) 981 continue; 982 983 /* log only if not logged before */ 984 if (!logged) 985 { 986 if (LogLevel > 8) 987 sm_syslog(LOG_INFO, NOQID, 988 "rejecting new messages: min free: %ld", 989 MinBlocksFree); 990 sm_setproctitle(true, e, 991 "rejecting new messages: min free: %ld", 992 MinBlocksFree); 993 logged = true; 994 } 995 setbitn(D_ETRNONLY, Daemons[idx].d_flags); 996 } 997 } 998 else 999 { 1000 for (idx = 0; idx < NDaemons; ++idx) 1001 { 1002 if (!bitnset(D_ETRNONLY, Daemons[idx].d_flags)) 1003 continue; 1004 1005 /* log only if not logged before */ 1006 if (!logged) 1007 { 1008 if (LogLevel > 8) 1009 sm_syslog(LOG_INFO, NOQID, 1010 "accepting new messages (again)"); 1011 logged = true; 1012 } 1013 1014 /* title will be set later */ 1015 clrbitn(D_ETRNONLY, Daemons[idx].d_flags); 1016 } 1017 } 1018 1019 /* only check disk space once a minute */ 1020 NextDiskSpaceCheck = now + 60; 1021 } 1022 1023 /* 1024 ** OPENDAEMONSOCKET -- open SMTP socket 1025 ** 1026 ** Deals with setting all appropriate options. 1027 ** 1028 ** Parameters: 1029 ** d -- the structure for the daemon to open. 1030 ** firsttime -- set if this is the initial open. 1031 ** 1032 ** Returns: 1033 ** Size in bytes of the daemon socket addr. 1034 ** 1035 ** Side Effects: 1036 ** Leaves DaemonSocket set to the open socket. 1037 ** Exits if the socket cannot be created. 1038 */ 1039 1040 #define MAXOPENTRIES 10 /* maximum number of tries to open connection */ 1041 1042 static int 1043 opendaemonsocket(d, firsttime) 1044 DAEMON_T *d; 1045 bool firsttime; 1046 { 1047 int on = 1; 1048 int fdflags; 1049 SOCKADDR_LEN_T socksize = 0; 1050 int ntries = 0; 1051 int save_errno; 1052 1053 if (tTd(15, 2)) 1054 sm_dprintf("opendaemonsocket(%s)\n", d->d_name); 1055 1056 do 1057 { 1058 if (ntries > 0) 1059 (void) sleep(5); 1060 if (firsttime || d->d_socket < 0) 1061 { 1062 #if _FFR_DAEMON_NETUNIX 1063 # if NETUNIX 1064 if (d->d_addr.sa.sa_family == AF_UNIX) 1065 { 1066 int rval; 1067 long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_ROOTOK|SFF_EXECOK|SFF_CREAT; 1068 1069 /* if not safe, don't use it */ 1070 rval = safefile(d->d_addr.sunix.sun_path, 1071 RunAsUid, RunAsGid, 1072 RunAsUserName, sff, 1073 S_IRUSR|S_IWUSR, NULL); 1074 if (rval != 0) 1075 { 1076 save_errno = errno; 1077 syserr("opendaemonsocket: daemon %s: unsafe domain socket %s", 1078 d->d_name, 1079 d->d_addr.sunix.sun_path); 1080 goto fail; 1081 } 1082 1083 /* Don't try to overtake an existing socket */ 1084 (void) unlink(d->d_addr.sunix.sun_path); 1085 } 1086 # endif /* NETUNIX */ 1087 #endif /* _FFR_DOMAIN_NETUNIX */ 1088 d->d_socket = socket(d->d_addr.sa.sa_family, 1089 SOCK_STREAM, 0); 1090 if (d->d_socket < 0) 1091 { 1092 save_errno = errno; 1093 syserr("opendaemonsocket: daemon %s: can't create server SMTP socket", 1094 d->d_name); 1095 fail: 1096 if (bitnset(D_OPTIONAL, d->d_flags) && 1097 (!transienterror(save_errno) || 1098 ntries >= MAXOPENTRIES - 1)) 1099 { 1100 syserr("opendaemonsocket: daemon %s: optional socket disabled", 1101 d->d_name); 1102 setbitn(D_DISABLE, d->d_flags); 1103 d->d_socket = -1; 1104 return -1; 1105 } 1106 severe: 1107 if (LogLevel > 0) 1108 sm_syslog(LOG_ALERT, NOQID, 1109 "daemon %s: problem creating SMTP socket", 1110 d->d_name); 1111 d->d_socket = -1; 1112 continue; 1113 } 1114 1115 if (SM_FD_SETSIZE > 0 && d->d_socket >= SM_FD_SETSIZE) 1116 { 1117 save_errno = EINVAL; 1118 syserr("opendaemonsocket: daemon %s: server SMTP socket (%d) too large", 1119 d->d_name, d->d_socket); 1120 goto fail; 1121 } 1122 1123 /* turn on network debugging? */ 1124 if (tTd(15, 101)) 1125 (void) setsockopt(d->d_socket, SOL_SOCKET, 1126 SO_DEBUG, (char *)&on, 1127 sizeof(on)); 1128 1129 (void) setsockopt(d->d_socket, SOL_SOCKET, 1130 SO_REUSEADDR, (char *)&on, sizeof(on)); 1131 (void) setsockopt(d->d_socket, SOL_SOCKET, 1132 SO_KEEPALIVE, (char *)&on, sizeof(on)); 1133 1134 #ifdef SO_RCVBUF 1135 if (d->d_tcprcvbufsize > 0) 1136 { 1137 if (setsockopt(d->d_socket, SOL_SOCKET, 1138 SO_RCVBUF, 1139 (char *) &d->d_tcprcvbufsize, 1140 sizeof(d->d_tcprcvbufsize)) < 0) 1141 syserr("opendaemonsocket: daemon %s: setsockopt(SO_RCVBUF)", d->d_name); 1142 } 1143 #endif /* SO_RCVBUF */ 1144 #ifdef SO_SNDBUF 1145 if (d->d_tcpsndbufsize > 0) 1146 { 1147 if (setsockopt(d->d_socket, SOL_SOCKET, 1148 SO_SNDBUF, 1149 (char *) &d->d_tcpsndbufsize, 1150 sizeof(d->d_tcpsndbufsize)) < 0) 1151 syserr("opendaemonsocket: daemon %s: setsockopt(SO_SNDBUF)", d->d_name); 1152 } 1153 #endif /* SO_SNDBUF */ 1154 1155 if ((fdflags = fcntl(d->d_socket, F_GETFD, 0)) == -1 || 1156 fcntl(d->d_socket, F_SETFD, 1157 fdflags | FD_CLOEXEC) == -1) 1158 { 1159 save_errno = errno; 1160 syserr("opendaemonsocket: daemon %s: failed to %s close-on-exec flag: %s", 1161 d->d_name, 1162 fdflags == -1 ? "get" : "set", 1163 sm_errstring(save_errno)); 1164 (void) close(d->d_socket); 1165 goto severe; 1166 } 1167 1168 switch (d->d_addr.sa.sa_family) 1169 { 1170 #if _FFR_DAEMON_NETUNIX 1171 # ifdef NETUNIX 1172 case AF_UNIX: 1173 socksize = sizeof(d->d_addr.sunix); 1174 break; 1175 # endif /* NETUNIX */ 1176 #endif /* _FFR_DAEMON_NETUNIX */ 1177 #if NETINET 1178 case AF_INET: 1179 socksize = sizeof(d->d_addr.sin); 1180 break; 1181 #endif /* NETINET */ 1182 1183 #if NETINET6 1184 case AF_INET6: 1185 socksize = sizeof(d->d_addr.sin6); 1186 break; 1187 #endif /* NETINET6 */ 1188 1189 #if NETISO 1190 case AF_ISO: 1191 socksize = sizeof(d->d_addr.siso); 1192 break; 1193 #endif /* NETISO */ 1194 1195 default: 1196 socksize = sizeof(d->d_addr); 1197 break; 1198 } 1199 1200 if (bind(d->d_socket, &d->d_addr.sa, socksize) < 0) 1201 { 1202 /* probably another daemon already */ 1203 save_errno = errno; 1204 syserr("opendaemonsocket: daemon %s: cannot bind", 1205 d->d_name); 1206 (void) close(d->d_socket); 1207 goto fail; 1208 } 1209 } 1210 if (!firsttime && 1211 listen(d->d_socket, d->d_listenqueue) < 0) 1212 { 1213 save_errno = errno; 1214 syserr("opendaemonsocket: daemon %s: cannot listen", 1215 d->d_name); 1216 (void) close(d->d_socket); 1217 goto severe; 1218 } 1219 return socksize; 1220 } while (ntries++ < MAXOPENTRIES && transienterror(save_errno)); 1221 syserr("!opendaemonsocket: daemon %s: server SMTP socket wedged: exiting", 1222 d->d_name); 1223 /* NOTREACHED */ 1224 return -1; /* avoid compiler warning on IRIX */ 1225 } 1226 /* 1227 ** SETUPDAEMON -- setup socket for daemon 1228 ** 1229 ** Parameters: 1230 ** daemonaddr -- socket for daemon 1231 ** 1232 ** Returns: 1233 ** port number on which daemon should run 1234 ** 1235 */ 1236 1237 static unsigned short 1238 setupdaemon(daemonaddr) 1239 SOCKADDR *daemonaddr; 1240 { 1241 unsigned short port; 1242 1243 /* 1244 ** Set up the address for the mailer. 1245 */ 1246 1247 if (daemonaddr->sa.sa_family == AF_UNSPEC) 1248 { 1249 memset(daemonaddr, '\0', sizeof(*daemonaddr)); 1250 #if NETINET 1251 daemonaddr->sa.sa_family = AF_INET; 1252 #endif /* NETINET */ 1253 } 1254 1255 switch (daemonaddr->sa.sa_family) 1256 { 1257 #if NETINET 1258 case AF_INET: 1259 if (daemonaddr->sin.sin_addr.s_addr == 0) 1260 daemonaddr->sin.sin_addr.s_addr = INADDR_ANY; 1261 port = daemonaddr->sin.sin_port; 1262 break; 1263 #endif /* NETINET */ 1264 1265 #if NETINET6 1266 case AF_INET6: 1267 if (IN6_IS_ADDR_UNSPECIFIED(&daemonaddr->sin6.sin6_addr)) 1268 daemonaddr->sin6.sin6_addr = in6addr_any; 1269 port = daemonaddr->sin6.sin6_port; 1270 break; 1271 #endif /* NETINET6 */ 1272 1273 default: 1274 /* unknown protocol */ 1275 port = 0; 1276 break; 1277 } 1278 if (port == 0) 1279 { 1280 #ifdef NO_GETSERVBYNAME 1281 port = htons(25); 1282 #else /* NO_GETSERVBYNAME */ 1283 { 1284 register struct servent *sp; 1285 1286 sp = getservbyname("smtp", "tcp"); 1287 if (sp == NULL) 1288 { 1289 syserr("554 5.3.5 service \"smtp\" unknown"); 1290 port = htons(25); 1291 } 1292 else 1293 port = sp->s_port; 1294 } 1295 #endif /* NO_GETSERVBYNAME */ 1296 } 1297 1298 switch (daemonaddr->sa.sa_family) 1299 { 1300 #if NETINET 1301 case AF_INET: 1302 daemonaddr->sin.sin_port = port; 1303 break; 1304 #endif /* NETINET */ 1305 1306 #if NETINET6 1307 case AF_INET6: 1308 daemonaddr->sin6.sin6_port = port; 1309 break; 1310 #endif /* NETINET6 */ 1311 1312 default: 1313 /* unknown protocol */ 1314 break; 1315 } 1316 return port; 1317 } 1318 /* 1319 ** CLRDAEMON -- reset the daemon connection 1320 ** 1321 ** Parameters: 1322 ** none. 1323 ** 1324 ** Returns: 1325 ** none. 1326 ** 1327 ** Side Effects: 1328 ** releases any resources used by the passive daemon. 1329 */ 1330 1331 void 1332 clrdaemon() 1333 { 1334 int i; 1335 1336 for (i = 0; i < NDaemons; i++) 1337 { 1338 if (Daemons[i].d_socket >= 0) 1339 (void) close(Daemons[i].d_socket); 1340 Daemons[i].d_socket = -1; 1341 } 1342 } 1343 1344 /* 1345 ** GETMODIFIERS -- get modifier flags 1346 ** 1347 ** Parameters: 1348 ** v -- the modifiers (input text line). 1349 ** modifiers -- pointer to flag field to represent modifiers. 1350 ** 1351 ** Returns: 1352 ** (xallocat()ed) string representation of modifiers. 1353 ** 1354 ** Side Effects: 1355 ** fills in modifiers. 1356 */ 1357 1358 char * 1359 getmodifiers(v, modifiers) 1360 char *v; 1361 BITMAP256 modifiers; 1362 { 1363 int l; 1364 char *h, *f, *flags; 1365 1366 /* maximum length of flags: upper case Option -> "OO " */ 1367 l = 3 * strlen(v) + 3; 1368 1369 /* is someone joking? */ 1370 if (l < 0 || l > 256) 1371 { 1372 if (LogLevel > 2) 1373 sm_syslog(LOG_ERR, NOQID, 1374 "getmodifiers too long, ignored"); 1375 return NULL; 1376 } 1377 flags = xalloc(l); 1378 f = flags; 1379 clrbitmap(modifiers); 1380 for (h = v; *h != '\0'; h++) 1381 { 1382 if (isascii(*h) && !isspace(*h) && isprint(*h)) 1383 { 1384 setbitn(*h, modifiers); 1385 if (flags != f) 1386 *flags++ = ' '; 1387 *flags++ = *h; 1388 if (isupper(*h)) 1389 *flags++ = *h; 1390 } 1391 } 1392 *flags++ = '\0'; 1393 return f; 1394 } 1395 1396 /* 1397 ** CHKDAEMONMODIFIERS -- check whether all daemons have set a flag. 1398 ** 1399 ** Parameters: 1400 ** flag -- the flag to test. 1401 ** 1402 ** Returns: 1403 ** true iff all daemons have set flag. 1404 */ 1405 1406 bool 1407 chkdaemonmodifiers(flag) 1408 int flag; 1409 { 1410 int i; 1411 1412 for (i = 0; i < NDaemons; i++) 1413 if (!bitnset((char) flag, Daemons[i].d_flags)) 1414 return false; 1415 return true; 1416 } 1417 1418 /* 1419 ** SETSOCKADDROPTIONS -- set options for SOCKADDR (daemon or client) 1420 ** 1421 ** Parameters: 1422 ** p -- the options line. 1423 ** d -- the daemon structure to fill in. 1424 ** 1425 ** Returns: 1426 ** none. 1427 */ 1428 1429 static void 1430 setsockaddroptions(p, d) 1431 char *p; 1432 DAEMON_T *d; 1433 { 1434 #if NETISO 1435 short portno; 1436 #endif /* NETISO */ 1437 char *port = NULL; 1438 char *addr = NULL; 1439 1440 #if NETINET 1441 if (d->d_addr.sa.sa_family == AF_UNSPEC) 1442 d->d_addr.sa.sa_family = AF_INET; 1443 #endif /* NETINET */ 1444 #if _FFR_SS_PER_DAEMON 1445 d->d_supersafe = DPO_NOTSET; 1446 #endif /* _FFR_SS_PER_DAEMON */ 1447 d->d_dm = DM_NOTSET; 1448 d->d_refuseLA = DPO_NOTSET; 1449 d->d_queueLA = DPO_NOTSET; 1450 d->d_delayLA = DPO_NOTSET; 1451 d->d_maxchildren = DPO_NOTSET; 1452 1453 while (p != NULL) 1454 { 1455 register char *f; 1456 register char *v; 1457 1458 while (isascii(*p) && isspace(*p)) 1459 p++; 1460 if (*p == '\0') 1461 break; 1462 f = p; 1463 p = strchr(p, ','); 1464 if (p != NULL) 1465 *p++ = '\0'; 1466 v = strchr(f, '='); 1467 if (v == NULL) 1468 continue; 1469 while (isascii(*++v) && isspace(*v)) 1470 continue; 1471 1472 switch (*f) 1473 { 1474 case 'A': /* address */ 1475 #if !_FFR_DPO_CS 1476 case 'a': 1477 #endif /* !_FFR_DPO_CS */ 1478 addr = v; 1479 break; 1480 1481 case 'c': 1482 d->d_maxchildren = atoi(v); 1483 break; 1484 1485 case 'D': /* DeliveryMode */ 1486 switch (*v) 1487 { 1488 case SM_QUEUE: 1489 case SM_DEFER: 1490 case SM_DELIVER: 1491 case SM_FORK: 1492 d->d_dm = *v; 1493 break; 1494 default: 1495 syserr("554 5.3.5 Unknown delivery mode %c", 1496 *v); 1497 break; 1498 } 1499 break; 1500 1501 case 'd': /* delayLA */ 1502 d->d_delayLA = atoi(v); 1503 break; 1504 1505 case 'F': /* address family */ 1506 #if !_FFR_DPO_CS 1507 case 'f': 1508 #endif /* !_FFR_DPO_CS */ 1509 if (isascii(*v) && isdigit(*v)) 1510 d->d_addr.sa.sa_family = atoi(v); 1511 #if _FFR_DAEMON_NETUNIX 1512 # ifdef NETUNIX 1513 else if (sm_strcasecmp(v, "unix") == 0 || 1514 sm_strcasecmp(v, "local") == 0) 1515 d->d_addr.sa.sa_family = AF_UNIX; 1516 # endif /* NETUNIX */ 1517 #endif /* _FFR_DAEMON_NETUNIX */ 1518 #if NETINET 1519 else if (sm_strcasecmp(v, "inet") == 0) 1520 d->d_addr.sa.sa_family = AF_INET; 1521 #endif /* NETINET */ 1522 #if NETINET6 1523 else if (sm_strcasecmp(v, "inet6") == 0) 1524 d->d_addr.sa.sa_family = AF_INET6; 1525 #endif /* NETINET6 */ 1526 #if NETISO 1527 else if (sm_strcasecmp(v, "iso") == 0) 1528 d->d_addr.sa.sa_family = AF_ISO; 1529 #endif /* NETISO */ 1530 #if NETNS 1531 else if (sm_strcasecmp(v, "ns") == 0) 1532 d->d_addr.sa.sa_family = AF_NS; 1533 #endif /* NETNS */ 1534 #if NETX25 1535 else if (sm_strcasecmp(v, "x.25") == 0) 1536 d->d_addr.sa.sa_family = AF_CCITT; 1537 #endif /* NETX25 */ 1538 else 1539 syserr("554 5.3.5 Unknown address family %s in Family=option", 1540 v); 1541 break; 1542 1543 #if MILTER 1544 case 'I': 1545 # if !_FFR_DPO_CS 1546 case 'i': 1547 # endif /* !_FFR_DPO_CS */ 1548 d->d_inputfilterlist = v; 1549 break; 1550 #endif /* MILTER */ 1551 1552 case 'L': /* listen queue size */ 1553 #if !_FFR_DPO_CS 1554 case 'l': 1555 #endif /* !_FFR_DPO_CS */ 1556 d->d_listenqueue = atoi(v); 1557 break; 1558 1559 case 'M': /* modifiers (flags) */ 1560 #if !_FFR_DPO_CS 1561 case 'm': 1562 #endif /* !_FFR_DPO_CS */ 1563 d->d_mflags = getmodifiers(v, d->d_flags); 1564 break; 1565 1566 case 'N': /* name */ 1567 #if !_FFR_DPO_CS 1568 case 'n': 1569 #endif /* !_FFR_DPO_CS */ 1570 d->d_name = v; 1571 break; 1572 1573 case 'P': /* port */ 1574 #if !_FFR_DPO_CS 1575 case 'p': 1576 #endif /* !_FFR_DPO_CS */ 1577 port = v; 1578 break; 1579 1580 case 'q': 1581 d->d_queueLA = atoi(v); 1582 break; 1583 1584 case 'R': /* receive buffer size */ 1585 d->d_tcprcvbufsize = atoi(v); 1586 break; 1587 1588 case 'r': 1589 d->d_refuseLA = atoi(v); 1590 break; 1591 1592 case 'S': /* send buffer size */ 1593 #if !_FFR_DPO_CS 1594 case 's': 1595 #endif /* !_FFR_DPO_CS */ 1596 d->d_tcpsndbufsize = atoi(v); 1597 break; 1598 1599 #if _FFR_SS_PER_DAEMON 1600 case 'T': /* SuperSafe */ 1601 if (tolower(*v) == 'i') 1602 d->d_supersafe = SAFE_INTERACTIVE; 1603 else if (tolower(*v) == 'p') 1604 # if MILTER 1605 d->d_supersafe = SAFE_REALLY_POSTMILTER; 1606 # else /* MILTER */ 1607 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 1608 "Warning: SuperSafe=PostMilter requires Milter support (-DMILTER)\n"); 1609 # endif /* MILTER */ 1610 else 1611 d->d_supersafe = atobool(v) ? SAFE_REALLY 1612 : SAFE_NO; 1613 break; 1614 #endif /* _FFR_SS_PER_DAEMON */ 1615 1616 default: 1617 syserr("554 5.3.5 PortOptions parameter \"%s\" unknown", 1618 f); 1619 } 1620 } 1621 1622 /* Check addr and port after finding family */ 1623 if (addr != NULL) 1624 { 1625 switch (d->d_addr.sa.sa_family) 1626 { 1627 #if _FFR_DAEMON_NETUNIX 1628 # if NETUNIX 1629 case AF_UNIX: 1630 if (strlen(addr) >= sizeof(d->d_addr.sunix.sun_path)) 1631 { 1632 errno = ENAMETOOLONG; 1633 syserr("setsockaddroptions: domain socket name too long: %s > %d", 1634 addr, sizeof(d->d_addr.sunix.sun_path)); 1635 break; 1636 } 1637 1638 /* file safety check done in opendaemonsocket() */ 1639 (void) memset(&d->d_addr.sunix.sun_path, '\0', 1640 sizeof(d->d_addr.sunix.sun_path)); 1641 (void) sm_strlcpy((char *)&d->d_addr.sunix.sun_path, 1642 addr, 1643 sizeof(d->d_addr.sunix.sun_path)); 1644 break; 1645 # endif /* NETUNIX */ 1646 #endif /* _FFR_DAEMON_NETUNIX */ 1647 #if NETINET 1648 case AF_INET: 1649 if (!isascii(*addr) || !isdigit(*addr) || 1650 ((d->d_addr.sin.sin_addr.s_addr = inet_addr(addr)) 1651 == INADDR_NONE)) 1652 { 1653 register struct hostent *hp; 1654 1655 hp = sm_gethostbyname(addr, AF_INET); 1656 if (hp == NULL) 1657 syserr("554 5.3.0 host \"%s\" unknown", 1658 addr); 1659 else 1660 { 1661 while (*(hp->h_addr_list) != NULL && 1662 hp->h_addrtype != AF_INET) 1663 hp->h_addr_list++; 1664 if (*(hp->h_addr_list) == NULL) 1665 syserr("554 5.3.0 host \"%s\" unknown", 1666 addr); 1667 else 1668 memmove(&d->d_addr.sin.sin_addr, 1669 *(hp->h_addr_list), 1670 INADDRSZ); 1671 # if NETINET6 1672 freehostent(hp); 1673 hp = NULL; 1674 # endif /* NETINET6 */ 1675 } 1676 } 1677 break; 1678 #endif /* NETINET */ 1679 1680 #if NETINET6 1681 case AF_INET6: 1682 if (anynet_pton(AF_INET6, addr, 1683 &d->d_addr.sin6.sin6_addr) != 1) 1684 { 1685 register struct hostent *hp; 1686 1687 hp = sm_gethostbyname(addr, AF_INET6); 1688 if (hp == NULL) 1689 syserr("554 5.3.0 host \"%s\" unknown", 1690 addr); 1691 else 1692 { 1693 while (*(hp->h_addr_list) != NULL && 1694 hp->h_addrtype != AF_INET6) 1695 hp->h_addr_list++; 1696 if (*(hp->h_addr_list) == NULL) 1697 syserr("554 5.3.0 host \"%s\" unknown", 1698 addr); 1699 else 1700 memmove(&d->d_addr.sin6.sin6_addr, 1701 *(hp->h_addr_list), 1702 IN6ADDRSZ); 1703 freehostent(hp); 1704 hp = NULL; 1705 } 1706 } 1707 break; 1708 #endif /* NETINET6 */ 1709 1710 default: 1711 syserr("554 5.3.5 address= option unsupported for family %d", 1712 d->d_addr.sa.sa_family); 1713 break; 1714 } 1715 } 1716 1717 if (port != NULL) 1718 { 1719 switch (d->d_addr.sa.sa_family) 1720 { 1721 #if NETINET 1722 case AF_INET: 1723 if (isascii(*port) && isdigit(*port)) 1724 d->d_addr.sin.sin_port = htons((unsigned short) 1725 atoi((const char *) port)); 1726 else 1727 { 1728 # ifdef NO_GETSERVBYNAME 1729 syserr("554 5.3.5 invalid port number: %s", 1730 port); 1731 # else /* NO_GETSERVBYNAME */ 1732 register struct servent *sp; 1733 1734 sp = getservbyname(port, "tcp"); 1735 if (sp == NULL) 1736 syserr("554 5.3.5 service \"%s\" unknown", 1737 port); 1738 else 1739 d->d_addr.sin.sin_port = sp->s_port; 1740 # endif /* NO_GETSERVBYNAME */ 1741 } 1742 break; 1743 #endif /* NETINET */ 1744 1745 #if NETINET6 1746 case AF_INET6: 1747 if (isascii(*port) && isdigit(*port)) 1748 d->d_addr.sin6.sin6_port = htons((unsigned short) 1749 atoi(port)); 1750 else 1751 { 1752 # ifdef NO_GETSERVBYNAME 1753 syserr("554 5.3.5 invalid port number: %s", 1754 port); 1755 # else /* NO_GETSERVBYNAME */ 1756 register struct servent *sp; 1757 1758 sp = getservbyname(port, "tcp"); 1759 if (sp == NULL) 1760 syserr("554 5.3.5 service \"%s\" unknown", 1761 port); 1762 else 1763 d->d_addr.sin6.sin6_port = sp->s_port; 1764 # endif /* NO_GETSERVBYNAME */ 1765 } 1766 break; 1767 #endif /* NETINET6 */ 1768 1769 #if NETISO 1770 case AF_ISO: 1771 /* assume two byte transport selector */ 1772 if (isascii(*port) && isdigit(*port)) 1773 portno = htons((unsigned short) atoi(port)); 1774 else 1775 { 1776 # ifdef NO_GETSERVBYNAME 1777 syserr("554 5.3.5 invalid port number: %s", 1778 port); 1779 # else /* NO_GETSERVBYNAME */ 1780 register struct servent *sp; 1781 1782 sp = getservbyname(port, "tcp"); 1783 if (sp == NULL) 1784 syserr("554 5.3.5 service \"%s\" unknown", 1785 port); 1786 else 1787 portno = sp->s_port; 1788 # endif /* NO_GETSERVBYNAME */ 1789 } 1790 memmove(TSEL(&d->d_addr.siso), 1791 (char *) &portno, 2); 1792 break; 1793 #endif /* NETISO */ 1794 1795 default: 1796 syserr("554 5.3.5 Port= option unsupported for family %d", 1797 d->d_addr.sa.sa_family); 1798 break; 1799 } 1800 } 1801 } 1802 /* 1803 ** SETDAEMONOPTIONS -- set options for running the MTA daemon 1804 ** 1805 ** Parameters: 1806 ** p -- the options line. 1807 ** 1808 ** Returns: 1809 ** true if successful, false otherwise. 1810 ** 1811 ** Side Effects: 1812 ** increments number of daemons. 1813 */ 1814 1815 #define DEF_LISTENQUEUE 10 1816 1817 struct dflags 1818 { 1819 char *d_name; 1820 int d_flag; 1821 }; 1822 1823 static struct dflags DaemonFlags[] = 1824 { 1825 { "AUTHREQ", D_AUTHREQ }, 1826 { "BINDIF", D_BINDIF }, 1827 { "CANONREQ", D_CANONREQ }, 1828 { "IFNHELO", D_IFNHELO }, 1829 { "FQMAIL", D_FQMAIL }, 1830 { "FQRCPT", D_FQRCPT }, 1831 { "SMTPS", D_SMTPS }, 1832 { "UNQUALOK", D_UNQUALOK }, 1833 { "NOAUTH", D_NOAUTH }, 1834 { "NOCANON", D_NOCANON }, 1835 { "NOETRN", D_NOETRN }, 1836 { "NOTLS", D_NOTLS }, 1837 { "ETRNONLY", D_ETRNONLY }, 1838 { "OPTIONAL", D_OPTIONAL }, 1839 { "DISABLE", D_DISABLE }, 1840 { "ISSET", D_ISSET }, 1841 { NULL, 0 } 1842 }; 1843 1844 static void 1845 printdaemonflags(d) 1846 DAEMON_T *d; 1847 { 1848 register struct dflags *df; 1849 bool first = true; 1850 1851 for (df = DaemonFlags; df->d_name != NULL; df++) 1852 { 1853 if (!bitnset(df->d_flag, d->d_flags)) 1854 continue; 1855 if (first) 1856 sm_dprintf("<%s", df->d_name); 1857 else 1858 sm_dprintf(",%s", df->d_name); 1859 first = false; 1860 } 1861 if (!first) 1862 sm_dprintf(">"); 1863 } 1864 1865 bool 1866 setdaemonoptions(p) 1867 register char *p; 1868 { 1869 if (NDaemons >= MAXDAEMONS) 1870 return false; 1871 Daemons[NDaemons].d_socket = -1; 1872 Daemons[NDaemons].d_listenqueue = DEF_LISTENQUEUE; 1873 clrbitmap(Daemons[NDaemons].d_flags); 1874 setsockaddroptions(p, &Daemons[NDaemons]); 1875 1876 #if MILTER 1877 if (Daemons[NDaemons].d_inputfilterlist != NULL) 1878 Daemons[NDaemons].d_inputfilterlist = newstr(Daemons[NDaemons].d_inputfilterlist); 1879 #endif /* MILTER */ 1880 1881 if (Daemons[NDaemons].d_name != NULL) 1882 Daemons[NDaemons].d_name = newstr(Daemons[NDaemons].d_name); 1883 else 1884 { 1885 char num[30]; 1886 1887 (void) sm_snprintf(num, sizeof(num), "Daemon%d", NDaemons); 1888 Daemons[NDaemons].d_name = newstr(num); 1889 } 1890 1891 if (tTd(37, 1)) 1892 { 1893 sm_dprintf("Daemon %s flags: ", Daemons[NDaemons].d_name); 1894 printdaemonflags(&Daemons[NDaemons]); 1895 sm_dprintf("\n"); 1896 } 1897 ++NDaemons; 1898 return true; 1899 } 1900 /* 1901 ** INITDAEMON -- initialize daemon if not yet done. 1902 ** 1903 ** Parameters: 1904 ** none 1905 ** 1906 ** Returns: 1907 ** none 1908 ** 1909 ** Side Effects: 1910 ** initializes structure for one daemon. 1911 */ 1912 1913 void 1914 initdaemon() 1915 { 1916 if (NDaemons == 0) 1917 { 1918 Daemons[NDaemons].d_socket = -1; 1919 Daemons[NDaemons].d_listenqueue = DEF_LISTENQUEUE; 1920 Daemons[NDaemons].d_name = "Daemon0"; 1921 NDaemons = 1; 1922 } 1923 } 1924 /* 1925 ** SETCLIENTOPTIONS -- set options for running the client 1926 ** 1927 ** Parameters: 1928 ** p -- the options line. 1929 ** 1930 ** Returns: 1931 ** none. 1932 */ 1933 1934 static DAEMON_T ClientSettings[AF_MAX + 1]; 1935 1936 void 1937 setclientoptions(p) 1938 register char *p; 1939 { 1940 int family; 1941 DAEMON_T d; 1942 1943 memset(&d, '\0', sizeof(d)); 1944 setsockaddroptions(p, &d); 1945 1946 /* grab what we need */ 1947 family = d.d_addr.sa.sa_family; 1948 STRUCTCOPY(d, ClientSettings[family]); 1949 setbitn(D_ISSET, ClientSettings[family].d_flags); /* mark as set */ 1950 if (d.d_name != NULL) 1951 ClientSettings[family].d_name = newstr(d.d_name); 1952 else 1953 { 1954 char num[30]; 1955 1956 (void) sm_snprintf(num, sizeof(num), "Client%d", family); 1957 ClientSettings[family].d_name = newstr(num); 1958 } 1959 } 1960 /* 1961 ** ADDR_FAMILY -- determine address family from address 1962 ** 1963 ** Parameters: 1964 ** addr -- the string representation of the address 1965 ** 1966 ** Returns: 1967 ** AF_INET, AF_INET6 or AF_UNSPEC 1968 ** 1969 ** Side Effects: 1970 ** none. 1971 */ 1972 1973 static int 1974 addr_family(addr) 1975 char *addr; 1976 { 1977 #if NETINET6 1978 SOCKADDR clt_addr; 1979 #endif /* NETINET6 */ 1980 1981 #if NETINET 1982 if (inet_addr(addr) != INADDR_NONE) 1983 { 1984 if (tTd(16, 9)) 1985 sm_dprintf("addr_family(%s): INET\n", addr); 1986 return AF_INET; 1987 } 1988 #endif /* NETINET */ 1989 #if NETINET6 1990 if (anynet_pton(AF_INET6, addr, &clt_addr.sin6.sin6_addr) == 1) 1991 { 1992 if (tTd(16, 9)) 1993 sm_dprintf("addr_family(%s): INET6\n", addr); 1994 return AF_INET6; 1995 } 1996 #endif /* NETINET6 */ 1997 #if _FFR_DAEMON_NETUNIX 1998 # if NETUNIX 1999 if (*addr == '/') 2000 { 2001 if (tTd(16, 9)) 2002 sm_dprintf("addr_family(%s): LOCAL\n", addr); 2003 return AF_UNIX; 2004 } 2005 # endif /* NETUNIX */ 2006 #endif /* _FFR_DAEMON_NETUNIX */ 2007 if (tTd(16, 9)) 2008 sm_dprintf("addr_family(%s): UNSPEC\n", addr); 2009 return AF_UNSPEC; 2010 } 2011 2012 /* 2013 ** CHKCLIENTMODIFIERS -- check whether all clients have set a flag. 2014 ** 2015 ** Parameters: 2016 ** flag -- the flag to test. 2017 ** 2018 ** Returns: 2019 ** true iff all configured clients have set the flag. 2020 */ 2021 2022 bool 2023 chkclientmodifiers(flag) 2024 int flag; 2025 { 2026 int i; 2027 bool flagisset; 2028 2029 flagisset = false; 2030 for (i = 0; i < AF_MAX; i++) 2031 { 2032 if (bitnset(D_ISSET, ClientSettings[i].d_flags)) 2033 { 2034 if (!bitnset((char) flag, ClientSettings[i].d_flags)) 2035 return false; 2036 flagisset = true; 2037 } 2038 } 2039 return flagisset; 2040 } 2041 2042 #if MILTER 2043 /* 2044 ** SETUP_DAEMON_FILTERS -- Parse per-socket filters 2045 ** 2046 ** Parameters: 2047 ** none 2048 ** 2049 ** Returns: 2050 ** none 2051 */ 2052 2053 void 2054 setup_daemon_milters() 2055 { 2056 int idx; 2057 2058 if (OpMode == MD_SMTP) 2059 { 2060 /* no need to configure the daemons */ 2061 return; 2062 } 2063 2064 for (idx = 0; idx < NDaemons; idx++) 2065 { 2066 if (Daemons[idx].d_inputfilterlist != NULL) 2067 { 2068 milter_config(Daemons[idx].d_inputfilterlist, 2069 Daemons[idx].d_inputfilters, 2070 MAXFILTERS); 2071 } 2072 } 2073 } 2074 #endif /* MILTER */ 2075 /* 2076 ** MAKECONNECTION -- make a connection to an SMTP socket on a machine. 2077 ** 2078 ** Parameters: 2079 ** host -- the name of the host. 2080 ** port -- the port number to connect to. 2081 ** mci -- a pointer to the mail connection information 2082 ** structure to be filled in. 2083 ** e -- the current envelope. 2084 ** enough -- time at which to stop further connection attempts. 2085 ** (0 means no limit) 2086 ** 2087 ** Returns: 2088 ** An exit code telling whether the connection could be 2089 ** made and if not why not. 2090 ** 2091 ** Side Effects: 2092 ** none. 2093 */ 2094 2095 static jmp_buf CtxConnectTimeout; 2096 2097 SOCKADDR CurHostAddr; /* address of current host */ 2098 2099 int 2100 makeconnection(host, port, mci, e, enough) 2101 char *host; 2102 volatile unsigned int port; 2103 register MCI *mci; 2104 ENVELOPE *e; 2105 time_t enough; 2106 { 2107 register volatile int addrno = 0; 2108 volatile int s; 2109 register struct hostent *volatile hp = (struct hostent *) NULL; 2110 SOCKADDR addr; 2111 SOCKADDR clt_addr; 2112 int save_errno = 0; 2113 volatile SOCKADDR_LEN_T addrlen; 2114 volatile bool firstconnect = true; 2115 SM_EVENT *volatile ev = NULL; 2116 #if NETINET6 2117 volatile bool v6found = false; 2118 #endif /* NETINET6 */ 2119 volatile int family = InetMode; 2120 SOCKADDR_LEN_T len; 2121 volatile SOCKADDR_LEN_T socksize = 0; 2122 volatile bool clt_bind; 2123 BITMAP256 d_flags; 2124 char *p; 2125 extern ENVELOPE BlankEnvelope; 2126 2127 /* retranslate {daemon_flags} into bitmap */ 2128 clrbitmap(d_flags); 2129 if ((p = macvalue(macid("{daemon_flags}"), e)) != NULL) 2130 { 2131 for (; *p != '\0'; p++) 2132 { 2133 if (!(isascii(*p) && isspace(*p))) 2134 setbitn(bitidx(*p), d_flags); 2135 } 2136 } 2137 2138 #if NETINET6 2139 v4retry: 2140 #endif /* NETINET6 */ 2141 clt_bind = false; 2142 2143 /* Set up the address for outgoing connection. */ 2144 if (bitnset(D_BINDIF, d_flags) && 2145 (p = macvalue(macid("{if_addr}"), e)) != NULL && 2146 *p != '\0') 2147 { 2148 #if NETINET6 2149 char p6[INET6_ADDRSTRLEN]; 2150 #endif /* NETINET6 */ 2151 2152 memset(&clt_addr, '\0', sizeof(clt_addr)); 2153 2154 /* infer the address family from the address itself */ 2155 clt_addr.sa.sa_family = addr_family(p); 2156 switch (clt_addr.sa.sa_family) 2157 { 2158 #if NETINET 2159 case AF_INET: 2160 clt_addr.sin.sin_addr.s_addr = inet_addr(p); 2161 if (clt_addr.sin.sin_addr.s_addr != INADDR_NONE && 2162 clt_addr.sin.sin_addr.s_addr != INADDR_LOOPBACK) 2163 { 2164 clt_bind = true; 2165 socksize = sizeof(struct sockaddr_in); 2166 } 2167 break; 2168 #endif /* NETINET */ 2169 2170 #if NETINET6 2171 case AF_INET6: 2172 if (inet_addr(p) != INADDR_NONE) 2173 (void) sm_snprintf(p6, sizeof(p6), 2174 "IPv6:::ffff:%s", p); 2175 else 2176 (void) sm_strlcpy(p6, p, sizeof(p6)); 2177 if (anynet_pton(AF_INET6, p6, 2178 &clt_addr.sin6.sin6_addr) == 1 && 2179 !IN6_IS_ADDR_LOOPBACK(&clt_addr.sin6.sin6_addr)) 2180 { 2181 clt_bind = true; 2182 socksize = sizeof(struct sockaddr_in6); 2183 } 2184 break; 2185 #endif /* NETINET6 */ 2186 2187 #if 0 2188 default: 2189 syserr("554 5.3.5 Address= option unsupported for family %d", 2190 clt_addr.sa.sa_family); 2191 break; 2192 #endif /* 0 */ 2193 } 2194 if (clt_bind) 2195 family = clt_addr.sa.sa_family; 2196 } 2197 2198 /* D_BINDIF not set or not available, fallback to ClientPortOptions */ 2199 if (!clt_bind) 2200 { 2201 STRUCTCOPY(ClientSettings[family].d_addr, clt_addr); 2202 switch (clt_addr.sa.sa_family) 2203 { 2204 #if NETINET 2205 case AF_INET: 2206 if (clt_addr.sin.sin_addr.s_addr == 0) 2207 clt_addr.sin.sin_addr.s_addr = INADDR_ANY; 2208 else 2209 clt_bind = true; 2210 if (clt_addr.sin.sin_port != 0) 2211 clt_bind = true; 2212 socksize = sizeof(struct sockaddr_in); 2213 break; 2214 #endif /* NETINET */ 2215 #if NETINET6 2216 case AF_INET6: 2217 if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr)) 2218 clt_addr.sin6.sin6_addr = in6addr_any; 2219 else 2220 clt_bind = true; 2221 socksize = sizeof(struct sockaddr_in6); 2222 if (clt_addr.sin6.sin6_port != 0) 2223 clt_bind = true; 2224 break; 2225 #endif /* NETINET6 */ 2226 #if NETISO 2227 case AF_ISO: 2228 socksize = sizeof(clt_addr.siso); 2229 clt_bind = true; 2230 break; 2231 #endif /* NETISO */ 2232 default: 2233 break; 2234 } 2235 } 2236 2237 /* 2238 ** Set up the address for the mailer. 2239 ** Accept "[a.b.c.d]" syntax for host name. 2240 */ 2241 2242 SM_SET_H_ERRNO(0); 2243 errno = 0; 2244 memset(&CurHostAddr, '\0', sizeof(CurHostAddr)); 2245 memset(&addr, '\0', sizeof(addr)); 2246 SmtpPhase = mci->mci_phase = "initial connection"; 2247 CurHostName = host; 2248 2249 if (host[0] == '[') 2250 { 2251 p = strchr(host, ']'); 2252 if (p != NULL) 2253 { 2254 #if NETINET 2255 unsigned long hid = INADDR_NONE; 2256 #endif /* NETINET */ 2257 #if NETINET6 2258 struct sockaddr_in6 hid6; 2259 #endif /* NETINET6 */ 2260 2261 *p = '\0'; 2262 #if NETINET6 2263 memset(&hid6, '\0', sizeof(hid6)); 2264 #endif /* NETINET6 */ 2265 #if NETINET 2266 if (family == AF_INET && 2267 (hid = inet_addr(&host[1])) != INADDR_NONE) 2268 { 2269 addr.sin.sin_family = AF_INET; 2270 addr.sin.sin_addr.s_addr = hid; 2271 } 2272 else 2273 #endif /* NETINET */ 2274 #if NETINET6 2275 if (family == AF_INET6 && 2276 anynet_pton(AF_INET6, &host[1], 2277 &hid6.sin6_addr) == 1) 2278 { 2279 addr.sin6.sin6_family = AF_INET6; 2280 addr.sin6.sin6_addr = hid6.sin6_addr; 2281 } 2282 else 2283 #endif /* NETINET6 */ 2284 { 2285 /* try it as a host name (avoid MX lookup) */ 2286 hp = sm_gethostbyname(&host[1], family); 2287 if (hp == NULL && p[-1] == '.') 2288 { 2289 #if NAMED_BIND 2290 int oldopts = _res.options; 2291 2292 _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 2293 #endif /* NAMED_BIND */ 2294 p[-1] = '\0'; 2295 hp = sm_gethostbyname(&host[1], 2296 family); 2297 p[-1] = '.'; 2298 #if NAMED_BIND 2299 _res.options = oldopts; 2300 #endif /* NAMED_BIND */ 2301 } 2302 *p = ']'; 2303 goto gothostent; 2304 } 2305 *p = ']'; 2306 } 2307 if (p == NULL) 2308 { 2309 extern char MsgBuf[]; 2310 2311 usrerrenh("5.1.2", 2312 "553 Invalid numeric domain spec \"%s\"", 2313 host); 2314 mci_setstat(mci, EX_NOHOST, "5.1.2", MsgBuf); 2315 errno = EINVAL; 2316 return EX_NOHOST; 2317 } 2318 } 2319 else 2320 { 2321 /* contortion to get around SGI cc complaints */ 2322 { 2323 p = &host[strlen(host) - 1]; 2324 hp = sm_gethostbyname(host, family); 2325 if (hp == NULL && *p == '.') 2326 { 2327 #if NAMED_BIND 2328 int oldopts = _res.options; 2329 2330 _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 2331 #endif /* NAMED_BIND */ 2332 *p = '\0'; 2333 hp = sm_gethostbyname(host, family); 2334 *p = '.'; 2335 #if NAMED_BIND 2336 _res.options = oldopts; 2337 #endif /* NAMED_BIND */ 2338 } 2339 } 2340 gothostent: 2341 if (hp == NULL) 2342 { 2343 #if NAMED_BIND 2344 /* check for name server timeouts */ 2345 # if NETINET6 2346 if (WorkAroundBrokenAAAA && family == AF_INET6 && 2347 errno == ETIMEDOUT) 2348 { 2349 /* 2350 ** An attempt with family AF_INET may 2351 ** succeed By skipping the next section 2352 ** of code, we will try AF_INET before 2353 ** failing. 2354 */ 2355 2356 if (tTd(16, 10)) 2357 sm_dprintf("makeconnection: WorkAroundBrokenAAAA: Trying AF_INET lookup (AF_INET6 failed)\n"); 2358 } 2359 else 2360 # endif /* NETINET6 */ 2361 { 2362 if (errno == ETIMEDOUT || 2363 # if _FFR_GETHBN_ExFILE 2364 # ifdef EMFILE 2365 errno == EMFILE || 2366 # endif /* EMFILE */ 2367 # ifdef ENFILE 2368 errno == ENFILE || 2369 # endif /* ENFILE */ 2370 # endif /* _FFR_GETHBN_ExFILE */ 2371 h_errno == TRY_AGAIN || 2372 (errno == ECONNREFUSED && UseNameServer)) 2373 { 2374 save_errno = errno; 2375 mci_setstat(mci, EX_TEMPFAIL, 2376 "4.4.3", NULL); 2377 errno = save_errno; 2378 return EX_TEMPFAIL; 2379 } 2380 } 2381 #endif /* NAMED_BIND */ 2382 #if NETINET6 2383 /* 2384 ** Try v6 first, then fall back to v4. 2385 ** If we found a v6 address, but no v4 2386 ** addresses, then TEMPFAIL. 2387 */ 2388 2389 if (family == AF_INET6) 2390 { 2391 family = AF_INET; 2392 goto v4retry; 2393 } 2394 if (v6found) 2395 goto v6tempfail; 2396 #endif /* NETINET6 */ 2397 save_errno = errno; 2398 mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 2399 errno = save_errno; 2400 return EX_NOHOST; 2401 } 2402 addr.sa.sa_family = hp->h_addrtype; 2403 switch (hp->h_addrtype) 2404 { 2405 #if NETINET 2406 case AF_INET: 2407 memmove(&addr.sin.sin_addr, 2408 hp->h_addr, 2409 INADDRSZ); 2410 break; 2411 #endif /* NETINET */ 2412 2413 #if NETINET6 2414 case AF_INET6: 2415 memmove(&addr.sin6.sin6_addr, 2416 hp->h_addr, 2417 IN6ADDRSZ); 2418 break; 2419 #endif /* NETINET6 */ 2420 2421 default: 2422 if (hp->h_length > sizeof(addr.sa.sa_data)) 2423 { 2424 syserr("makeconnection: long sa_data: family %d len %d", 2425 hp->h_addrtype, hp->h_length); 2426 mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 2427 errno = EINVAL; 2428 return EX_NOHOST; 2429 } 2430 memmove(addr.sa.sa_data, hp->h_addr, hp->h_length); 2431 break; 2432 } 2433 addrno = 1; 2434 } 2435 2436 /* 2437 ** Determine the port number. 2438 */ 2439 2440 if (port == 0) 2441 { 2442 #ifdef NO_GETSERVBYNAME 2443 port = htons(25); 2444 #else /* NO_GETSERVBYNAME */ 2445 register struct servent *sp = getservbyname("smtp", "tcp"); 2446 2447 if (sp == NULL) 2448 { 2449 if (LogLevel > 2) 2450 sm_syslog(LOG_ERR, NOQID, 2451 "makeconnection: service \"smtp\" unknown"); 2452 port = htons(25); 2453 } 2454 else 2455 port = sp->s_port; 2456 #endif /* NO_GETSERVBYNAME */ 2457 } 2458 2459 #if NETINET6 2460 if (addr.sa.sa_family == AF_INET6 && 2461 IN6_IS_ADDR_V4MAPPED(&addr.sin6.sin6_addr) && 2462 ClientSettings[AF_INET].d_addr.sa.sa_family != 0) 2463 { 2464 /* 2465 ** Ignore mapped IPv4 address since 2466 ** there is a ClientPortOptions setting 2467 ** for IPv4. 2468 */ 2469 2470 goto nextaddr; 2471 } 2472 #endif /* NETINET6 */ 2473 2474 switch (addr.sa.sa_family) 2475 { 2476 #if NETINET 2477 case AF_INET: 2478 addr.sin.sin_port = port; 2479 addrlen = sizeof(struct sockaddr_in); 2480 break; 2481 #endif /* NETINET */ 2482 2483 #if NETINET6 2484 case AF_INET6: 2485 addr.sin6.sin6_port = port; 2486 addrlen = sizeof(struct sockaddr_in6); 2487 break; 2488 #endif /* NETINET6 */ 2489 2490 #if NETISO 2491 case AF_ISO: 2492 /* assume two byte transport selector */ 2493 memmove(TSEL((struct sockaddr_iso *) &addr), (char *) &port, 2); 2494 addrlen = sizeof(struct sockaddr_iso); 2495 break; 2496 #endif /* NETISO */ 2497 2498 default: 2499 syserr("Can't connect to address family %d", addr.sa.sa_family); 2500 mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 2501 errno = EINVAL; 2502 #if NETINET6 2503 if (hp != NULL) 2504 freehostent(hp); 2505 #endif /* NETINET6 */ 2506 return EX_NOHOST; 2507 } 2508 2509 /* 2510 ** Try to actually open the connection. 2511 */ 2512 2513 #if XLA 2514 /* if too many connections, don't bother trying */ 2515 if (!xla_noqueue_ok(host)) 2516 { 2517 # if NETINET6 2518 if (hp != NULL) 2519 freehostent(hp); 2520 # endif /* NETINET6 */ 2521 return EX_TEMPFAIL; 2522 } 2523 #endif /* XLA */ 2524 2525 for (;;) 2526 { 2527 if (tTd(16, 1)) 2528 sm_dprintf("makeconnection (%s [%s].%d (%d))\n", 2529 host, anynet_ntoa(&addr), ntohs(port), 2530 (int) addr.sa.sa_family); 2531 2532 /* save for logging */ 2533 CurHostAddr = addr; 2534 2535 #if HASRRESVPORT 2536 if (bitnset(M_SECURE_PORT, mci->mci_mailer->m_flags)) 2537 { 2538 int rport = IPPORT_RESERVED - 1; 2539 2540 s = rresvport(&rport); 2541 } 2542 else 2543 #endif /* HASRRESVPORT */ 2544 { 2545 s = socket(addr.sa.sa_family, SOCK_STREAM, 0); 2546 } 2547 if (s < 0) 2548 { 2549 save_errno = errno; 2550 syserr("makeconnection: cannot create socket"); 2551 #if XLA 2552 xla_host_end(host); 2553 #endif /* XLA */ 2554 mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 2555 #if NETINET6 2556 if (hp != NULL) 2557 freehostent(hp); 2558 #endif /* NETINET6 */ 2559 errno = save_errno; 2560 return EX_TEMPFAIL; 2561 } 2562 2563 #ifdef SO_SNDBUF 2564 if (ClientSettings[family].d_tcpsndbufsize > 0) 2565 { 2566 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 2567 (char *) &ClientSettings[family].d_tcpsndbufsize, 2568 sizeof(ClientSettings[family].d_tcpsndbufsize)) < 0) 2569 syserr("makeconnection: setsockopt(SO_SNDBUF)"); 2570 } 2571 #endif /* SO_SNDBUF */ 2572 #ifdef SO_RCVBUF 2573 if (ClientSettings[family].d_tcprcvbufsize > 0) 2574 { 2575 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, 2576 (char *) &ClientSettings[family].d_tcprcvbufsize, 2577 sizeof(ClientSettings[family].d_tcprcvbufsize)) < 0) 2578 syserr("makeconnection: setsockopt(SO_RCVBUF)"); 2579 } 2580 #endif /* SO_RCVBUF */ 2581 2582 if (tTd(16, 1)) 2583 sm_dprintf("makeconnection: fd=%d\n", s); 2584 2585 /* turn on network debugging? */ 2586 if (tTd(16, 101)) 2587 { 2588 int on = 1; 2589 2590 (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, 2591 (char *)&on, sizeof(on)); 2592 } 2593 if (e->e_xfp != NULL) /* for debugging */ 2594 (void) sm_io_flush(e->e_xfp, SM_TIME_DEFAULT); 2595 errno = 0; /* for debugging */ 2596 2597 if (clt_bind) 2598 { 2599 int on = 1; 2600 2601 switch (clt_addr.sa.sa_family) 2602 { 2603 #if NETINET 2604 case AF_INET: 2605 if (clt_addr.sin.sin_port != 0) 2606 (void) setsockopt(s, SOL_SOCKET, 2607 SO_REUSEADDR, 2608 (char *) &on, 2609 sizeof(on)); 2610 break; 2611 #endif /* NETINET */ 2612 2613 #if NETINET6 2614 case AF_INET6: 2615 if (clt_addr.sin6.sin6_port != 0) 2616 (void) setsockopt(s, SOL_SOCKET, 2617 SO_REUSEADDR, 2618 (char *) &on, 2619 sizeof(on)); 2620 break; 2621 #endif /* NETINET6 */ 2622 } 2623 2624 if (bind(s, &clt_addr.sa, socksize) < 0) 2625 { 2626 save_errno = errno; 2627 (void) close(s); 2628 errno = save_errno; 2629 syserr("makeconnection: cannot bind socket [%s]", 2630 anynet_ntoa(&clt_addr)); 2631 #if NETINET6 2632 if (hp != NULL) 2633 freehostent(hp); 2634 #endif /* NETINET6 */ 2635 errno = save_errno; 2636 return EX_TEMPFAIL; 2637 } 2638 } 2639 2640 /* 2641 ** Linux seems to hang in connect for 90 minutes (!!!). 2642 ** Time out the connect to avoid this problem. 2643 */ 2644 2645 if (setjmp(CtxConnectTimeout) == 0) 2646 { 2647 int i; 2648 2649 if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0) 2650 ev = sm_setevent(TimeOuts.to_iconnect, 2651 connecttimeout, 0); 2652 else if (TimeOuts.to_connect != 0) 2653 ev = sm_setevent(TimeOuts.to_connect, 2654 connecttimeout, 0); 2655 else 2656 ev = NULL; 2657 2658 switch (ConnectOnlyTo.sa.sa_family) 2659 { 2660 #if NETINET 2661 case AF_INET: 2662 addr.sin.sin_addr.s_addr = ConnectOnlyTo.sin.sin_addr.s_addr; 2663 break; 2664 #endif /* NETINET */ 2665 2666 #if NETINET6 2667 case AF_INET6: 2668 memmove(&addr.sin6.sin6_addr, 2669 &ConnectOnlyTo.sin6.sin6_addr, 2670 IN6ADDRSZ); 2671 break; 2672 #endif /* NETINET6 */ 2673 } 2674 if (tTd(16, 1)) 2675 sm_dprintf("Connecting to [%s]...\n", anynet_ntoa(&addr)); 2676 i = connect(s, (struct sockaddr *) &addr, addrlen); 2677 save_errno = errno; 2678 if (ev != NULL) 2679 sm_clrevent(ev); 2680 if (i >= 0) 2681 break; 2682 } 2683 else 2684 save_errno = errno; 2685 2686 /* couldn't connect.... figure out why */ 2687 (void) close(s); 2688 2689 /* if running demand-dialed connection, try again */ 2690 if (DialDelay > 0 && firstconnect && 2691 bitnset(M_DIALDELAY, mci->mci_mailer->m_flags)) 2692 { 2693 if (tTd(16, 1)) 2694 sm_dprintf("Connect failed (%s); trying again...\n", 2695 sm_errstring(save_errno)); 2696 firstconnect = false; 2697 (void) sleep(DialDelay); 2698 continue; 2699 } 2700 2701 if (LogLevel > 13) 2702 sm_syslog(LOG_INFO, e->e_id, 2703 "makeconnection (%s [%s]) failed: %s", 2704 host, anynet_ntoa(&addr), 2705 sm_errstring(save_errno)); 2706 2707 #if NETINET6 2708 nextaddr: 2709 #endif /* NETINET6 */ 2710 if (hp != NULL && hp->h_addr_list[addrno] != NULL && 2711 (enough == 0 || curtime() < enough)) 2712 { 2713 if (tTd(16, 1)) 2714 sm_dprintf("Connect failed (%s); trying new address....\n", 2715 sm_errstring(save_errno)); 2716 switch (addr.sa.sa_family) 2717 { 2718 #if NETINET 2719 case AF_INET: 2720 memmove(&addr.sin.sin_addr, 2721 hp->h_addr_list[addrno++], 2722 INADDRSZ); 2723 break; 2724 #endif /* NETINET */ 2725 2726 #if NETINET6 2727 case AF_INET6: 2728 memmove(&addr.sin6.sin6_addr, 2729 hp->h_addr_list[addrno++], 2730 IN6ADDRSZ); 2731 break; 2732 #endif /* NETINET6 */ 2733 2734 default: 2735 memmove(addr.sa.sa_data, 2736 hp->h_addr_list[addrno++], 2737 hp->h_length); 2738 break; 2739 } 2740 continue; 2741 } 2742 errno = save_errno; 2743 2744 #if NETINET6 2745 if (family == AF_INET6) 2746 { 2747 if (tTd(16, 1)) 2748 sm_dprintf("Connect failed (%s); retrying with AF_INET....\n", 2749 sm_errstring(save_errno)); 2750 v6found = true; 2751 family = AF_INET; 2752 if (hp != NULL) 2753 { 2754 freehostent(hp); 2755 hp = NULL; 2756 } 2757 goto v4retry; 2758 } 2759 v6tempfail: 2760 #endif /* NETINET6 */ 2761 /* couldn't open connection */ 2762 #if NETINET6 2763 /* Don't clobber an already saved errno from v4retry */ 2764 if (errno > 0) 2765 #endif /* NETINET6 */ 2766 save_errno = errno; 2767 if (tTd(16, 1)) 2768 sm_dprintf("Connect failed (%s)\n", 2769 sm_errstring(save_errno)); 2770 #if XLA 2771 xla_host_end(host); 2772 #endif /* XLA */ 2773 mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL); 2774 #if NETINET6 2775 if (hp != NULL) 2776 freehostent(hp); 2777 #endif /* NETINET6 */ 2778 errno = save_errno; 2779 return EX_TEMPFAIL; 2780 } 2781 2782 #if NETINET6 2783 if (hp != NULL) 2784 { 2785 freehostent(hp); 2786 hp = NULL; 2787 } 2788 #endif /* NETINET6 */ 2789 2790 /* connection ok, put it into canonical form */ 2791 mci->mci_out = NULL; 2792 if ((mci->mci_out = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 2793 (void *) &s, 2794 SM_IO_WRONLY_B, NULL)) == NULL || 2795 (s = dup(s)) < 0 || 2796 (mci->mci_in = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 2797 (void *) &s, 2798 SM_IO_RDONLY_B, NULL)) == NULL) 2799 { 2800 save_errno = errno; 2801 syserr("cannot open SMTP client channel, fd=%d", s); 2802 mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 2803 if (mci->mci_out != NULL) 2804 (void) sm_io_close(mci->mci_out, SM_TIME_DEFAULT); 2805 (void) close(s); 2806 errno = save_errno; 2807 return EX_TEMPFAIL; 2808 } 2809 sm_io_automode(mci->mci_out, mci->mci_in); 2810 2811 /* set {client_flags} */ 2812 if (ClientSettings[addr.sa.sa_family].d_mflags != NULL) 2813 { 2814 macdefine(&mci->mci_macro, A_PERM, 2815 macid("{client_flags}"), 2816 ClientSettings[addr.sa.sa_family].d_mflags); 2817 } 2818 else 2819 macdefine(&mci->mci_macro, A_PERM, 2820 macid("{client_flags}"), ""); 2821 2822 /* "add" {client_flags} to bitmap */ 2823 if (bitnset(D_IFNHELO, ClientSettings[addr.sa.sa_family].d_flags)) 2824 { 2825 /* look for just this one flag */ 2826 setbitn(D_IFNHELO, d_flags); 2827 } 2828 2829 /* find out name for Interface through which we connect */ 2830 len = sizeof(addr); 2831 if (getsockname(s, &addr.sa, &len) == 0) 2832 { 2833 char *name; 2834 char family[5]; 2835 2836 macdefine(&BlankEnvelope.e_macro, A_TEMP, 2837 macid("{if_addr_out}"), anynet_ntoa(&addr)); 2838 (void) sm_snprintf(family, sizeof(family), "%d", 2839 addr.sa.sa_family); 2840 macdefine(&BlankEnvelope.e_macro, A_TEMP, 2841 macid("{if_family_out}"), family); 2842 2843 name = hostnamebyanyaddr(&addr); 2844 macdefine(&BlankEnvelope.e_macro, A_TEMP, 2845 macid("{if_name_out}"), name); 2846 if (LogLevel > 11) 2847 { 2848 /* log connection information */ 2849 sm_syslog(LOG_INFO, e->e_id, 2850 "SMTP outgoing connect on %.40s", name); 2851 } 2852 if (bitnset(D_IFNHELO, d_flags)) 2853 { 2854 if (name[0] != '[' && strchr(name, '.') != NULL) 2855 mci->mci_heloname = newstr(name); 2856 } 2857 } 2858 else 2859 { 2860 macdefine(&BlankEnvelope.e_macro, A_PERM, 2861 macid("{if_name_out}"), NULL); 2862 macdefine(&BlankEnvelope.e_macro, A_PERM, 2863 macid("{if_addr_out}"), NULL); 2864 macdefine(&BlankEnvelope.e_macro, A_PERM, 2865 macid("{if_family_out}"), NULL); 2866 } 2867 2868 /* Use the configured HeloName as appropriate */ 2869 if (HeloName != NULL && HeloName[0] != '\0') 2870 mci->mci_heloname = newstr(HeloName); 2871 2872 mci_setstat(mci, EX_OK, NULL, NULL); 2873 return EX_OK; 2874 } 2875 2876 static void 2877 connecttimeout(ignore) 2878 int ignore; 2879 { 2880 /* 2881 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 2882 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 2883 ** DOING. 2884 */ 2885 2886 errno = ETIMEDOUT; 2887 longjmp(CtxConnectTimeout, 1); 2888 } 2889 /* 2890 ** MAKECONNECTION_DS -- make a connection to a domain socket. 2891 ** 2892 ** Parameters: 2893 ** mux_path -- the path of the socket to connect to. 2894 ** mci -- a pointer to the mail connection information 2895 ** structure to be filled in. 2896 ** 2897 ** Returns: 2898 ** An exit code telling whether the connection could be 2899 ** made and if not why not. 2900 ** 2901 ** Side Effects: 2902 ** none. 2903 */ 2904 2905 #if NETUNIX 2906 int 2907 makeconnection_ds(mux_path, mci) 2908 char *mux_path; 2909 register MCI *mci; 2910 { 2911 int sock; 2912 int rval, save_errno; 2913 long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_ROOTOK|SFF_EXECOK; 2914 struct sockaddr_un unix_addr; 2915 2916 /* if not safe, don't connect */ 2917 rval = safefile(mux_path, RunAsUid, RunAsGid, RunAsUserName, 2918 sff, S_IRUSR|S_IWUSR, NULL); 2919 2920 if (rval != 0) 2921 { 2922 syserr("makeconnection_ds: unsafe domain socket %s", 2923 mux_path); 2924 mci_setstat(mci, EX_TEMPFAIL, "4.3.5", NULL); 2925 errno = rval; 2926 return EX_TEMPFAIL; 2927 } 2928 2929 /* prepare address structure */ 2930 memset(&unix_addr, '\0', sizeof(unix_addr)); 2931 unix_addr.sun_family = AF_UNIX; 2932 2933 if (strlen(mux_path) >= sizeof(unix_addr.sun_path)) 2934 { 2935 syserr("makeconnection_ds: domain socket name %s too long", 2936 mux_path); 2937 2938 /* XXX why TEMPFAIL but 5.x.y ? */ 2939 mci_setstat(mci, EX_TEMPFAIL, "5.3.5", NULL); 2940 errno = ENAMETOOLONG; 2941 return EX_UNAVAILABLE; 2942 } 2943 (void) sm_strlcpy(unix_addr.sun_path, mux_path, 2944 sizeof(unix_addr.sun_path)); 2945 2946 /* initialize domain socket */ 2947 sock = socket(AF_UNIX, SOCK_STREAM, 0); 2948 if (sock == -1) 2949 { 2950 save_errno = errno; 2951 syserr("makeconnection_ds: could not create domain socket %s", 2952 mux_path); 2953 mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 2954 errno = save_errno; 2955 return EX_TEMPFAIL; 2956 } 2957 2958 /* connect to server */ 2959 if (connect(sock, (struct sockaddr *) &unix_addr, 2960 sizeof(unix_addr)) == -1) 2961 { 2962 save_errno = errno; 2963 syserr("Could not connect to socket %s", mux_path); 2964 mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL); 2965 (void) close(sock); 2966 errno = save_errno; 2967 return EX_TEMPFAIL; 2968 } 2969 2970 /* connection ok, put it into canonical form */ 2971 mci->mci_out = NULL; 2972 if ((mci->mci_out = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 2973 (void *) &sock, SM_IO_WRONLY_B, NULL)) 2974 == NULL 2975 || (sock = dup(sock)) < 0 || 2976 (mci->mci_in = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 2977 (void *) &sock, SM_IO_RDONLY_B, NULL)) 2978 == NULL) 2979 { 2980 save_errno = errno; 2981 syserr("cannot open SMTP client channel, fd=%d", sock); 2982 mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 2983 if (mci->mci_out != NULL) 2984 (void) sm_io_close(mci->mci_out, SM_TIME_DEFAULT); 2985 (void) close(sock); 2986 errno = save_errno; 2987 return EX_TEMPFAIL; 2988 } 2989 sm_io_automode(mci->mci_out, mci->mci_in); 2990 2991 mci_setstat(mci, EX_OK, NULL, NULL); 2992 errno = 0; 2993 return EX_OK; 2994 } 2995 #endif /* NETUNIX */ 2996 /* 2997 ** SHUTDOWN_DAEMON -- Performs a clean shutdown of the daemon 2998 ** 2999 ** Parameters: 3000 ** none. 3001 ** 3002 ** Returns: 3003 ** none. 3004 ** 3005 ** Side Effects: 3006 ** closes control socket, exits. 3007 */ 3008 3009 void 3010 shutdown_daemon() 3011 { 3012 int i; 3013 char *reason; 3014 3015 sm_allsignals(true); 3016 3017 reason = ShutdownRequest; 3018 ShutdownRequest = NULL; 3019 PendingSignal = 0; 3020 3021 if (LogLevel > 9) 3022 sm_syslog(LOG_INFO, CurEnv->e_id, "stopping daemon, reason=%s", 3023 reason == NULL ? "implicit call" : reason); 3024 3025 FileName = NULL; 3026 closecontrolsocket(true); 3027 #if XLA 3028 xla_all_end(); 3029 #endif /* XLA */ 3030 3031 for (i = 0; i < NDaemons; i++) 3032 { 3033 if (Daemons[i].d_socket >= 0) 3034 { 3035 (void) close(Daemons[i].d_socket); 3036 Daemons[i].d_socket = -1; 3037 3038 #if _FFR_DAEMON_NETUNIX 3039 # if NETUNIX 3040 /* Remove named sockets */ 3041 if (Daemons[i].d_addr.sa.sa_family == AF_UNIX) 3042 { 3043 int rval; 3044 long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_MUSTOWN|SFF_EXECOK|SFF_CREAT; 3045 3046 /* if not safe, don't use it */ 3047 rval = safefile(Daemons[i].d_addr.sunix.sun_path, 3048 RunAsUid, RunAsGid, 3049 RunAsUserName, sff, 3050 S_IRUSR|S_IWUSR, NULL); 3051 if (rval == 0 && 3052 unlink(Daemons[i].d_addr.sunix.sun_path) < 0) 3053 { 3054 sm_syslog(LOG_WARNING, NOQID, 3055 "Could not remove daemon %s socket: %s: %s", 3056 Daemons[i].d_name, 3057 Daemons[i].d_addr.sunix.sun_path, 3058 sm_errstring(errno)); 3059 } 3060 } 3061 # endif /* NETUNIX */ 3062 #endif /* _FFR_DAEMON_NETUNIX */ 3063 } 3064 } 3065 3066 finis(false, true, EX_OK); 3067 } 3068 /* 3069 ** RESTART_DAEMON -- Performs a clean restart of the daemon 3070 ** 3071 ** Parameters: 3072 ** none. 3073 ** 3074 ** Returns: 3075 ** none. 3076 ** 3077 ** Side Effects: 3078 ** restarts the daemon or exits if restart fails. 3079 */ 3080 3081 /* Make a non-DFL/IGN signal a noop */ 3082 #define SM_NOOP_SIGNAL(sig, old) \ 3083 do \ 3084 { \ 3085 (old) = sm_signal((sig), sm_signal_noop); \ 3086 if ((old) == SIG_IGN || (old) == SIG_DFL) \ 3087 (void) sm_signal((sig), (old)); \ 3088 } while (0) 3089 3090 void 3091 restart_daemon() 3092 { 3093 bool drop; 3094 int save_errno; 3095 char *reason; 3096 sigfunc_t ignore, oalrm, ousr1; 3097 extern int DtableSize; 3098 3099 /* clear the events to turn off SIGALRMs */ 3100 sm_clear_events(); 3101 sm_allsignals(true); 3102 3103 reason = RestartRequest; 3104 RestartRequest = NULL; 3105 PendingSignal = 0; 3106 3107 if (SaveArgv[0][0] != '/') 3108 { 3109 if (LogLevel > 3) 3110 sm_syslog(LOG_INFO, NOQID, 3111 "could not restart: need full path"); 3112 finis(false, true, EX_OSFILE); 3113 /* NOTREACHED */ 3114 } 3115 if (LogLevel > 3) 3116 sm_syslog(LOG_INFO, NOQID, "restarting %s due to %s", 3117 SaveArgv[0], 3118 reason == NULL ? "implicit call" : reason); 3119 3120 closecontrolsocket(true); 3121 #if SM_CONF_SHM 3122 cleanup_shm(DaemonPid == getpid()); 3123 #endif /* SM_CONF_SHM */ 3124 3125 /* close locked pid file */ 3126 close_sendmail_pid(); 3127 3128 /* 3129 ** Want to drop to the user who started the process in all cases 3130 ** *but* when running as "smmsp" for the clientmqueue queue run 3131 ** daemon. In that case, UseMSP will be true, RunAsUid should not 3132 ** be root, and RealUid should be either 0 or RunAsUid. 3133 */ 3134 3135 drop = !(UseMSP && RunAsUid != 0 && 3136 (RealUid == 0 || RealUid == RunAsUid)); 3137 3138 if (drop_privileges(drop) != EX_OK) 3139 { 3140 if (LogLevel > 0) 3141 sm_syslog(LOG_ALERT, NOQID, 3142 "could not drop privileges: %s", 3143 sm_errstring(errno)); 3144 finis(false, true, EX_OSERR); 3145 /* NOTREACHED */ 3146 } 3147 3148 sm_close_on_exec(STDERR_FILENO + 1, DtableSize); 3149 3150 /* 3151 ** Need to allow signals before execve() to make them "harmless". 3152 ** However, the default action can be "terminate", so it isn't 3153 ** really harmless. Setting signals to IGN will cause them to be 3154 ** ignored in the new process to, so that isn't a good alternative. 3155 */ 3156 3157 SM_NOOP_SIGNAL(SIGALRM, oalrm); 3158 SM_NOOP_SIGNAL(SIGCHLD, ignore); 3159 SM_NOOP_SIGNAL(SIGHUP, ignore); 3160 SM_NOOP_SIGNAL(SIGINT, ignore); 3161 SM_NOOP_SIGNAL(SIGPIPE, ignore); 3162 SM_NOOP_SIGNAL(SIGTERM, ignore); 3163 #ifdef SIGUSR1 3164 SM_NOOP_SIGNAL(SIGUSR1, ousr1); 3165 #endif /* SIGUSR1 */ 3166 3167 /* Turn back on signals */ 3168 sm_allsignals(false); 3169 3170 (void) execve(SaveArgv[0], (ARGV_T) SaveArgv, (ARGV_T) ExternalEnviron); 3171 save_errno = errno; 3172 3173 /* block signals again and restore needed signals */ 3174 sm_allsignals(true); 3175 3176 /* For finis() events */ 3177 (void) sm_signal(SIGALRM, oalrm); 3178 3179 #ifdef SIGUSR1 3180 /* For debugging finis() */ 3181 (void) sm_signal(SIGUSR1, ousr1); 3182 #endif /* SIGUSR1 */ 3183 3184 errno = save_errno; 3185 if (LogLevel > 0) 3186 sm_syslog(LOG_ALERT, NOQID, "could not exec %s: %s", 3187 SaveArgv[0], sm_errstring(errno)); 3188 finis(false, true, EX_OSFILE); 3189 /* NOTREACHED */ 3190 } 3191 /* 3192 ** MYHOSTNAME -- return the name of this host. 3193 ** 3194 ** Parameters: 3195 ** hostbuf -- a place to return the name of this host. 3196 ** size -- the size of hostbuf. 3197 ** 3198 ** Returns: 3199 ** A list of aliases for this host. 3200 ** 3201 ** Side Effects: 3202 ** Adds numeric codes to $=w. 3203 */ 3204 3205 struct hostent * 3206 myhostname(hostbuf, size) 3207 char hostbuf[]; 3208 int size; 3209 { 3210 register struct hostent *hp; 3211 3212 if (gethostname(hostbuf, size) < 0 || hostbuf[0] == '\0') 3213 (void) sm_strlcpy(hostbuf, "localhost", size); 3214 hp = sm_gethostbyname(hostbuf, InetMode); 3215 #if NETINET && NETINET6 3216 if (hp == NULL && InetMode == AF_INET6) 3217 { 3218 /* 3219 ** It's possible that this IPv6 enabled machine doesn't 3220 ** actually have any IPv6 interfaces and, therefore, no 3221 ** IPv6 addresses. Fall back to AF_INET. 3222 */ 3223 3224 hp = sm_gethostbyname(hostbuf, AF_INET); 3225 } 3226 #endif /* NETINET && NETINET6 */ 3227 if (hp == NULL) 3228 return NULL; 3229 if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL) 3230 (void) cleanstrcpy(hostbuf, hp->h_name, size); 3231 3232 #if NETINFO 3233 if (strchr(hostbuf, '.') == NULL) 3234 { 3235 char *domainname; 3236 3237 domainname = ni_propval("/locations", NULL, "resolver", 3238 "domain", '\0'); 3239 if (domainname != NULL && 3240 strlen(domainname) + strlen(hostbuf) + 1 < size) 3241 (void) sm_strlcat2(hostbuf, ".", domainname, size); 3242 } 3243 #endif /* NETINFO */ 3244 3245 /* 3246 ** If there is still no dot in the name, try looking for a 3247 ** dotted alias. 3248 */ 3249 3250 if (strchr(hostbuf, '.') == NULL) 3251 { 3252 char **ha; 3253 3254 for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++) 3255 { 3256 if (strchr(*ha, '.') != NULL) 3257 { 3258 (void) cleanstrcpy(hostbuf, *ha, size - 1); 3259 hostbuf[size - 1] = '\0'; 3260 break; 3261 } 3262 } 3263 } 3264 3265 /* 3266 ** If _still_ no dot, wait for a while and try again -- it is 3267 ** possible that some service is starting up. This can result 3268 ** in excessive delays if the system is badly configured, but 3269 ** there really isn't a way around that, particularly given that 3270 ** the config file hasn't been read at this point. 3271 ** All in all, a bit of a mess. 3272 */ 3273 3274 if (strchr(hostbuf, '.') == NULL && 3275 !getcanonname(hostbuf, size, true, NULL)) 3276 { 3277 sm_syslog(LOG_CRIT, NOQID, 3278 "My unqualified host name (%s) unknown; sleeping for retry", 3279 hostbuf); 3280 message("My unqualified host name (%s) unknown; sleeping for retry", 3281 hostbuf); 3282 (void) sleep(60); 3283 if (!getcanonname(hostbuf, size, true, NULL)) 3284 { 3285 sm_syslog(LOG_ALERT, NOQID, 3286 "unable to qualify my own domain name (%s) -- using short name", 3287 hostbuf); 3288 message("WARNING: unable to qualify my own domain name (%s) -- using short name", 3289 hostbuf); 3290 } 3291 } 3292 return hp; 3293 } 3294 /* 3295 ** ADDRCMP -- compare two host addresses 3296 ** 3297 ** Parameters: 3298 ** hp -- hostent structure for the first address 3299 ** ha -- actual first address 3300 ** sa -- second address 3301 ** 3302 ** Returns: 3303 ** 0 -- if ha and sa match 3304 ** else -- they don't match 3305 */ 3306 3307 static int 3308 addrcmp(hp, ha, sa) 3309 struct hostent *hp; 3310 char *ha; 3311 SOCKADDR *sa; 3312 { 3313 #if NETINET6 3314 unsigned char *a; 3315 #endif /* NETINET6 */ 3316 3317 switch (sa->sa.sa_family) 3318 { 3319 #if NETINET 3320 case AF_INET: 3321 if (hp->h_addrtype == AF_INET) 3322 return memcmp(ha, (char *) &sa->sin.sin_addr, INADDRSZ); 3323 break; 3324 #endif /* NETINET */ 3325 3326 #if NETINET6 3327 case AF_INET6: 3328 a = (unsigned char *) &sa->sin6.sin6_addr; 3329 3330 /* Straight binary comparison */ 3331 if (hp->h_addrtype == AF_INET6) 3332 return memcmp(ha, a, IN6ADDRSZ); 3333 3334 /* If IPv4-mapped IPv6 address, compare the IPv4 section */ 3335 if (hp->h_addrtype == AF_INET && 3336 IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr)) 3337 return memcmp(a + IN6ADDRSZ - INADDRSZ, ha, INADDRSZ); 3338 break; 3339 #endif /* NETINET6 */ 3340 } 3341 return -1; 3342 } 3343 /* 3344 ** GETAUTHINFO -- get the real host name associated with a file descriptor 3345 ** 3346 ** Uses RFC1413 protocol to try to get info from the other end. 3347 ** 3348 ** Parameters: 3349 ** fd -- the descriptor 3350 ** may_be_forged -- an outage that is set to true if the 3351 ** forward lookup of RealHostName does not match 3352 ** RealHostAddr; set to false if they do match. 3353 ** 3354 ** Returns: 3355 ** The user@host information associated with this descriptor. 3356 */ 3357 3358 static jmp_buf CtxAuthTimeout; 3359 3360 static void 3361 authtimeout(ignore) 3362 int ignore; 3363 { 3364 /* 3365 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 3366 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 3367 ** DOING. 3368 */ 3369 3370 errno = ETIMEDOUT; 3371 longjmp(CtxAuthTimeout, 1); 3372 } 3373 3374 char * 3375 getauthinfo(fd, may_be_forged) 3376 int fd; 3377 bool *may_be_forged; 3378 { 3379 unsigned short SM_NONVOLATILE port = 0; 3380 SOCKADDR_LEN_T falen; 3381 register char *volatile p = NULL; 3382 SOCKADDR la; 3383 SOCKADDR_LEN_T lalen; 3384 #ifndef NO_GETSERVBYNAME 3385 register struct servent *sp; 3386 # if NETINET 3387 static unsigned short port4 = 0; 3388 # endif /* NETINET */ 3389 # if NETINET6 3390 static unsigned short port6 = 0; 3391 # endif /* NETINET6 */ 3392 #endif /* ! NO_GETSERVBYNAME */ 3393 volatile int s; 3394 int i = 0; 3395 size_t len; 3396 SM_EVENT *ev; 3397 int nleft; 3398 struct hostent *hp; 3399 char *ostype = NULL; 3400 char **ha; 3401 char ibuf[MAXNAME + 1]; 3402 static char hbuf[MAXNAME + MAXAUTHINFO + 11]; 3403 3404 *may_be_forged = false; 3405 falen = sizeof(RealHostAddr); 3406 if (isatty(fd) || (i = getpeername(fd, &RealHostAddr.sa, &falen)) < 0 || 3407 falen <= 0 || RealHostAddr.sa.sa_family == 0) 3408 { 3409 if (i < 0) 3410 { 3411 /* 3412 ** ENOTSOCK is OK: bail on anything else, but reset 3413 ** errno in this case, so a mis-report doesn't 3414 ** happen later. 3415 */ 3416 3417 if (errno != ENOTSOCK) 3418 return NULL; 3419 errno = 0; 3420 } 3421 (void) sm_strlcpyn(hbuf, sizeof(hbuf), 2, RealUserName, 3422 "@localhost"); 3423 if (tTd(9, 1)) 3424 sm_dprintf("getauthinfo: %s\n", hbuf); 3425 return hbuf; 3426 } 3427 3428 if (RealHostName == NULL) 3429 { 3430 /* translate that to a host name */ 3431 RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 3432 if (strlen(RealHostName) > MAXNAME) 3433 RealHostName[MAXNAME] = '\0'; /* XXX - 1 ? */ 3434 } 3435 3436 /* cross check RealHostName with forward DNS lookup */ 3437 if (anynet_ntoa(&RealHostAddr)[0] != '[' && 3438 RealHostName[0] != '[') 3439 { 3440 int family; 3441 3442 family = RealHostAddr.sa.sa_family; 3443 #if NETINET6 && NEEDSGETIPNODE 3444 /* 3445 ** If RealHostAddr is an IPv6 connection with an 3446 ** IPv4-mapped address, we need RealHostName's IPv4 3447 ** address(es) for addrcmp() to compare against 3448 ** RealHostAddr. 3449 ** 3450 ** Actually, we only need to do this for systems 3451 ** which NEEDSGETIPNODE since the real getipnodebyname() 3452 ** already does V4MAPPED address via the AI_V4MAPPEDCFG 3453 ** flag. A better fix to this problem is to add this 3454 ** functionality to our stub getipnodebyname(). 3455 */ 3456 3457 if (family == AF_INET6 && 3458 IN6_IS_ADDR_V4MAPPED(&RealHostAddr.sin6.sin6_addr)) 3459 family = AF_INET; 3460 #endif /* NETINET6 && NEEDSGETIPNODE */ 3461 3462 /* try to match the reverse against the forward lookup */ 3463 hp = sm_gethostbyname(RealHostName, family); 3464 if (hp == NULL) 3465 { 3466 /* XXX: Could be a temporary error on forward lookup */ 3467 *may_be_forged = true; 3468 } 3469 else 3470 { 3471 for (ha = hp->h_addr_list; *ha != NULL; ha++) 3472 { 3473 if (addrcmp(hp, *ha, &RealHostAddr) == 0) 3474 break; 3475 } 3476 *may_be_forged = *ha == NULL; 3477 #if NETINET6 3478 freehostent(hp); 3479 hp = NULL; 3480 #endif /* NETINET6 */ 3481 } 3482 } 3483 3484 if (TimeOuts.to_ident == 0) 3485 goto noident; 3486 3487 lalen = sizeof(la); 3488 switch (RealHostAddr.sa.sa_family) 3489 { 3490 #if NETINET 3491 case AF_INET: 3492 if (getsockname(fd, &la.sa, &lalen) < 0 || 3493 lalen <= 0 || 3494 la.sa.sa_family != AF_INET) 3495 { 3496 /* no ident info */ 3497 goto noident; 3498 } 3499 port = RealHostAddr.sin.sin_port; 3500 3501 /* create ident query */ 3502 (void) sm_snprintf(ibuf, sizeof(ibuf), "%d,%d\r\n", 3503 ntohs(RealHostAddr.sin.sin_port), 3504 ntohs(la.sin.sin_port)); 3505 3506 /* create local address */ 3507 la.sin.sin_port = 0; 3508 3509 /* create foreign address */ 3510 # ifdef NO_GETSERVBYNAME 3511 RealHostAddr.sin.sin_port = htons(113); 3512 # else /* NO_GETSERVBYNAME */ 3513 3514 /* 3515 ** getservbyname() consumes about 5% of the time 3516 ** when receiving a small message (almost all of the time 3517 ** spent in this routine). 3518 ** Hence we store the port in a static variable 3519 ** to save this time. 3520 ** The portnumber shouldn't change very often... 3521 ** This code makes the assumption that the port number 3522 ** is not 0. 3523 */ 3524 3525 if (port4 == 0) 3526 { 3527 sp = getservbyname("auth", "tcp"); 3528 if (sp != NULL) 3529 port4 = sp->s_port; 3530 else 3531 port4 = htons(113); 3532 } 3533 RealHostAddr.sin.sin_port = port4; 3534 break; 3535 # endif /* NO_GETSERVBYNAME */ 3536 #endif /* NETINET */ 3537 3538 #if NETINET6 3539 case AF_INET6: 3540 if (getsockname(fd, &la.sa, &lalen) < 0 || 3541 lalen <= 0 || 3542 la.sa.sa_family != AF_INET6) 3543 { 3544 /* no ident info */ 3545 goto noident; 3546 } 3547 port = RealHostAddr.sin6.sin6_port; 3548 3549 /* create ident query */ 3550 (void) sm_snprintf(ibuf, sizeof(ibuf), "%d,%d\r\n", 3551 ntohs(RealHostAddr.sin6.sin6_port), 3552 ntohs(la.sin6.sin6_port)); 3553 3554 /* create local address */ 3555 la.sin6.sin6_port = 0; 3556 3557 /* create foreign address */ 3558 # ifdef NO_GETSERVBYNAME 3559 RealHostAddr.sin6.sin6_port = htons(113); 3560 # else /* NO_GETSERVBYNAME */ 3561 if (port6 == 0) 3562 { 3563 sp = getservbyname("auth", "tcp"); 3564 if (sp != NULL) 3565 port6 = sp->s_port; 3566 else 3567 port6 = htons(113); 3568 } 3569 RealHostAddr.sin6.sin6_port = port6; 3570 break; 3571 # endif /* NO_GETSERVBYNAME */ 3572 #endif /* NETINET6 */ 3573 default: 3574 /* no ident info */ 3575 goto noident; 3576 } 3577 3578 s = -1; 3579 if (setjmp(CtxAuthTimeout) != 0) 3580 { 3581 if (s >= 0) 3582 (void) close(s); 3583 goto noident; 3584 } 3585 3586 /* put a timeout around the whole thing */ 3587 ev = sm_setevent(TimeOuts.to_ident, authtimeout, 0); 3588 3589 /* connect to foreign IDENT server using same address as SMTP socket */ 3590 s = socket(la.sa.sa_family, SOCK_STREAM, 0); 3591 if (s < 0) 3592 { 3593 sm_clrevent(ev); 3594 goto noident; 3595 } 3596 if (bind(s, &la.sa, lalen) < 0 || 3597 connect(s, &RealHostAddr.sa, lalen) < 0) 3598 goto closeident; 3599 3600 if (tTd(9, 10)) 3601 sm_dprintf("getauthinfo: sent %s", ibuf); 3602 3603 /* send query */ 3604 if (write(s, ibuf, strlen(ibuf)) < 0) 3605 goto closeident; 3606 3607 /* get result */ 3608 p = &ibuf[0]; 3609 nleft = sizeof(ibuf) - 1; 3610 while ((i = read(s, p, nleft)) > 0) 3611 { 3612 char *s; 3613 3614 p += i; 3615 nleft -= i; 3616 *p = '\0'; 3617 if ((s = strchr(ibuf, '\n')) != NULL) 3618 { 3619 if (p > s + 1) 3620 { 3621 p = s + 1; 3622 *p = '\0'; 3623 } 3624 break; 3625 } 3626 if (nleft <= 0) 3627 break; 3628 } 3629 (void) close(s); 3630 sm_clrevent(ev); 3631 if (i < 0 || p == &ibuf[0]) 3632 goto noident; 3633 3634 if (p >= &ibuf[2] && *--p == '\n' && *--p == '\r') 3635 p--; 3636 *++p = '\0'; 3637 3638 if (tTd(9, 3)) 3639 sm_dprintf("getauthinfo: got %s\n", ibuf); 3640 3641 /* parse result */ 3642 p = strchr(ibuf, ':'); 3643 if (p == NULL) 3644 { 3645 /* malformed response */ 3646 goto noident; 3647 } 3648 while (isascii(*++p) && isspace(*p)) 3649 continue; 3650 if (sm_strncasecmp(p, "userid", 6) != 0) 3651 { 3652 /* presumably an error string */ 3653 goto noident; 3654 } 3655 p += 6; 3656 while (isascii(*p) && isspace(*p)) 3657 p++; 3658 if (*p++ != ':') 3659 { 3660 /* either useridxx or malformed response */ 3661 goto noident; 3662 } 3663 3664 /* p now points to the OSTYPE field */ 3665 while (isascii(*p) && isspace(*p)) 3666 p++; 3667 ostype = p; 3668 p = strchr(p, ':'); 3669 if (p == NULL) 3670 { 3671 /* malformed response */ 3672 goto noident; 3673 } 3674 else 3675 { 3676 char *charset; 3677 3678 *p = '\0'; 3679 charset = strchr(ostype, ','); 3680 if (charset != NULL) 3681 *charset = '\0'; 3682 } 3683 3684 /* 1413 says don't do this -- but it's broken otherwise */ 3685 while (isascii(*++p) && isspace(*p)) 3686 continue; 3687 3688 /* p now points to the authenticated name -- copy carefully */ 3689 if (sm_strncasecmp(ostype, "other", 5) == 0 && 3690 (ostype[5] == ' ' || ostype[5] == '\0')) 3691 { 3692 (void) sm_strlcpy(hbuf, "IDENT:", sizeof(hbuf)); 3693 cleanstrcpy(&hbuf[6], p, MAXAUTHINFO); 3694 } 3695 else 3696 cleanstrcpy(hbuf, p, MAXAUTHINFO); 3697 len = strlen(hbuf); 3698 (void) sm_strlcpyn(&hbuf[len], sizeof(hbuf) - len, 2, "@", 3699 RealHostName == NULL ? "localhost" : RealHostName); 3700 goto postident; 3701 3702 closeident: 3703 (void) close(s); 3704 sm_clrevent(ev); 3705 3706 noident: 3707 /* put back the original incoming port */ 3708 switch (RealHostAddr.sa.sa_family) 3709 { 3710 #if NETINET 3711 case AF_INET: 3712 if (port > 0) 3713 RealHostAddr.sin.sin_port = port; 3714 break; 3715 #endif /* NETINET */ 3716 3717 #if NETINET6 3718 case AF_INET6: 3719 if (port > 0) 3720 RealHostAddr.sin6.sin6_port = port; 3721 break; 3722 #endif /* NETINET6 */ 3723 } 3724 3725 if (RealHostName == NULL) 3726 { 3727 if (tTd(9, 1)) 3728 sm_dprintf("getauthinfo: NULL\n"); 3729 return NULL; 3730 } 3731 (void) sm_strlcpy(hbuf, RealHostName, sizeof(hbuf)); 3732 3733 postident: 3734 #if IP_SRCROUTE 3735 # ifndef GET_IPOPT_DST 3736 # define GET_IPOPT_DST(dst) (dst) 3737 # endif /* ! GET_IPOPT_DST */ 3738 /* 3739 ** Extract IP source routing information. 3740 ** 3741 ** Format of output for a connection from site a through b 3742 ** through c to d: 3743 ** loose: @site-c@site-b:site-a 3744 ** strict: !@site-c@site-b:site-a 3745 ** 3746 ** o - pointer within ipopt_list structure. 3747 ** q - pointer within ls/ss rr route data 3748 ** p - pointer to hbuf 3749 */ 3750 3751 if (RealHostAddr.sa.sa_family == AF_INET) 3752 { 3753 SOCKOPT_LEN_T ipoptlen; 3754 int j; 3755 unsigned char *q; 3756 unsigned char *o; 3757 int l; 3758 struct IPOPTION ipopt; 3759 3760 ipoptlen = sizeof(ipopt); 3761 if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS, 3762 (char *) &ipopt, &ipoptlen) < 0) 3763 goto noipsr; 3764 if (ipoptlen == 0) 3765 goto noipsr; 3766 o = (unsigned char *) ipopt.IP_LIST; 3767 while (o != NULL && o < (unsigned char *) &ipopt + ipoptlen) 3768 { 3769 switch (*o) 3770 { 3771 case IPOPT_EOL: 3772 o = NULL; 3773 break; 3774 3775 case IPOPT_NOP: 3776 o++; 3777 break; 3778 3779 case IPOPT_SSRR: 3780 case IPOPT_LSRR: 3781 /* 3782 ** Source routing. 3783 ** o[0] is the option type (loose/strict). 3784 ** o[1] is the length of this option, 3785 ** including option type and 3786 ** length. 3787 ** o[2] is the pointer into the route 3788 ** data. 3789 ** o[3] begins the route data. 3790 */ 3791 3792 p = &hbuf[strlen(hbuf)]; 3793 l = sizeof(hbuf) - (hbuf - p) - 6; 3794 (void) sm_snprintf(p, SPACELEFT(hbuf, p), 3795 " [%s@%.*s", 3796 *o == IPOPT_SSRR ? "!" : "", 3797 l > 240 ? 120 : l / 2, 3798 inet_ntoa(GET_IPOPT_DST(ipopt.IP_DST))); 3799 i = strlen(p); 3800 p += i; 3801 l -= strlen(p); 3802 3803 j = o[1] / sizeof(struct in_addr) - 1; 3804 3805 /* q skips length and router pointer to data */ 3806 q = &o[3]; 3807 for ( ; j >= 0; j--) 3808 { 3809 struct in_addr addr; 3810 3811 memcpy(&addr, q, sizeof(addr)); 3812 (void) sm_snprintf(p, 3813 SPACELEFT(hbuf, p), 3814 "%c%.*s", 3815 j != 0 ? '@' : ':', 3816 l > 240 ? 120 : 3817 j == 0 ? l : l / 2, 3818 inet_ntoa(addr)); 3819 i = strlen(p); 3820 p += i; 3821 l -= i + 1; 3822 q += sizeof(struct in_addr); 3823 } 3824 o += o[1]; 3825 break; 3826 3827 default: 3828 /* Skip over option */ 3829 o += o[1]; 3830 break; 3831 } 3832 } 3833 (void) sm_snprintf(p, SPACELEFT(hbuf, p), "]"); 3834 goto postipsr; 3835 } 3836 3837 noipsr: 3838 #endif /* IP_SRCROUTE */ 3839 if (RealHostName != NULL && RealHostName[0] != '[') 3840 { 3841 p = &hbuf[strlen(hbuf)]; 3842 (void) sm_snprintf(p, SPACELEFT(hbuf, p), " [%.100s]", 3843 anynet_ntoa(&RealHostAddr)); 3844 } 3845 if (*may_be_forged) 3846 { 3847 p = &hbuf[strlen(hbuf)]; 3848 (void) sm_strlcpy(p, " (may be forged)", SPACELEFT(hbuf, p)); 3849 macdefine(&BlankEnvelope.e_macro, A_PERM, 3850 macid("{client_resolve}"), "FORGED"); 3851 } 3852 3853 #if IP_SRCROUTE 3854 postipsr: 3855 #endif /* IP_SRCROUTE */ 3856 3857 /* put back the original incoming port */ 3858 switch (RealHostAddr.sa.sa_family) 3859 { 3860 #if NETINET 3861 case AF_INET: 3862 if (port > 0) 3863 RealHostAddr.sin.sin_port = port; 3864 break; 3865 #endif /* NETINET */ 3866 3867 #if NETINET6 3868 case AF_INET6: 3869 if (port > 0) 3870 RealHostAddr.sin6.sin6_port = port; 3871 break; 3872 #endif /* NETINET6 */ 3873 } 3874 3875 if (tTd(9, 1)) 3876 sm_dprintf("getauthinfo: %s\n", hbuf); 3877 return hbuf; 3878 } 3879 /* 3880 ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 3881 ** 3882 ** Parameters: 3883 ** map -- a pointer to this map. 3884 ** name -- the (presumably unqualified) hostname. 3885 ** av -- unused -- for compatibility with other mapping 3886 ** functions. 3887 ** statp -- an exit status (out parameter) -- set to 3888 ** EX_TEMPFAIL if the name server is unavailable. 3889 ** 3890 ** Returns: 3891 ** The mapping, if found. 3892 ** NULL if no mapping found. 3893 ** 3894 ** Side Effects: 3895 ** Looks up the host specified in hbuf. If it is not 3896 ** the canonical name for that host, return the canonical 3897 ** name (unless MF_MATCHONLY is set, which will cause the 3898 ** status only to be returned). 3899 */ 3900 3901 char * 3902 host_map_lookup(map, name, av, statp) 3903 MAP *map; 3904 char *name; 3905 char **av; 3906 int *statp; 3907 { 3908 register struct hostent *hp; 3909 #if NETINET 3910 struct in_addr in_addr; 3911 #endif /* NETINET */ 3912 #if NETINET6 3913 struct in6_addr in6_addr; 3914 #endif /* NETINET6 */ 3915 char *cp, *ans = NULL; 3916 register STAB *s; 3917 time_t now; 3918 #if NAMED_BIND 3919 time_t SM_NONVOLATILE retrans = 0; 3920 int SM_NONVOLATILE retry = 0; 3921 #endif /* NAMED_BIND */ 3922 char hbuf[MAXNAME + 1]; 3923 3924 /* 3925 ** See if we have already looked up this name. If so, just 3926 ** return it (unless expired). 3927 */ 3928 3929 now = curtime(); 3930 s = stab(name, ST_NAMECANON, ST_ENTER); 3931 if (bitset(NCF_VALID, s->s_namecanon.nc_flags) && 3932 s->s_namecanon.nc_exp >= now) 3933 { 3934 if (tTd(9, 1)) 3935 sm_dprintf("host_map_lookup(%s) => CACHE %s\n", 3936 name, 3937 s->s_namecanon.nc_cname == NULL 3938 ? "NULL" 3939 : s->s_namecanon.nc_cname); 3940 errno = s->s_namecanon.nc_errno; 3941 SM_SET_H_ERRNO(s->s_namecanon.nc_herrno); 3942 *statp = s->s_namecanon.nc_stat; 3943 if (*statp == EX_TEMPFAIL) 3944 { 3945 CurEnv->e_status = "4.4.3"; 3946 message("851 %s: Name server timeout", 3947 shortenstring(name, 33)); 3948 } 3949 if (*statp != EX_OK) 3950 return NULL; 3951 if (s->s_namecanon.nc_cname == NULL) 3952 { 3953 syserr("host_map_lookup(%s): bogus NULL cache entry, errno=%d, h_errno=%d", 3954 name, 3955 s->s_namecanon.nc_errno, 3956 s->s_namecanon.nc_herrno); 3957 return NULL; 3958 } 3959 if (bitset(MF_MATCHONLY, map->map_mflags)) 3960 cp = map_rewrite(map, name, strlen(name), NULL); 3961 else 3962 cp = map_rewrite(map, 3963 s->s_namecanon.nc_cname, 3964 strlen(s->s_namecanon.nc_cname), 3965 av); 3966 return cp; 3967 } 3968 3969 /* 3970 ** If we are running without a regular network connection (usually 3971 ** dial-on-demand) and we are just queueing, we want to avoid DNS 3972 ** lookups because those could try to connect to a server. 3973 */ 3974 3975 if (CurEnv->e_sendmode == SM_DEFER && 3976 bitset(MF_DEFER, map->map_mflags)) 3977 { 3978 if (tTd(9, 1)) 3979 sm_dprintf("host_map_lookup(%s) => DEFERRED\n", name); 3980 *statp = EX_TEMPFAIL; 3981 return NULL; 3982 } 3983 3984 /* 3985 ** If first character is a bracket, then it is an address 3986 ** lookup. Address is copied into a temporary buffer to 3987 ** strip the brackets and to preserve name if address is 3988 ** unknown. 3989 */ 3990 3991 if (tTd(9, 1)) 3992 sm_dprintf("host_map_lookup(%s) => ", name); 3993 #if NAMED_BIND 3994 if (map->map_timeout > 0) 3995 { 3996 retrans = _res.retrans; 3997 _res.retrans = map->map_timeout; 3998 } 3999 if (map->map_retry > 0) 4000 { 4001 retry = _res.retry; 4002 _res.retry = map->map_retry; 4003 } 4004 #endif /* NAMED_BIND */ 4005 4006 /* set default TTL */ 4007 s->s_namecanon.nc_exp = now + SM_DEFAULT_TTL; 4008 if (*name != '[') 4009 { 4010 int ttl; 4011 4012 (void) sm_strlcpy(hbuf, name, sizeof(hbuf)); 4013 if (getcanonname(hbuf, sizeof(hbuf) - 1, !HasWildcardMX, &ttl)) 4014 { 4015 ans = hbuf; 4016 if (ttl > 0) 4017 s->s_namecanon.nc_exp = now + SM_MIN(ttl, 4018 SM_DEFAULT_TTL); 4019 } 4020 } 4021 else 4022 { 4023 if ((cp = strchr(name, ']')) == NULL) 4024 { 4025 if (tTd(9, 1)) 4026 sm_dprintf("FAILED\n"); 4027 return NULL; 4028 } 4029 *cp = '\0'; 4030 4031 hp = NULL; 4032 #if NETINET 4033 if ((in_addr.s_addr = inet_addr(&name[1])) != INADDR_NONE) 4034 hp = sm_gethostbyaddr((char *)&in_addr, 4035 INADDRSZ, AF_INET); 4036 #endif /* NETINET */ 4037 #if NETINET6 4038 if (hp == NULL && 4039 anynet_pton(AF_INET6, &name[1], &in6_addr) == 1) 4040 hp = sm_gethostbyaddr((char *)&in6_addr, 4041 IN6ADDRSZ, AF_INET6); 4042 #endif /* NETINET6 */ 4043 *cp = ']'; 4044 4045 if (hp != NULL) 4046 { 4047 /* found a match -- copy out */ 4048 ans = denlstring((char *) hp->h_name, true, true); 4049 #if NETINET6 4050 if (ans == hp->h_name) 4051 { 4052 static char n[MAXNAME + 1]; 4053 4054 /* hp->h_name is about to disappear */ 4055 (void) sm_strlcpy(n, ans, sizeof(n)); 4056 ans = n; 4057 } 4058 freehostent(hp); 4059 hp = NULL; 4060 #endif /* NETINET6 */ 4061 } 4062 } 4063 #if NAMED_BIND 4064 if (map->map_timeout > 0) 4065 _res.retrans = retrans; 4066 if (map->map_retry > 0) 4067 _res.retry = retry; 4068 #endif /* NAMED_BIND */ 4069 4070 s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 4071 4072 /* Found an answer */ 4073 if (ans != NULL) 4074 { 4075 s->s_namecanon.nc_stat = *statp = EX_OK; 4076 if (s->s_namecanon.nc_cname != NULL) 4077 sm_free(s->s_namecanon.nc_cname); 4078 s->s_namecanon.nc_cname = sm_strdup_x(ans); 4079 if (bitset(MF_MATCHONLY, map->map_mflags)) 4080 cp = map_rewrite(map, name, strlen(name), NULL); 4081 else 4082 cp = map_rewrite(map, ans, strlen(ans), av); 4083 if (tTd(9, 1)) 4084 sm_dprintf("FOUND %s\n", ans); 4085 return cp; 4086 } 4087 4088 4089 /* No match found */ 4090 s->s_namecanon.nc_errno = errno; 4091 #if NAMED_BIND 4092 s->s_namecanon.nc_herrno = h_errno; 4093 if (tTd(9, 1)) 4094 sm_dprintf("FAIL (%d)\n", h_errno); 4095 switch (h_errno) 4096 { 4097 case TRY_AGAIN: 4098 if (UseNameServer) 4099 { 4100 CurEnv->e_status = "4.4.3"; 4101 message("851 %s: Name server timeout", 4102 shortenstring(name, 33)); 4103 } 4104 *statp = EX_TEMPFAIL; 4105 break; 4106 4107 case HOST_NOT_FOUND: 4108 case NO_DATA: 4109 *statp = EX_NOHOST; 4110 break; 4111 4112 case NO_RECOVERY: 4113 *statp = EX_SOFTWARE; 4114 break; 4115 4116 default: 4117 *statp = EX_UNAVAILABLE; 4118 break; 4119 } 4120 #else /* NAMED_BIND */ 4121 if (tTd(9, 1)) 4122 sm_dprintf("FAIL\n"); 4123 *statp = EX_NOHOST; 4124 #endif /* NAMED_BIND */ 4125 s->s_namecanon.nc_stat = *statp; 4126 return NULL; 4127 } 4128 /* 4129 ** HOST_MAP_INIT -- initialize host class structures 4130 ** 4131 ** Parameters: 4132 ** map -- a pointer to this map. 4133 ** args -- argument string. 4134 ** 4135 ** Returns: 4136 ** true. 4137 */ 4138 4139 bool 4140 host_map_init(map, args) 4141 MAP *map; 4142 char *args; 4143 { 4144 register char *p = args; 4145 4146 for (;;) 4147 { 4148 while (isascii(*p) && isspace(*p)) 4149 p++; 4150 if (*p != '-') 4151 break; 4152 switch (*++p) 4153 { 4154 case 'a': 4155 map->map_app = ++p; 4156 break; 4157 4158 case 'T': 4159 map->map_tapp = ++p; 4160 break; 4161 4162 case 'm': 4163 map->map_mflags |= MF_MATCHONLY; 4164 break; 4165 4166 case 't': 4167 map->map_mflags |= MF_NODEFER; 4168 break; 4169 4170 case 'S': /* only for consistency */ 4171 map->map_spacesub = *++p; 4172 break; 4173 4174 case 'D': 4175 map->map_mflags |= MF_DEFER; 4176 break; 4177 4178 case 'd': 4179 { 4180 char *h; 4181 4182 while (isascii(*++p) && isspace(*p)) 4183 continue; 4184 h = strchr(p, ' '); 4185 if (h != NULL) 4186 *h = '\0'; 4187 map->map_timeout = convtime(p, 's'); 4188 if (h != NULL) 4189 *h = ' '; 4190 } 4191 break; 4192 4193 case 'r': 4194 while (isascii(*++p) && isspace(*p)) 4195 continue; 4196 map->map_retry = atoi(p); 4197 break; 4198 } 4199 while (*p != '\0' && !(isascii(*p) && isspace(*p))) 4200 p++; 4201 if (*p != '\0') 4202 *p++ = '\0'; 4203 } 4204 if (map->map_app != NULL) 4205 map->map_app = newstr(map->map_app); 4206 if (map->map_tapp != NULL) 4207 map->map_tapp = newstr(map->map_tapp); 4208 return true; 4209 } 4210 4211 #if NETINET6 4212 /* 4213 ** ANYNET_NTOP -- convert an IPv6 network address to printable form. 4214 ** 4215 ** Parameters: 4216 ** s6a -- a pointer to an in6_addr structure. 4217 ** dst -- buffer to store result in 4218 ** dst_len -- size of dst buffer 4219 ** 4220 ** Returns: 4221 ** A printable version of that structure. 4222 */ 4223 4224 char * 4225 anynet_ntop(s6a, dst, dst_len) 4226 struct in6_addr *s6a; 4227 char *dst; 4228 size_t dst_len; 4229 { 4230 register char *ap; 4231 4232 if (IN6_IS_ADDR_V4MAPPED(s6a)) 4233 ap = (char *) inet_ntop(AF_INET, 4234 &s6a->s6_addr[IN6ADDRSZ - INADDRSZ], 4235 dst, dst_len); 4236 else 4237 { 4238 char *d; 4239 size_t sz; 4240 4241 /* Save pointer to beginning of string */ 4242 d = dst; 4243 4244 /* Add IPv6: protocol tag */ 4245 sz = sm_strlcpy(dst, "IPv6:", dst_len); 4246 if (sz >= dst_len) 4247 return NULL; 4248 dst += sz; 4249 dst_len -= sz; 4250 ap = (char *) inet_ntop(AF_INET6, s6a, dst, dst_len); 4251 4252 /* Restore pointer to beginning of string */ 4253 if (ap != NULL) 4254 ap = d; 4255 } 4256 return ap; 4257 } 4258 4259 /* 4260 ** ANYNET_PTON -- convert printed form to network address. 4261 ** 4262 ** Wrapper for inet_pton() which handles IPv6: labels. 4263 ** 4264 ** Parameters: 4265 ** family -- address family 4266 ** src -- string 4267 ** dst -- destination address structure 4268 ** 4269 ** Returns: 4270 ** 1 if the address was valid 4271 ** 0 if the address wasn't parseable 4272 ** -1 if error 4273 */ 4274 4275 int 4276 anynet_pton(family, src, dst) 4277 int family; 4278 const char *src; 4279 void *dst; 4280 { 4281 if (family == AF_INET6 && sm_strncasecmp(src, "IPv6:", 5) == 0) 4282 src += 5; 4283 return inet_pton(family, src, dst); 4284 } 4285 #endif /* NETINET6 */ 4286 /* 4287 ** ANYNET_NTOA -- convert a network address to printable form. 4288 ** 4289 ** Parameters: 4290 ** sap -- a pointer to a sockaddr structure. 4291 ** 4292 ** Returns: 4293 ** A printable version of that sockaddr. 4294 */ 4295 4296 #ifdef USE_SOCK_STREAM 4297 4298 # if NETLINK 4299 # include <net/if_dl.h> 4300 # endif /* NETLINK */ 4301 4302 char * 4303 anynet_ntoa(sap) 4304 register SOCKADDR *sap; 4305 { 4306 register char *bp; 4307 register char *ap; 4308 int l; 4309 static char buf[100]; 4310 4311 /* check for null/zero family */ 4312 if (sap == NULL) 4313 return "NULLADDR"; 4314 if (sap->sa.sa_family == 0) 4315 return "0"; 4316 4317 switch (sap->sa.sa_family) 4318 { 4319 # if NETUNIX 4320 case AF_UNIX: 4321 if (sap->sunix.sun_path[0] != '\0') 4322 (void) sm_snprintf(buf, sizeof(buf), "[UNIX: %.64s]", 4323 sap->sunix.sun_path); 4324 else 4325 (void) sm_strlcpy(buf, "[UNIX: localhost]", sizeof(buf)); 4326 return buf; 4327 # endif /* NETUNIX */ 4328 4329 # if NETINET 4330 case AF_INET: 4331 return (char *) inet_ntoa(sap->sin.sin_addr); 4332 # endif /* NETINET */ 4333 4334 # if NETINET6 4335 case AF_INET6: 4336 ap = anynet_ntop(&sap->sin6.sin6_addr, buf, sizeof(buf)); 4337 if (ap != NULL) 4338 return ap; 4339 break; 4340 # endif /* NETINET6 */ 4341 4342 # if NETLINK 4343 case AF_LINK: 4344 (void) sm_snprintf(buf, sizeof(buf), "[LINK: %s]", 4345 link_ntoa((struct sockaddr_dl *) &sap->sa)); 4346 return buf; 4347 # endif /* NETLINK */ 4348 default: 4349 /* this case is needed when nothing is #defined */ 4350 /* in order to keep the switch syntactically correct */ 4351 break; 4352 } 4353 4354 /* unknown family -- just dump bytes */ 4355 (void) sm_snprintf(buf, sizeof(buf), "Family %d: ", sap->sa.sa_family); 4356 bp = &buf[strlen(buf)]; 4357 ap = sap->sa.sa_data; 4358 for (l = sizeof(sap->sa.sa_data); --l >= 0; ) 4359 { 4360 (void) sm_snprintf(bp, SPACELEFT(buf, bp), "%02x:", 4361 *ap++ & 0377); 4362 bp += 3; 4363 } 4364 *--bp = '\0'; 4365 return buf; 4366 } 4367 /* 4368 ** HOSTNAMEBYANYADDR -- return name of host based on address 4369 ** 4370 ** Parameters: 4371 ** sap -- SOCKADDR pointer 4372 ** 4373 ** Returns: 4374 ** text representation of host name. 4375 ** 4376 ** Side Effects: 4377 ** none. 4378 */ 4379 4380 char * 4381 hostnamebyanyaddr(sap) 4382 register SOCKADDR *sap; 4383 { 4384 register struct hostent *hp; 4385 # if NAMED_BIND 4386 int saveretry; 4387 # endif /* NAMED_BIND */ 4388 # if NETINET6 4389 struct in6_addr in6_addr; 4390 # endif /* NETINET6 */ 4391 4392 # if NAMED_BIND 4393 /* shorten name server timeout to avoid higher level timeouts */ 4394 saveretry = _res.retry; 4395 if (_res.retry * _res.retrans > 20) 4396 _res.retry = 20 / _res.retrans; 4397 # endif /* NAMED_BIND */ 4398 4399 switch (sap->sa.sa_family) 4400 { 4401 # if NETINET 4402 case AF_INET: 4403 hp = sm_gethostbyaddr((char *) &sap->sin.sin_addr, 4404 INADDRSZ, AF_INET); 4405 break; 4406 # endif /* NETINET */ 4407 4408 # if NETINET6 4409 case AF_INET6: 4410 hp = sm_gethostbyaddr((char *) &sap->sin6.sin6_addr, 4411 IN6ADDRSZ, AF_INET6); 4412 break; 4413 # endif /* NETINET6 */ 4414 4415 # if NETISO 4416 case AF_ISO: 4417 hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr, 4418 sizeof(sap->siso.siso_addr), AF_ISO); 4419 break; 4420 # endif /* NETISO */ 4421 4422 # if NETUNIX 4423 case AF_UNIX: 4424 hp = NULL; 4425 break; 4426 # endif /* NETUNIX */ 4427 4428 default: 4429 hp = sm_gethostbyaddr(sap->sa.sa_data, sizeof(sap->sa.sa_data), 4430 sap->sa.sa_family); 4431 break; 4432 } 4433 4434 # if NAMED_BIND 4435 _res.retry = saveretry; 4436 # endif /* NAMED_BIND */ 4437 4438 # if NETINET || NETINET6 4439 if (hp != NULL && hp->h_name[0] != '[' 4440 # if NETINET6 4441 && inet_pton(AF_INET6, hp->h_name, &in6_addr) != 1 4442 # endif /* NETINET6 */ 4443 # if NETINET 4444 && inet_addr(hp->h_name) == INADDR_NONE 4445 # endif /* NETINET */ 4446 ) 4447 { 4448 char *name; 4449 4450 name = denlstring((char *) hp->h_name, true, true); 4451 # if NETINET6 4452 if (name == hp->h_name) 4453 { 4454 static char n[MAXNAME + 1]; 4455 4456 /* Copy the string, hp->h_name is about to disappear */ 4457 (void) sm_strlcpy(n, name, sizeof(n)); 4458 name = n; 4459 } 4460 freehostent(hp); 4461 # endif /* NETINET6 */ 4462 return name; 4463 } 4464 # endif /* NETINET || NETINET6 */ 4465 4466 # if NETINET6 4467 if (hp != NULL) 4468 { 4469 freehostent(hp); 4470 hp = NULL; 4471 } 4472 # endif /* NETINET6 */ 4473 4474 # if NETUNIX 4475 if (sap->sa.sa_family == AF_UNIX && sap->sunix.sun_path[0] == '\0') 4476 return "localhost"; 4477 # endif /* NETUNIX */ 4478 { 4479 static char buf[203]; 4480 4481 (void) sm_snprintf(buf, sizeof(buf), "[%.200s]", 4482 anynet_ntoa(sap)); 4483 return buf; 4484 } 4485 } 4486 #endif /* USE_SOCK_STREAM */ 4487