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