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