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