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