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